|
|
|
|
|
by lenkite
3309 days ago
|
|
Thanks for this very informative post! However, I think you disparage good old win32 just a tiny wee bit. It was quite well designed for its time - perhaps a little too ahead of its time. Everything was async, to communicate between windows you needed to post events to queues, you could customize the window classes any way you wished - it was perhaps an extraordinarily sophisticated and flexible framework and lots of talented folks made it dance. It had a really good and long 20+ year run. (and still running strong in some desktop software) |
|
Effectively, a Win16 system is/was basically exactly equivalent to an Erlang node, but one where your "processes" just happened to be paired, component-wise†, with handles to structs of GUI properties held in window-manager memory.
Like an Erlang node, Win16 is/was:
• green-threaded — i.e. they both have very low-overhead in-memory structures containing a tiny heap/arena and a reference to an in-memory delegate code module, through which execution would pass in turn. In Erlang, these are "processes"; in Win16, these are windows—i.e. actual windows, but also "controls" in the controls library.
• cooperatively-scheduled (yes, Erlang is cooperatively scheduled—when you're writing C NIFs. When you're executing HLL bytecode in the Erlang VM, this fact is papered over by the call/ret instructions implicitly checking reduction-count and yielding; but if you're writing native code—like in Win16—you do that yourself.)
• Message-passing, with every process having a message inbox holding dynamically-typed message-structs that must be matched on and decoded, or discarded.
• Offering facilities to register and hold system-wide handles to large static data-blobs (Erlang large-binaries, Win16 rsrc handles);
• Capable of doing IPC only by having processes post messages to another process's queue, and then putting themselves into a mode that waits for a response;
• Based on a supervision hierarchy: in Erlang, processes spawn children (themselves processes) and then manage them using IPC; in Win16, root-level windows spawn controls (themselves windows) and then manage them using IPC.
And, crucially, in both of these systems, real machine-threads are irrelevant. Both Win16 and Erlang were written in an era when "concurrency" was a desired goal but multicore didn't yet exists—and so they don't really have any concept of thread affinity for processes/windows. Both systems are designed as if there is only one thread, belonging to a single, global scheduler—and then their multicore variants (SMP Erlang and Win32) attempt to transparently replicate the semantics of this older system (though in different ways: Erlang allows processes to be re-scheduled between scheduler threads, while Win32 pins windows to whatever scheduler-thread they're spawned on.)
Win32 later introduced an alternative model to take better advantage of multithreading: COM "multi-threaded apartments", allowing windows (or, as a generalization, COM servers, which could now execute and participate in IPC on a thread without spawning any window-instances) to interoperate across thread boundaries without requiring a message be serialized and passed through the scheduler/window-manager process.
† http://cowboyprogramming.com/2007/01/05/evolve-your-heirachy...