This is similar to our cooperative implementation of FBP written in C (which has been used for production work), except that the whole application hangs every time we us a standard C I/O service. I believe there is an async I/O facility available for C, which could (perhaps partially) address this problem, but we haven't done any experimenting with it.
The other type of FBP implementation (asynchronous) is used for the Java implementation (JavaFBP), and now for our C# implementation (C#FBP). In this case, every FBP thread is an instance of the Thread class, and synchronization only needs to occur when working with inter-thread Connections. Control can switch between threads at any point, but only Connections need to be protected (plus a couple of other minor features). In the Java implementation, we use the Java "synchronized" function to control this. This version (http://www.jpaulmorrison.com/fbp/JavaFBP-2.4.jar) is available on my web site, and also on SourceForge. The C# implementation of course uses the "lock" function, and is available on SourceForge, and also on my web site, at http://www.jpaulmorrison.com/fbp/CsharpFBP-2.3.zip.
Note on max. number of threads from SvenSteinseifer:
Regarding the use of threads: A quick search on the internet revealed that the maximum number of threads depends on the operating system and the available memory. I've attached a test program I found on the net which tries to spawn as many threads as possible. On my machine with 2GB ram, an out of memory error occurs after creating 7400 - 7500 threads. It is possible to limit the stack size using a command line switch. To limit the stack size to 100kB, one would issue the following command on the command line: java -Xss100k MaxThreads?
With this setting the maximum number of threads increases significantly (~ 23k threads on my machine).
Another mainframe approach: I have built experimentally an FBP asynchronous, preemptive implementation, for the IBM mainframe MVS environment, using MVS multitasking. This would allow a SQL call or a Sort to only affect one thread, so it looks very appealing, although the overhead is greater than that of the cooperative implementations. However, it should also make much better use of multiprocessor machines. However, StanWilliams has pointed out that this strategy will only work when the number of tasks is small - when it becomes larger, we may have to assign tasks to threads dynamically, or even share FBP threads between the infrastructure threads. No experimenting has been done with the preliminary MVS version so far, but I would be happy to make it available to anyone who wants to take a stab at it.
One last (MVS) option - maybe far in the future - would be to use the IBM LE/MVS thread capability, but I believe IBM has only enabled it for the POSIX environment, which AFAIK is only invokable from C.
Ruby: Ruby uses "green threads", local to one interpreter - thanks, JohnCowan! This is essentially the same technique that we used in the first three IBM implementations (that I have called "synchronous" above) - their advantages and disadvantages are described quite well in http://www.jguru.com/faq/view.jsp?EID=143462. But for another view, see http://www.cincomsmalltalk.com/blog/blogView?showComments=true&entry=3303013147.
For a discussion of this issue in Erlang, see http://www.erlang.se/publications/xjobb/0089-hedqvist.pdf.
Python:
Extract from http://www.linuxjournal.com/node/7871/print
There's an inherent complexity in asynchronous programming, especially when you need to do many blocking operations in succession. In Python, however, the benefits of threading are diminished by Python's Global Interpreter Lock (GIL). Threaded programming in Python is refreshingly simple, because all internal Python operations are thread-safe. To add an item to a list or set a dictionary key, no locks are required, so as to avoid race conditions among threads. Unfortunately, this is implemented through an interpreter-wide lock that Python's interpreter uses liberally. So, although two threads safely can append to the same list at the same time, if they're appending to two different lists, the same lock is used. Because threaded Python applications suffer a resulting performance hit, asynchronous single-thread programming is all the more desirable for a language such as Python.
See also the Python documentation at http://docs.python.org/api/threads.html.