
Hello Cafe! I am trying to implement networked application in Haskell. It should accept many client connections and support bidirectional conversation, that is not just loop with Request -> Response function but also sending notifications to clients etc. NB: I came from C++ background and used to explicit asynchonous operations and pools of OS threads. (Boost.Asio + Boost.Thread) There seem to be lots of goodies around (green threads, STM). The problem is that I cannot figure out how to design such applications. First of all now I have to start some threads for each client. Client state and behaviour may change depending on data that comes from it or other clients. So it seems that I have to start at least three threads: one that reads data from socket, one that sends queued messages to the socket and one that represents clients main behaviour loop. The last one will supposedly read from some STM sources, one of them being TChan/TMVar filled by thread that reads socket. Here I get stuck: how to manage that threads? I tried to search STM examples at hackage and the most interesting packages were: 1) combinatorrent - quite complex application, but it seem to be highly Erlang-inspired, so I am not sure that it is the simplest way of doing thing. 2) network-connection package - it is a library that wraps socket and uses STM internally but exposes almost the same interface with blocking operations. Thread management is quite explicit there. But this package is marked obsolete. I wondered if one can rely upon garbage collector to reap dead threads when using STM? Or is it too error prone (accidental references to STM object that prevent it from being collected) and unpredictable? I have read this post: http://blog.ezyang.com/2011/07/blockedindefinitelyonmvar/ It shows that relying upon handling BlockedIndefinitelyOn* exceptions is a bad idea but is it OK just to rely upon that blocked forever thread will die and not to kill it explicitly? And also if it is really reliable, what are exact rules when some object goes out of scope and becomes collectable? For example in blog post mentioned above in "main1" example "lock" variable is accessible until the end of do-block, i.e. if I add "takeMVar lock" line to its end, it will compile. But it is not used actually. Is it guaranteed that explicit performGC will reap it? Possibly the best answer would be just pointing me to some recent examples of concurrent network applications. Thanks!