
Don G wrote:
From a quick read, it looks similar to the implementation path I had used at my work, but probably more flexible in how event_dispatcher relates to event_handler. I think there is a good likelihood that the two are complementary.
Ok could you expand a bit? What do you mean by complementary?
The code I wrote for work had an implementation-side abstraction with an abstract base like event_handler, though I called it Selectable. It had a signal mask that mapped to your event_handler::event_type_t enum. The thread pool internal to the network object managed calls to select (or whatever) based on the signal mask.
Ok the reason I expose it is for the possibility to write single threaded reactive servers.
At least for Windows, one cannot mix sockets with other types of objects (files or whatnot). And, while I have not tried it, the docs seem to suggest that sockets for IPv4 and IPv6 may not be able to go to a single select call. All this makes matching event_handler instances to an appropriate event_dispatcher tricky and not portable. In other words, something that should be hidden from the user.
You could implement a select like replacement using WSAEventSelect and WaitForMultipleObjects to mix and match (though it would support only 64 handles, which also select does by default).
The real complexity, though, comes when the number of objects gets large, in particular larger than a single call to select() can handle. This necessitated some load balancing logic to shuffle Selectable objects between threads, create new threads, cleanup extra threads, etc.. All of this is stuff that should only be written once! :) As a user of the library (again, at my work), I never have to worry about that mundane stuff. That is the job of the network library.
Both yes and no. An implementation such as active_event_dispatcher could provide this choice and functionality, at lower layer there should be implementations that let the user of the library make the choices (and even going reactive single threaded). And eg using iocp the threading is basically done by the os (just as long as you have a pool of thread dequeing packages). For the other notification mechanisms i guess a leader follower pattern should be implemented.
And it scales pretty well. Though I haven't tested N*1000 simultaneous connections using drones across the network to simulate heavy CPU load, I have stress tested the library upto the limit of Windows XP Pro (not Server) and on Linux with N*1000 where N < 3, using lots of threads to generate the load.
While all thread pooling and connection aggregation is managed behind the scenes, some of this could be exposed in an abstract manner to allow user code to influence the load balancing algorithm. This, I think, would be for only the very advanced user and not something to tackle initially.
I think this should be added as another layer on top of of the more primitive dispatchers. Look eg at TP_Reactor from ace that uses a single threaded dispatcher and a leader follower pattern to handle events from multiple threads. This is also described in POSA2 (http://www.amazon.com/exec/obidos/ASIN/0471606952/ref%3Dsim%5Fbooks/103-8124...) . Which in general contains a lot of good patterns and advice for networked programming.
1. Should the network library provide different choices of implementation to the user? For the most part, the platform will dictate the available solutions, so having the user decide would make their code non-portable. [my thought so far is no]
2. Would it be better perhaps to only provide behavior choices (sync, async, non-blocking) as part of the interface? [my thought is yes]
I think two but not providing choices just support them all automatically and efficiently. And give the user a possibilty to plugin own implementations of the concepts.
This is where our goals diverge I guess ;). I don't see any point in the user deciding these details, especially implementing their own concrete classes. And I do see it creating confusion amongst those that don't have the "Network API Guru" honor badge<g>.
Well implementing own concrete classes should only be for the ones with badge and advanced users understanding the concepts, there arent that many implementing streambufs today either though the possibility exists, except for advanced users.
The interfaces I proposed provide a very clean and complete interface, IMHO<g>, and the implementation can be quite scalable (for those that need it to be) and I know it is extremely portable, even to non-socket based systems.
I think ut looks fairly good as well and agree whith calebs and have kind of don't like the extensive use of shared_ptr I think ownership and resource managment should be handed over to the user and not mandated by the library. /Michel