Blog Post

Rick Molloy: Actor-based Programming in C++ - Control Flow versus Data Flow

Sign in to queue

Description

Rick Molloy is back and he's got some code and coding techniques to share. Thank you Rick! This tutorial/example is done in C++, but the concepts span languages (actor-based, data flow style of programming)

Here, Rick explores converting a simple loop to a set of actors or agents that communicate via message passing.  In particular he looks at the difference between a "control flow" style implementation and a "data flow" style implementation. The actor based approach is great because it separates the guts of the work from the loop logic so code looks more like the flow charts we draw on our whiteboards.

But, there's some down sides with the control flow approach and implementing the data flow approach can be tricky.  So Rick wanted to walk through an example of both to help illustrate the differences.

The downside to the control flow approach comes in when you have lots of agents, there tends to be either a 1:1 coupling of threads to tasks OR the tasks start taking on more than one responsibility and become less manageable.

A data flow style approach helps with this, because it decouples the 1:1 thread to task relationship but it can be an awkward refactoring if you're not used to it, it takes more code, and there aren't many examples available to look at on the web so Rick wanted to share another one.

 Download the code for this demo (will work in VC++ 2010)

Embed

Download

Download this episode

The Discussion

  • User profile image
    ryanb

    The code download link is not working, and is in fact redirecting to a malware site.  Please fix.

     

  • User profile image
    Charles

    Fixed. Sorry about that!

  • User profile image
    Ryan Riley

    Thanks for fixing that, Charles.

  • User profile image
    ryanb

    Yes, much better now.  Thanks.

  • User profile image
    Benjamin Lindley

    Normally, I avoid macros like the plague. But that DEFINE_HAS_MEMBER is just too brilliant.

  • User profile image
    rickmolloy

    @Benjamin - multiple folks contributed to the concise DEFINE_HAS_MEMBER in the example, my original version was more verbose.

    In general I also try to avoid macros but I think there are a few really good use cases for them.  For me they involve things like converting class / variable names to strings (we see this a lot in debugging / tracing) or in cases where you want the name of something in a class (in a macro) to vary but not the structure.

    In C++11 I think template aliases will help with some places where folks are using macros now as will being able to allow constructors to call other constructors, but I don't think it will help in this instance because the preprocessor is converting the type to a string.

    The original DEFINE_HAS_MEMBER is part of the concrt sample pack in connect.h at http://code.msdn.com/concrtextrasAnd">http://code.msdn.com/concrtextras

    And Xiang Fan has a blog post on how to do this without decltype at:
    http://blogs.msdn.com/b/xiangfan/archive/2009/02/09/c-template-trick-detecting-the-existence-of-class-member-at-compile-time.aspx-Rick">http://blogs.msdn.com/b/xiangfan/archive/2009/02/09/c-template-trick-detecting-the-existence-of-class-member-at-compile-time.aspx

    -Rick

     

  • User profile image
    Glen

    Hi Rick

    Subtle. I initially wondered what the value/purpose was of such an at length discussion of what appears to a simple and unremarkable style of code. Especially if the transformed code might actually run slower on some machines.

    After more consideration though I am realising both that this style of code is quite profound such that it could eventually become quite the norm; and that your long focus on a simple example to demonstrate the core concepts being introduced was a good idea. So thanks, it hit the mark for me.

  • User profile image
    rab36

    Hi Rick,

    thanks a lot for this lecture on dataflow patterns. For me it was very interesting to see, that the equation 1 agent = 1 thread does not necessarly hold when using call, transform, etc. to implement the agent. This is good news, because that was one of my main concerns when thinking about using the asynchronous agents library.

    Bernd

     

  • User profile image
    rickmolloy

    @Glen. Thank you I'm glad this was useful.

    @Bernd.  Just confirming in concrt, the scheduler / resource manager control the number of threads. If you have 1000 calls and send 1000 messages to them there will be approximately 4 threads running at once on a 4-core processing those thousand messages until they are completed. You will in fact see more threads, but they are not usually usuall actively processing items, they're kept in reserve in case an API call is made that is considered 'blocking'. 

    'Agents' can hold onto a thread when they don't exit their run method in a short amount of time (as do all tasks), but there only a  few examples online showing folks how to do this.  In reality you may want to have a mix of 'control flow' and 'dataflow' agents in an application, it just depends on what you need.

  • User profile image
    AlessandroV

    Hi Rick,

    the lecture is very interesting and I tried to modify the sample code to the two kinds of agents but most of the time it doesn't work (it locks, or crashes with "pure virtual function call").

    What am I missing?

  • User profile image
    rickmolloy

    @AlessandroV - what are you trying to change?  There are several more samples on msdn here: http://msdn.microsoft.com/en-us/library/dd492627.aspx

Add Your 2 Cents