
Hi Cory, --- Cory Nelson <phrosty@gmail.com> wrote:
Perhaps asio::error could be changed to assert() that it is checked before it goes out of scope. It is important to make sure the user checks it as inconsistent application states can be a big problem to track.
Hmmm, I dunno. What constitutes checking? What if the application simply wants to post (i.e. via a demuxer::post() call) a copy of the error to another function object where the real work is to be performed? This is likely to occur when you start composing asynchronous operations to create higher levels of abstraction. The mechanism to then keep track of whether the error has been checked could start to be quite heavy. <snip>
I see this as a layer of abstraction that can be added on top of asio. For example, one could write a free function async_connect that used a URL-style encoding of the target endpoint. I don't see it as in scope for asio _for_now_.
It would definately be an abstraction and it could certainly be written by the user. But what I was getting at is that nearly all client apps would make good use of a function like this, so why not prevent such remaking of the wheel and put it right in asio?
I think at this point I'd rather give it time to allow the interface to grow out of common use cases. I.e. see where more experience in the field takes it and then put it into a library.
- What happens if you need to perform per-thread initialisation before any other code runs in the thread? For example on Windows you might be using COM, and so need to call CoInitializeEx in each thread.
I don't use COM. I'm not sure of what it would entail.
The issue of exceptions that escape from handlers also just occurred to me. The current design in asio lets these exceptions propagate through demuxer::run() so that the application can handle them. Correctly handling exceptions presents a problem for an internally managed thread pool. <snip>
Having heard your reasons - how feasible would it be to include a threaded_demuxer type, which would be built with high-perf scalability in mind?
Well, I don't see it as impossible, but I also don't see it as necessary to writing scalable, high-performance apps. Today I was thinking that it should be possible to develop a (possibly portable) thread-pooling solution to this external to asio. The hard part is having a way of detecting that an additional thread is required. Once you've decided you need an additional thread, then you just spawn it and have it call demuxer::run() to donate itself to the pool. <snip>
This is true. It will awake another thread if an active one blocks. However if all of your threads decide to block you will have a dead cpu.
My advice is to avoid blocking ;) Seriously, my experience to date leads me to believe that long running blocking operations should be abstracted behind an asynchronous interface, so that the "main" thread of an application does not block. <snip>
You have two threads running seperate demuxers. Suppose the sockets in one of them gets a heavy workload and the other has nothing to do?
This might be an unlikely scenario, but it's also an unacceptable and easily avoidable one.
Spreading the workload between threads (without forcing a socket to always be on one thread) will always be the optimal way to go, and the only way to do this sanely on multiple platforms is to have the demuxer do the threading.
I just present the demuxer-per-cpu idea as a possible design alternative that asio permits. It may be suitable for some applications but not others. My point is that it is not necessarily unacceptable -- I think it is entirely reasonable to choose to trade off some potential performance in favour of avoiding the development complexity introduced by synchronisation. Oh BTW, I forgot to mention ConnectEx. I was planning to do it before the review but as time was running short I didn't want to risk introducing instability. I intend to enable it for builds that target Windows XP or later. I'm still of two minds as to whether Windows 2000 targeted builds should try to dynamically load it and use it, since that increases the amount of code generated and the complexity of the implementation. Is it worth it? Cheers, Chris