Archive

Author Archive

Acting In C++

May 21, 2015 2 comments

Because they’re a perfect fit for mega-core processors and they’re safer and more enjoyable to program than raw, multi-threaded, systems, I’ve been a fan of Actor-based concurrent systems ever since I experimented with Erlang and Akka (via its Java API). Thus, as a C++ programmer, I was excited to discover the “C++ Actor Framework” (CAF). Like the Akka toolkit/runtime, the CAF is based on the design of the longest living, proven, production-ready, pragmatic, actor-based, language that I know of – the venerable Erlang programming language.

Curious to check out the CAF, I downloaded, compiled, and installed the framework source code with nary a problem (on CentOS 7.0, GCC 4.8.2). I then built and ran the sample “Hello World” program presented in the user manual:

CAF HW

As you can see, the CAF depends on the use one of my favorite C++11 features – lambda functions – to implement actor behavior.

The logic in main() uses the CAF spawn() function to create two concurrently running, message-exchanging (messages of type std::string), actors named “mirror” and “hello_world“. During the spawning of the “hello_world” actor, the main() logic passes it a handle (via const actor&) to the previously created “mirror” actor so that “hello_world” can asynchronously communicate with “mirror” via message-passing. Then, much like the parent thread in a multi-threaded program “join()“s the threads it creates to wait for the threads to complete their work, the main() thread of control uses the CAF await_all_actors_done() function to do the same for the two actors it spawns.

When I ran the program as a local C++ application in the Eclipse IDE, here is the output that appeared in the console window:

CAF mirror

The figure below visually illustrates the exchange of messages between the program’s actors during runtime. Upon being created, the “hello_world” actor sends a text message (via sync_send()) containing “Hello World” as its payload to the previously spawned “mirror” actor. The “hello_world” actor then immediately chains the then() function to the call to synchronously await for the response message it expects back from the “mirror” actor. Note that a lambda function that will receive and print the response message string to the console (via the framework’s thread-safe aout object) is passed as an argument into the then() function.

CAF HW actors

Looking at the code for the “mirror” actor, we can deduce that when the framework spawns an instance of it, the framework gives the actor a handle to itself and the actor returns the behavior (again, in the form of a lambda function) that it wants the framework to invoke each time a message is sent to the actor. The “mirror” actor behavior: prints the received message to the console, tells the framework that it wants to terminate itself (via the call to quit()), and returns a mirrored translation of the input message to the framework for passage back to the sending actor (in this case, the “hello_world” actor).

Note that the application contains no explicit code for threads, tasks, mutexes, locks, atomics, condition variables, promises, futures, or thread-safe containers to futz with. The CAF framework hides all the underlying synchronization and message passing minutiae under the abstractions it provides so that the programmer can concentrate on the application domain functionality. Great stuff!

I modified the code slightly so that the application actors exchange user-defined message types instead of std::strings.

req-resp CAF

Here is the modified code:

struct ReqMessage {
  int32_t anInt32_t;
  double aDouble;
  string aString;
};

struct RespMessage {
  enum class AckNack{ACK, NACK};
  AckNack response;
};

void printMsg(event_based_actor* self, const ReqMessage& msg) {
  aout(self) << "anInt32_t = " << msg.anInt32_t << endl
             << "aDouble = " << msg.aDouble << endl
             << "aString = " << msg.aString << endl
             << endl;
}

void fillReqMessage(ReqMessage& msg) {
  msg.aDouble = 55.5;
  msg.anInt32_t = 22;
  msg.aString = "Bulldozer00 Rocks!";
}

behavior responder(event_based_actor* self) {
  // return the (initial) actor behavior
  return {
  // a handler for messages of type ReqMessage
  // and replies with a RespMessage
  [=](const ReqMessage& msg) -> RespMessage {
    // prints the content of ReqMessage via aout
    // (thread-safe cout wrapper)
    printMsg(self, msg);
    // terminates this actor *after* the return statement
    // ('become' a quitter, otherwise loops forever)
    self->quit();
    // reply with an "ACK"
    return RespMessage{RespMessage::AckNack::ACK};
  }};
}

void requester(event_based_actor* self, const actor& responder) {
  // create & send a ReqMessage to our buddy ...
  ReqMessage req{};
  fillReqMessage(req);
  self->sync_send(responder, req).then(
  // ... wait for a response ...
  [=](const RespMessage& resp) {
    // ... and print it
    RespMessage::AckNack payload{resp.response};
    string txt =
      (payload == RespMessage::AckNack::ACK) ? "ACK" : "NACK";
    aout(self) << txt << endl;
  });
}

int main() {
  // create a new actor that calls 'responder()'
  auto responder_actor = spawn(responder);
  // create another actor that calls 'requester(responder_actor)';
  spawn(requester, responder_actor);
  // wait until all other actors we have spawned are done
  await_all_actors_done();
  // run cleanup code before exiting main
  shutdown();
}

And here is the Eclipse console output:
req-resp CAF output

Categories: C++, C++11 Tags: , , ,

Whence Actors?


While sketching out the following drawing, I was thinking about the migration from sequential to concurrent programming driven by the rise of multicore machines. Can you find anything wrong with it?

Concurrency Abstractions

Right out of the box, C++ provided Objects (via classes) and procedures (via free standing functions). With C++11, standardized support for threads and tasks finally arrived to the language in library form. I can’t wait for Actors to appear in….. ?

cpp actors

Categories: C++11, C++14, C++17 Tags: , , ,

It’s All About That Jell


Agile, Traditional, Lean, Burndown Charts, Kanban Boards, Earned Value Management Metrics, Code Coverage, Static Code Analysis, Coaches, Consultants, Daily Standup Meetings, Weekly Sit Down Meetings, Periodic Program/Project Reviews. All the shit managers obsess over doesn’t matter. It’s all about that Jell, ’bout that jell, ’bout that jell.

Jellin

 

 

All About The Jell

VCID, ACID, SCID


First, we have VCID:

VCID

In VCID mode, we iteratively define, at a coarse level of granularity, what the Domain-Specific Architecture (DSA) is and what the revenue-generating portfolio of Apps that we’ll be developing are.

Next up, we have ACID:

ACID

In ACID mode, we’ll iteratively define, at at finer level of detail, what each of our Apps will do for our customers and the components that will comprise each App.

Then, we have SCID, where we iteratively cut real App & DSA code and implement per-App stories/use cases/functions:

SCID

But STOP! Unlike the previous paragraphs imply, the “CID”s shouldn’t be managed as a sequential, three step, waterfall execution from the abstract world of concepts to the real world of concrete code. If so, your work is perhaps doomed. The CIDs should inform each other. When work in one CID exposes an error(s) in another CID, a transition into the flawed CID state should be executed to repair the error(s).

CID STM

Managed correctly, your product development system becomes a dynamically executing, inter-coupled, set of operating states with error-correcting feedback loops that steer the system toward its goal of providing value to your customers and profits to your coffers.

CID Timeline

Nothing Is Unassailable


I recently posted a tidbit on Twitter which I thought was benignly unassailable:

Unassailable

Of course, Twitter being Twitter, I was wrong – and that’s one of the reasons why I love (and hate) Twitter. When your head gets too inflated, Twitter can deflate it as fast as a pin pops a balloon.

type_names

Too “Professional”

May 7, 2015 3 comments
Categories: miscellaneous Tags: ,

The Annihilation Of Conceptual Integrity


When a large group or committee is tasked with designing a complex system from scratch, or evolving an existing one, I always think of these timeless quotes from Fred Brooks:

“A design flows from a chief designer, supported by a design team, not partitioned among one.” – Fred Brooks

“The entire system also must have conceptual integrity, and that requires a system architect to design it all, from the top down.” – Fred Brooks

Who advocates … for the product itself—its conceptual integrity, its efficiency, its economy, its robustness? Often, no one.” – Fred Brooks

“A little retrospection shows that although many fine, useful software systems have been designed by committees and built as part of multi-part projects, those software systems that have excited passionate fans are those that are the products of one or a few designing minds, great designers.” – Fred Brooks

Note Fred’s correlation between “conceptual integrity” and the individual (or small group) for success.

C++ is a large, sprawling, complex, programming language. With the next language specification update due to be ratified by the ISO C++ committee in 2017, Bjarne Stroustrup (the original, one-man, creator and curator of C++) felt the need to publish a passionate plea admonishing the committee to “stop the insanity“: Thoughts About C++17.

No Longer Cpp

By reminding the committee members of the essence of what uniquely distinguishes C++ from its peers, Bjarne is warning against the danger of annihilating the language’s conceptual integrity. The center must hold!

 It seems to be a popular pastime to condemn C++ for being a filthy mess caused by rampant design-by-committee. This has been suggested repeatedly since before the committee was founded, but I feel it is now far worse. Adding a lot of unrelated features and library components will do much to add complexity to the language, making it scarier to both novices and “mainline programmers”. What I do not want to try to do:
• Turn C++ into a radically different language
• Turn parts of  C++ into a much higher-level language by providing a segregated sub-language
• Have C++ compete with every other language by adding as many as possible of their features
• Incrementally modify C++ to support a whole new “paradigm”
• Hamper C++’s use for the most demanding systems programming tasks
• Increase the complexity of C++ use for the 99% for the benefit of the 1% (us and our best friends).

Like all the other C++ committee members, Bjarne is a really, really, smart guy. For the decades that I’ve followed his efforts to evolve and improve the language, Bjarne has always expressed empathy for “the little people“; the 99% (of which I am a card-carrying member).

In a world in which the top 1% doesn’t seem to give a shit about the remaining 99%, it’s always refreshing to encounter a 1 percenter who cares deeply about the other 99 percenters. And THAT, my dear reader, is what has always endeared Mr. Bjarne Stroustrup to me.

Ninety Nine Pct

I am often asked – often by influential and/or famous people – if I am planning a D&E2 (The Design And Evolution Of C++ version 2). I’m not, I’m too busy using and improving C++. However, should I ever find it convenient to semi-retire, D&E2 would be a great project. However, I could do that if and only if I could honestly write it without condemning the language or my friends. We need to ship something we can be proud of and that we can articulate.

W00t! I didn’t know I was influential and/or famous: And In The Beginning.

Follow

Get every new post delivered to your Inbox.

Join 495 other followers

%d bloggers like this: