Boost logo

Boost :

From: Roland (roland.schwarz_at_[hidden])
Date: 2004-01-09 05:23:27


(Darryl Green <Darryl.Green_at_[hidden]>) wrote:
 
> I've been lurking on this thread for a while, and haven't said anything
> because I can't currently put my code where my mouth is. However, I
> think that boost.thread should be refined, not extended.

This is what I think too.

> Regardless of
> how it is implemented on a given platform, boost.thread provides a
> lightweight C++ compatible wrapper over a portable subset of pthreads.
> Yes, there are some extensions to that already - thread pool for
> example. As much as anything else these extensions serve to
> validate/refine the basic boost.thread design, rathern than tamper with
> its implementation.

Yes this would be the ideal case. And this was my approach too. I intended
to be a user only of the library.

>
> Specifically, I don't think that boost.thread condvars should be
> extended to deal with IO any more than I think pthreads condvars should
> be. I do think that portable IO multiplexing would be great and
> shouldn't be in a socket specific lib. However it looks like the latest
> proposal for the boost.socket lib should be generic enough (maybe needs
> a name change?).

Thank you for the pointer. Btw.: where can I find it? Is this in the sandbox cvs?

>
> >
> > While it is a challenge on its own to design a portable asynchronous
> > IO abstracction, every such design somehow would need to link
> > conditions with the native async IO mechanism of the relevant
> > platform.
>
> Why?
>

I have come to this opinion because cond.wait() and WFMO or select are
the two mechanisms where one deliberately puts a thread into sleep. (These
are also automatic cancelation points in pthread.) So when I need to wait
for either one of a condition beeing notified or an IO event occuring there
is no way of doing this efficiently (altough the operating systems would allow
for this). I can imagine a helper thread which converts IO events to notifies
or notifies to events that can be recognized by the IO multiplexer. But this
gets (unnecessary?) complex, and shurely inefficient. Also this thread
likely will be a bottleneck for throughput. How many helper threads should be
there? The other solutions unfortunately need to alter some code within
the library _or_ disclose some of the internal structs. I think the latter is
to be avoided at all circumstances, while adding a defined primitive
that gives the desired access would be preferable.

> Any IO multiplexing system should have some way to allow non-IO events
> to wake it up. In any case this is generally merely an issue of
> definition - it is easy enough in most environments to find some sort of
> pipe-like interface - even a socket if necessary, that can be used for
> this purpose - stuff a "message" in one end, this wakes up the thread
> blocked (eg in select) at the other. The content of the message
> can/should be very minimal - just enough to identify the message/event.
> The "body" can be passed via other methods specifically memory in the
> case of a threading environment. None of this has any interaction with
> the threading lib used.

Thank you for pointing this out, but I already was aware of this option. What
I dislike on this is the inhomogenous nature of signalling. Say you have
a thread that sits waiting for IO, and then you want to send it a command.
Say it is waiting for IO inside an object that is made thread safe using
the monitor pattern. Now you want to send a command. The command
functions are secured by the monitor. How do you secure the function
that is waiting for IO? You would need to manually unlock and lock
the monitor somehow, while still not beeing able to honour a general
notify that would be able to force a state stange of the object irrespective
how many thread are waiting on it in any combination of wait types.

I must admit that I am a little biased now by the fact that I was able to
write a small application that contains two classes that are derived
from thread and condition namely cancelable_thread and cancelable_condition
that have been possible simply by _using_ boost.thread. For me this
was a strong indication of how complete the boost.thread primitives
already are. I wouldn't dare to tamper with them at all!

But, my classes still suffer from the problem that I cannot sucessfully
cancel when a thread is inside the IO wait. Sure cancelling a thread can
be tackled by other means (e.g like pthread) but cancelling an object on
which you have a mix of different threads waiting?

Recently I skimmed over a tutorial of the ACE library. They also point out
that they have unified these two types of wait.

But please, don't get me wrong. I am not in a position to criticize the
boost.threads at all. I want to learn how to use it efficiently and solve
some basic problems with it.
Perhaps you could tell me how you would tackle the following problem:

You have an object that implements the doubly bound buffer as to be
seen in one of the examples. You have an IO port (tty, sockets, parallel, ....)
Now you want a thread that multiplexes on the buffer or the IO.

I would like to expose the condition that signals data vailability
and then beeing able to wait on either this condition or the IO.
I would be glad if you could give me a sketch of how this could be
done with boost.thread (efficiently) without altering it.

>
> Have a look at the latest socket lib proposal and see if you can see a
> way of using it like this. Obviously efficiency is an issue here, and if
> the best you can do is send the message over TCP it is probably not
> efficient enough!
>

Thank you again for the pointer. I will check this out.

> > Unfortunately I do not see a way, how this could be done without
> > altering the code of condition.hpp so before giving it a try
> > and start hacking
> > away I would like to hear some opinions. Perhaps there still
> > is a way to emulate
> > this on top of boost.thread somehow?
>
> Not on top - along side. I must admit I haven't looked closely at your
> use case. Maybe if I have missed something you can point it out.
>

Along side implies, in my reading, that the problems are orthogonal.
I hope I was able to point out that they are almost, but not completely
orthogonal.
I try to be more precize: Altough the operating system makes no
difference on threads whether they are waiting for IO to complete
or they are waiting on a synchronization primitive (condvar) the
application program has to deal with these cases in a fundamental
different manner. (And I think this makes things unnecessary complicated.)
Put it yet another way: Completing an IO request causes some kernel
module to issue a signal. In an ideal world this would be a condvar
beeing notified, wouldn't it?

Regards,
Roland


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk