Hacker News new | ask | show | jobs
by zigzigzag 3309 days ago
Well, I hope we're not getting sentimental about Win16. I've written more than my fair share of Windows API code and even though some of the concepts are now coming back into fashion again, largely due to the limits of browser engines, it really isn't an era I'd return to at all. Those models were all abandoned for solid reasons and Apple's failure to do so in time nearly killed the company.

I'm not sure your description of COM is quite right. The way I remember it, windows (HWNDS) were and still are objects with thread affinity. COM had the notion of a "single threaded apartment" which basically meant the COM server received RPCs using regular Window messages, and the MTA that you mention simply meant no inter-thread marshalling was done at all i.e. the object was inherently thread safe using locks or whatever. But Windows never changed to a model where the controls library was thread safe: changing the contents of an edit box from another thread, for instance, always required a context switch.

COM's usage and abusage of the window message system for fast inter-thread switching was only ever an ugly hack, which caused all kinds of weird problems and glitches. Most obviously it caused Windows' reliance on actually having a GUI layer to deepen considerably because now inter-thread/inter-process RPC - that on Linux and MacOS were well modularised into things like Mach IPC, SunRPC, DBUS etc - were totally tied to the windowing system.

IIRC the entire apartment concept was also stupidly designed, so there were constant problems with Microsoft using COM internally to implement some APIs, which would by default enter an STA and require the _caller_ of the API to pump the message queue otherwise the API they'd just used would silently fail to work. In the era I was working with it that fact wasn't always properly documented, I think.

1 comments

> COM's usage and abusage of the window message system for fast inter-thread switching was only ever an ugly hack

This is effectively the entire point I wanted to dispute in my original post above; I guess I didn't get it across clearly enough.

As can be seen from how pre-COM (e.g. DDE, OLE) IPC was achieved on Windows, Microsoft truly believed that sending messages through the window-manager was a good way to do IPC. Their designs just kept doing it, over and over. STA COM messaging wasn't a hack; it was more of the same, a doubling-down on a long-standing design paradigm. MTA COM messaging was the hack—a way to make everything continue to look like HWND messaging (with an abstraction layer added), but have it transparently optimize to SHM IPC in cases where that was beneficial [and where the developer had ensured their ADTs were compatible with it.]

> Most obviously it caused Windows' reliance on actually having a GUI layer to deepen considerably because now inter-thread/inter-process RPC - that on Linux and MacOS were well modularised into things like Mach IPC, SunRPC, DBUS etc - were totally tied to the windowing system.

And, driven by the "evidence" of this repeated doubling-down above, I would conclude that this was the point: Microsoft considered Windows to be about, well, windows.

As I was saying above, a "window" in the Win16 sense was effectively the same thing as an Erlang process, but with some extra (optional-to-use!) GUI data stuck to it. The "correct" way to achieve async parallelism in Win16 was literally to create a "background window" that would register a kernel timer to send it tick events, and then do work when it received one. Which is the same thing you do if you want to write an Erlang process to wake up and poll some data source every so often.

My point isn't just that there are parallels here; my point is that Microsoft expected you to use the "window" primitive in exactly the ways that Erlang expects you to use the "process" primitive. Windows are the "process" primitive of Win16—they're tiny, green-threaded processes, and the window-manager is their scheduler.

That statement should make Microsoft's views on IPC clearer. Of course Windows IPC is achieved by putting messages through the window-manager. The window-manager is the scheduler†; knowing about other window-processes and routing messages to them is its job. It is DBUS—and it is also, given DDE, the equivalent of macOS's LaunchServices daemon.

---

† ...or rather, the window-manager is the scheduler for anything that's not a DOS VM. Windows, from 2.x through to 9x, was effectively a two-layer system: a bare-metal hypervisor "kernel" (KERNEL.EXE/KRNL386.EXE) with one Windows dom0 and N DOS domUs; and then an OS "kernel" running in that Windows dom0. That dom0 OS kernel is GDI.EXE, and cooperative message-passing is its scheduling algorithm. It also happens to do graphics. (It's a paravirtualized kernel that relies heavily on the hypervisor kernel above it, yes, but it's still the kernel of the Windows domain.)