Go
package main import "fmt" func main() { sayHello := make(chan string) sayWorld := make(chan string) quitter := make(chan string) go func() { for i := 0; i < 1000; i++ { fmt.Print("Hello ") sayWorld <- "Do it" <-sayHello } sayWorld <- "Quit" }() go func() { for { var reply string reply = <- sayWorld if (reply == "Quit") { break } fmt.Print("World!\n") sayHello <- "Do it" } quitter <- "Done" }() <-quitter }
Erlang
-module(hello_world). -export([start/0, say_hello/2, say_world/0]). say_hello(0, WorldPid) -> WorldPid ! quit; say_hello(N, WorldPid) -> io:format("Hello ", []), WorldPid ! {sayWorld, self()}, receive sayHello -> say_hello(N - 1, WorldPid) end. say_world() -> receive quit -> quit; {sayWorld, HelloPid} -> io:format("World!~n", []), HelloPid ! sayHello, say_world() end. start() -> WorldPid = spawn(hello_world, say_world, []), spawn(hello_world, say_hello, [1000, WorldPid]).
C++ (Mindroid)
#include <stdio.h> #include "mindroid/os/Message.h" #include "mindroid/os/Handler.h" #include "mindroid/os/LooperThread.h" using namespace mindroid; static const int SAY_HELLO = 0; static const int SAY_WORLD = 1; static const int QUIT = 2; class HelloHandler : public Handler { public: HelloHandler(const sp<Handler>& worldHandler) : mWorldHandler(worldHandler), mCounter(0) {} virtual void handleMessage(const sp<Message>& msg) { switch (msg->what) { case SAY_HELLO: mCounter++; if (mCounter <= 1000) { printf("Hello "); sp<Message> sayWorld = mWorldHandler->obtainMessage(SAY_WORLD); sayWorld->metaData()->putObject("SayHello", obtainMessage(SAY_HELLO)); sayWorld->sendToTarget(); } else { mWorldHandler->obtainMessage(QUIT) ->sendToTarget(); Looper::myLooper()->quit(); } break; } } private: sp<Handler> mWorldHandler; int mCounter; }; class WorldHandler : public Handler { public: virtual void handleMessage(const sp<Message>& msg) { switch (msg->what) { case SAY_WORLD: printf("World!\n"); msg->metaData() ->getObject<Message>("SayHello") ->sendToTarget(); break; case QUIT: Looper::myLooper()->quit(); break; } } }; int main() { sp< LooperThread<WorldHandler> > wlt = new LooperThread<WorldHandler>(); wlt->start(); Looper::prepare(); sp<Handler> hh = new HelloHandler(wlt->getHandler()); hh->obtainMessage(SAY_HELLO)->sendToTarget(); Looper::loop(); return 0; }
I think I really like Go (although Erlang is a bit more crafty :-)). Go eases developing scalable and reliable distributed systems while being a good to read language. Since you can also handle much more concurrent activities with one machine using Goroutines (compared to plain operating system threads) it also helps in saving energy.
Links
I did a Common Lisp version of it at http://tapoueh.org/blog/2012/11/04-Concurrent-Hello.html to compare, and the lparallel Common Lisp library author did some work on the topic too at http://lparallel.org/2012/11/05/concurrent-hello-world/
ReplyDeleteA libccpa example for C++11 would also make a good fit: https://github.com/Neverlord/libcppa
ReplyDeletedon't understand why you don't use the built in async functionality in C++11?
ReplyDeleteYou can use a lot of C++ abstractions to implement a concurrent Hello World. Plain threads and semaphores, Boost fibers, or other async stuff. But I wanted to see the solution using the Mindroid framework since it is much lighter weight (than Boost) and therefore even runs on tiny embedded hardware targets. Furthermore I really like Android's concurrency stuff. But I have to admit that the Mindroid C++ is somewhat bloated here. This is because Mindroid is a concurrency library that focuses on Actors and message passing which is great for real applications that need to scale but not for tiny ones like Hello World.
DeleteActors and CSP:
ReplyDeletehttp://cstheory.stackexchange.com/questions/184/whats-the-difference-between-the-actor-model-of-concurrency-and-communicating-s
https://groups.google.com/forum/?fromgroups=#!topic/golang-nuts/TbVZNLbvZlY
http://bartoszmilewski.com/2009/07/16/on-actors-and-casting/