Boost logo

Boost :

From: Victor A. Wagner, Jr. (vawjr_at_[hidden])
Date: 2002-08-12 13:06:25


At Monday 2002/08/12 09:47, you wrote:
>----- Original Message -----
>From: "Victor A. Wagner, Jr." <vawjr_at_[hidden]>
> > At Monday 2002/08/12 05:53, you wrote:
> > >>If join is called on a thread that terminated through an exception, then
>you
> > >>could notify the caller of join that the thread terminated through an
> > >>uncaught exception, but that is another issue.
> > >
> > >And how do other threads know that the thread has terminated?
> >
> > how does join() work?
>
>Through very explicit thread safe synchronization. Apples and oranges, and
>you can't begin to compare the two.

Ok, I originally read it as how would the join() know the thread has
terminated. The original question was about join() and it's caller, not
any other threads.

I guess the problem is that I have _no clue_ what your background is, and
what "threading" means to you (except for your assertion that they are NOT
"delayed calls").
My experience comes from several multi-tasking systems written at Computer
Automation in the '70s, Amiga, OS/2, and WinNT (and successors). Almost
all of it has been embedded systems and most of those weren't multi-user
(except in a very limited sense). We pretty much ignored Unix and it's
derivatives because they couldn't give any sort of guarantees on response
time, and the original fork(), join() was WAY too expensive (many of our
systems didn't have any "backing store" (a disk, for example). So while we
kept watching what "*nix was doing" it never really became relevant for
embedded systems.
We also never gave much thought to "time-slicing" which seemed like a good
way to force a context switch (not always that cheap a thing to do) for no
apparent gain. ALL of the tasks/processes/whateveryouwanttocallthem needed
to complete, and we needed every nanosecond we could get.

So, I guess that's where I'm coming from... fast, and minimal. We didn't
need all the "safety" included in "modern multi-tasking" systems, and
"protecting users" from each other just didn't exist.
We also chose to implement 'tools' which could be used to build others...
e.g. it's trivial to build a mutex from a semaphore, vice-versa is quite
difficult (if it can be done at all), so we provided semaphores, not
mutexes. We assumed that our customers would be writing "systems" of their
own, and if we needed something, they might also, so we didn't take away
capability _ever_. If they chose to be unsafe, that was their decision.

Another thing we concerned ourselves with: making it as easy as possible
for a customer to start using a new feature.
In some instances the new feature was multi-tasking itself. The details
are probably of historical interest only:
How do you make a subroutine/function "thread-safe" when the ONLY call
instruction puts the return address in memory at the "goto" address and
starts executing at the next (i.e. no stack to "push" it onto) and which
allowed interrupts between the storing of the return address and the
execution of the 1st instruction of the function (one of the more foolish
engineering design decisions I've ever had to deal with)?
We managed to do it with a single macro to modify the subroutine definition
(and some very clever code (not all of it mine)).

Perhaps it is because of the care we gave to this kind of thing, that I
believe that changing a function from 'normal' to being run as a thread
(delayed call isn't exactly the right term here, but separated call/return
would be better) is to define a new construct which _could_ be:

try {
      //for exposition only.... the following 3 lines USED to
be somedouble = myfunc(a, b, c)
      boost::thread<double, return_std_exceptions> mythread(myfunc, a, b, c);
      //.... and later on
      somedouble = mythread.join();
}
catch (std::exception& e)
{
     //process the exception
}

Ambitious? probably yes.
Worthwhile? In my opinion, definitely.
it's worth noting that myfunc() can STILL be called in the normal fashion
if desired. Changes are required _only_ to use the new capability.

> > > And remember the mechanism needs to be thread safe. And even after
> > > that, what should I do with the knowledge if the thread in question is
> > > one created by some library?
> >
> > if you know it's being "join()ed" does it matter who created it?
>
>First, I never claimed you knew it was being join()ed. Second, yes it very
>much matters who created it. He's the only one likely to have any way of
>dealing with the exception.
>
>Bill Kempf
>_______________________________________________
>Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Victor A. Wagner Jr. http://rudbek.com
PGP RSA fingerprint = 4D20 EBF6 0101 B069 3817 8DBF C846 E47A
PGP D-H fingerprint = 98BC 65E3 1A19 43EC 3908 65B9 F755 E6F4 63BB 9D93
The five most dangerous words in the English language:
               "There oughta be a law"


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