Going Deep

Expert to Expert: Inside Concurrent Basic (CB)

Download this episode

Download Video


"Concurrent Basic extends Visual Basic with stylish asynchronous concurrency constructs derived from the join calculus. Our design advances earlier MSRC work on Polyphonic C#, Comega and the Joins Library. Unlike its C# based predecessors, CB adopts a simple event-like syntax familiar to VB programmers, allows one to declare generic concurrency abstractions and provides more natural support for inheritance. CB also offers open extensibility based on custom attributes."

Code Sample:

Module Buffer
  Public Asynchronous Put(ByVal s As String)
  Public Synchronous Take() As String
  Private Function CaseTakeAndPut(ByVal s As String) As String  When Take, Put
     Return s
  End Function
End Module


OK. Sounds great. There are new keywords, Asynchronous and Synchronous. Conceptually, these are easy enough to understand. How do they work, exactly? What's the thinking behind the current design? Why was VB.NET chosen as the language to extend? Wouldn't any CLI language suffice? Who thought this up, anyway? What's the thinking behind the thinking?

Enter C9 celebrity host Erik Meijer, who leads yet another great conversation with fellow software experts Claudio Russo (MSR Researcher and co-creator of Concurrent Basic) and Lucian Wischik (software developer and current VB.NET Czar).

Obviously, we've been focusing a lot of attention of Concurrency and Parallelism over the past few years. We talk about the library versus language approach quite a bit. In this case, concurrency constructs have been baked into the language to form a different variant of VB, CB (Concurrent Basic). CB is a research project and therefore a research language. It has no ship vehicle and is not available for trial at this point. Microsoft makes no committment to shipping VB with these concurrency constructs built in. CB is a research language.  CB is being shown in action at this year's MSR TechFest. Be sure to check out Laura's coverage of TechFest 2009.



Available formats for this video:

Actual format may change based on video formats available and browser capability.

    The Discussion

    • mavstar001
      Interesting stuff.  I personally just switched languages from VB to C# in order to take advantage of the CCR and Yield.

      How different is this concept from the CCR with it's ports and yield statements? (beyond obvious syntax differences)
    • RoryBecker2
      Why use Function semantics to hook A and B to Wait..... Seems like a waste of code.... What else might we put in the function?

    • sylvan
      I don't understand why the "handler" has to be a separate function. Seems highly redundant. I mean look at the example, "CasTakeAndPut ... Take, Put". Why do we need a named function here? WHen else would it be called? Why not just do what Polyphonic C# did?

      Actually I don't mind separating the handler (Polyphonic C# did get pretty long function headers because you specified them all "in line" with the handler statement), actually, but I don't see why it needs to be named. Also, seems a bit weird how the inputs for the various channels gets mapped to the parameter list of the handler - if you have ten of them taking different numbers of argument (including zero) of different types, then what does the parameter list for your handler look like and how long does it take you to get that right on average? Why not something like:

      Asynchronous Put( ByVal s As String)
      Synchronous Take() As String

      When Put( ByVal s As String ), Take() As String
         return s
      End When

      This removes the rendundant function name (and Function keyword), as well as making it obvious where each parameter comes from. In fact, we may possibly omit the type in the "When" clause since it's already declared and just say "Put(s)"? So you'd basically specify all your channels up front first, giving the types and any other modifiers (like access), and then just a short and sweet "when" clause at the end. Seems pretty clean to me:

      Asynchronous Put( ByVal s As String)
      Synchronous Take() As String

      When Take, Put(s)
         return s
      End When

      I think this idea is very promising, but I do think the syntax here is unecessarily clumsy... Unless someone can explain why we need all that extra stuff? Caveat: The video broke about half way through for me so maybe there's a really good motivation for this later on?
    • Charles
      At what point did the video break for you?
    • sylvan
      Don't worry, it's not a problem on your end. I've had some codec issues here lately affecting all sorts of videos.
    • crusso


      I’m no expert on the CCR , but I believe a CCR port is equivalent to a CB asynchronous channels. As far as I know, the CCR  has no direct equivalent of synchronous channels. However, you can code up a synchronous channel  using a port that takes an additional response port on which to reply to a “synchronous” sender. The sender would pass a fresh port along with the original payload then wait (block) to receive a response. Indeed, in the original join calculus that underpins CB, all channels were asynchronous and a similar encoding was used to emulate synchronous sends. The advantage of directly supporting synchronous channels is that it avoids the additional protocol used by the encoding (which a user could get wrong, for instance,  by incorrectly sharing a reply port across two calls). The disadvantage is that it encourages the user to write blocking code with the potential for deadlock.


      Unlike CB,  the CCR encourages a completely asynchronous programming style but makes clever use of C#’s yield statements to let the user write asynchronous blocks of code in a sequential style, without having to explicitly CPS convert the sequential code. I think it’s a shame VB doesn’t have iterators  and hope iterators or more general coroutines are supported in future.


      F#’s asynchronous workflows are similar in this regard, but use a continuation monad instead of C#’s iterators to achieve fully composable asynchronous computations.  


    • crusso

      You can and typically do put non-trivial code in the body of a pattern.  The simple examples in the video were meant to illustrate the basic expressive power of CB patterns to express choice, join and forking operations.

      For example, the more realistic one-place-buffer has non-trivial function bodies:

      Public Class OnePlaceBuffer(Of T)
        Private Asynchronous Empty()
        Private Asynchronous Contains(ByVal t As T)
        Public Synchronous Put(ByVal t As T)
        Public Synchronous Take() As T
        Private Sub CasePutAndEmpty(ByVal t As T) When Put, Empty
        End Sub
        Private Function CaseTakeAndContains(ByVal t As T) As T When Take, Contains
          Return t
        End Function
        Public Sub New()
        End Sub
      End Class

      Have a look at the paper or slides on the concurrent basic site for more examples.

    • crusso

      In general,  the parameters to the pattern are the (ordered) concatenation of the parameters of the channels following [When] which is simple to specify but, as you rightly observed, easy to get wrong. So I agree with you that the syntax is a little clumsy and could be sugared to or even replaced by something more concise and less error prone. I had actually considered precisely the explicitly typed syntax you suggest - in fact, we already had this in Comega for purely asynchronous patterns. The even better implicitly typed variant make perfect sense, and is close to my ML heart, but is less in keeping with VB.


      Apart from implementation expediency, the main reason I opted for the explicit variant is that it is similar to the [Handles] syntax, makes it easy to override patterns in subclasses and to support recursion in the body of the handler as well as debugging and testing of patterns. Perhaps we should support the fully explicit syntax as well as sugar for the more concise, even implicitly-typed form that generates a private, non-recursive method. Heck, we could also just jettison the [Handles] analogy completely...


       Another thing one might consider adding is the ability to declare that a channel handles some events and (for symmetry) that an event is raised by some pattern.


      The main motivation for departing from the Polyphonic C# syntax was that decoupling channel and pattern declarations makes it easier to support inheritance and the addition of new patterns in subclasses.


      We’re definitely open to suggestions and very grateful for your feedback.

    • Stefan F.dot
      I'm working on a similar solution and have published a proposal
      see <http://threadsafeprogramming.blogspot.com>

      what do you think about it ?

      / Stefan
    • YuryS
      You may be interested also in MC# language (www.mcsharp.net),
      which has channels (and handlers) as first class tools.
    • ReCkeSs ROHIT

      Vedio dosent play

    Comments closed

    Comments have been closed since this content was published more than 30 days ago, but if you'd like to continue the conversation, please create a new thread in our Forums, or Contact Us and let us know.