Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Novice: Exiting and starting threads.

26 views
Skip to first unread message

Sol Rosenberg

unread,
Feb 12, 2002, 3:34:05 AM2/12/02
to
Hi,

I'm trying to do some simple POSIX programming, however, I'm stuck
pretty much right away. I wish to start two threads in my main
function/thread, each performing a task, then exiting them and let the
main function perform some checking. The synchronization is done by
simple mutexs. Then I wish to start the threads again and so one. The
loop must continue infinitly. However, an error occur were I cannot
open the threads again after around 500 loops (depends on my Linux
distribution I think). The error number is 11.

A simplified version of my code is (hope it is not too long):

---------------------------------------
#include <stdio.h>
#include <math.h>
#include <pthread.h>

/* Defines */
#define FLUSH fflush(stdout)

/* Global mutexs */
pthread_mutex_t mutex_1, mutex_2;

/* Function protoypes */
void myfun_1(void);
void myfun_2(void);
void mycheck(int);

int main(void){
pthread_t thread1, thread2;
int c_1, c_2;

while(1){
pthread_mutex_lock(&mutex_1);
c_1 = pthread_create(&thread1, NULL, (void*)&myfun_1, NULL);
mycheck(c_1);

pthread_mutex_lock(&mutex_2);
c_2 = pthread_create(&thread2, NULL, (void*)&myfun_2, NULL);
mycheck(c_2);

pthread_mutex_lock(&mutex_1);
pthread_mutex_lock(&mutex_2);

printf("---------------------\n"); FLUSH;

pthread_mutex_unlock(&mutex_1);
pthread_mutex_unlock(&mutex_2);
}

return 0;
}

void myfun_1(void){
static int m = 0;

printf("This is call nr: %d to myfun_1 \n", ++m);
FLUSH;

pthread_mutex_unlock(&mutex_1);
pthread_exit(0);
}


void myfun_2(void){
static int m = 0;

printf("This is call nr: %d to myfun_2 \n", ++m);
FLUSH;

pthread_mutex_unlock(&mutex_2);
pthread_exit(0);
}

void mycheck(int n){

if (n != 0){
fprintf(stderr, "ERROR NUMBER %d - BAILING OUT!! \n", n);
exit(2);
}

}

------------------------

Hope that someone will help.

Jesper

David Butenhof

unread,
Feb 12, 2002, 7:40:09 AM2/12/02
to
Sol Rosenberg wrote:

> Hi,
>
> I'm trying to do some simple POSIX programming, however, I'm stuck
> pretty much right away. I wish to start two threads in my main
> function/thread, each performing a task, then exiting them and let the
> main function perform some checking. The synchronization is done by
> simple mutexs. Then I wish to start the threads again and so one. The
> loop must continue infinitly. However, an error occur were I cannot
> open the threads again after around 500 loops (depends on my Linux
> distribution I think). The error number is 11.
>
> A simplified version of my code is (hope it is not too long):
>
> ---------------------------------------

> /* Global mutexs */
> pthread_mutex_t mutex_1, mutex_2;

BUG 1: You are not INITIALIZING either of the mutexes before you use them.
Either use the static initializer PTHREAD_MUTEX_INITIALIZER here, or call
pthread_mutex_init() in main() before you use them.

> int main(void){
> pthread_t thread1, thread2;
> int c_1, c_2;
>
> while(1){
> pthread_mutex_lock(&mutex_1);

BUG 2: You CANNOT (imagine that written in extremely large neon blinking
letters that sear themselves into your retinas permanently) hand off a
locked mutex from one thread to another. It's illegal. It's nonportable.
It's wrong. It violates the basic essential concept of a mutex. And, even
worse than all that, such usage renders itself meaningless because it
provides no memory visibility guarantees between the two threads. (In this
case it doesn't matter since pthread_create() provides the only memory
guarantee you'd really need... but that's beside the point.)

I'm not sure what you're hoping to accomplish with this use of mutexes,
anyway. Perhaps you're trying to make sure that you don't start a "thread1"
from iteration n+1 until the "thread1" from iteration n has finished
writing and flushing? If so, you should simply JOIN both of your threads at
the end of each iteration to be sure they're done. (This will also solve
"BUG 4", detailed below.)

> c_1 = pthread_create(&thread1, NULL, (void*)&myfun_1, NULL);

BUG 3 (minor): the 3rd argument is of type void *myfunc(void*), not
"void*". The thread start function should be properly declared, and you
should just use the name. Otherwise your code isn't 100% portable; and
you're not really making things any easier on yourself.

BUG 4 (this is the one you've noticed): You are neither detaching nor
joining the threads you create. Each runs, terminates, and then hangs
around waiting for you to give it permission to go away. And you don't.
Thus, eventually you exceed the available resources and are unable to
create yet another thread.

You can either call pthread_join() for each thread you create at some
reasonable point, or, if you don't care WHEN they terminate, you can simply
create each thread DETACHED. To do that, create a thread attributes object
with pthread_attr_create(), set the "detach state" attribute to
PTHREAD_CREATE_DETACHED with pthread_attr_setdetachstate(), and then pass
the attributes object (the address of the pthread_attr_t variable) to
pthread_create() as the second argument:

pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
pthread_create (&thread1, &attr, myfun_1, NULL);

When you do this, each thread will "evaporate" when it terminates. As long
as you don't create threads faster than they can run and terminate, you
won't exceed your available resources. (Note that you might still sometimes
receive EAGAIN if you do manage to "get ahead" of your threads; if so, you
just need to wait a bit to let them catch up.)

--
/------------------[ David.B...@compaq.com ]------------------\
| Compaq Computer Corporation POSIX Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\-----[ http://home.earthlink.net/~anneart/family/dave.html ]-----/

Sergey P. Derevyago

unread,
Feb 12, 2002, 8:17:00 AM2/12/02
to
David Butenhof wrote:
> You can either call pthread_join() for each thread you create at some
> reasonable point, or, if you don't care WHEN they terminate, you can simply
> create each thread DETACHED.
BTW was it a good idea to make thread non-detached by default? It seems like
the most users "expect" their threads "to be detached" by default.
--
With all respect, Sergey. http://cpp3.virtualave.net/
mailto : ders at skeptik.net

Alexander Terekhov

unread,
Feb 12, 2002, 1:53:50 PM2/12/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6915CC...@iobox.com>...

> David Butenhof wrote:
> > You can either call pthread_join() for each thread you create at some
> > reasonable point, or, if you don't care WHEN they terminate, you can simply
> > create each thread DETACHED.
> BTW was it a good idea to make thread non-detached by default? It seems like
> the most users "expect" their threads "to be detached" by default.

But how would you then *join* -- get concurrently invoked function's
return value? Well, please do not tell me about yet another monitor
(mutex + cv) for "exit_status/value (should be capable to "store"
PTHREAD_CANCELED... and btw, how would you "catch" pthread_exit()?)";
I know it and the first thing I'll then ask you is how/when would you
destroy/finalize THAT sort-of-"thread-object"?

I think that all these failures to join/detach/pthread_exit-main(),
return/pthread_exit some local/stack address and "lets assume that
pthread_create makes that pthread_t var update/store visible/in-sync
wrt thread creation" bugs ARE the most frequent ones for less
experienced/informed/educated threaders, at least that is my
personal conclusion/observation after a year or so on this
newsgroup.

I think that the following would nicely address ALL these problems:
(including non-ANSI-C/C++ pthread_exit( (void*)some_int_value )/
pthread_create( &tid,0,&blabla,(void*)some_int_value ) !!! ;-))

http://www.terekhov.de/thread_ptr.txt
http://www.terekhov.de/mythread.c

But unfortunately, I just have not enough time to attack
that meta-"bind"-stuff :(

Anyway, any input/critique/help (and even flames ;-))
is greatly appreciated!

regards,
alexander.

Alexander Terekhov

unread,
Feb 12, 2002, 2:48:23 PM2/12/02
to
David Butenhof <David.B...@compaq.com> wrote in message news:<K28a8.231$Jh4....@news.cpqcorp.net>...
[...]

> pthread_attr_t attr;
> pthread_attr_init (&attr);
> pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
> pthread_create (&thread1, &attr, myfun_1, NULL);
>
> When you do this, each thread will "evaporate" when it terminates. As long
> as you don't create threads faster than they can run and terminate, you
> won't exceed your available resources. (Note that you might still sometimes
> receive EAGAIN if you do manage to "get ahead" of your threads; if so, you
> just need to wait a bit to let them catch up.)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Hmmm.. Do you mean sleep() or something like that?
AFAICT, not telling the system the REAL REASON I am
waiting (btw, how long?) for -- availability/cleanup/
recycle of thread objects, this ??could?? accomplish
nothing, unless I am missing something and then I just
apologize in advance... (other "non-terminated"
perhaps "long-running" threads could "get ahead"
of "recycler" and consume all available processing
cycles while I am waiting; so when I wakeup and call
pthread_create() again, I could then just get back
well, EAGAIN *again*... and *again*).

Is there some way to solve this "problem" NOT blocking
other still "active"/"long-running" threads?

Why not just strengthen semantics of pthread_join()
with respect to thread-resources/-objects utilization
and subsequent pthread_create() calls?

Or just somehow (perhaps thread_attr) tell that
*pthread_create* should *itself* wait/"let them
catch up"?

Or just provide some generic/optional "thread-recycled"
notification mechanism (for both joinable and detached
type threads), which would allow me to be build my own
monitor?

regards,
alexander.

David Schwartz

unread,
Feb 12, 2002, 2:54:51 PM2/12/02
to
Alexander Terekhov wrote:

> Is there some way to solve this "problem" NOT blocking
> other still "active"/"long-running" threads?

Defer the thread creation. Keep a table of threads that need to be
created and scan it periodically. If there are entries, try to create
them. This doesn't change the semantics because there is no guarantee
that a thread will start running in any particular time frame.

> Why not just strengthen semantics of pthread_join()
> with respect to thread-resources/-objects utilization
> and subsequent pthread_create() calls?
>
> Or just somehow (perhaps thread_attr) tell that
> *pthread_create* should *itself* wait/"let them
> catch up"?
>
> Or just provide some generic/optional "thread-recycled"
> notification mechanism (for both joinable and detached
> type threads), which would allow me to be build my own
> monitor?

If you want it code it. If a thread library doesn't provide you exactly
the semantics you want, then wrap it and provide them. Never let a real
pthread terminate, just re-task it. You are way overengineering a very
simple issue.

DS

Alexander Terekhov

unread,
Feb 12, 2002, 5:18:58 PM2/12/02
to
David Schwartz <dav...@webmaster.com> wrote in message news:<3C69730B...@webmaster.com>...

Gee! David, I am long enough here... I know that you LOVE
TASKS/JOBS (and probably *hate* thread-cancellation ;-)).

TASKS/JOBS are OK (and I would really love to see (and use)
some "goal-driven" thread-pooling (throughput-oriented/LIFO
thread-pools with "optimal" system-controlled/auto-adjustable
concurrency (min. context switches), but taking into account
"optimal" bandwidth-/IO-utilization and average response times,
etc... become a part of some future Pthreads!), but they are
NOT *threads*, however!

Consider:

http://www.opengroup.org/onlinepubs/007904975/xrat/xsh_chap02.html#tag_03_02_09
(first paragraph)

and specifically:

http://www.opengroup.org/onlinepubs/007904975/xrat/xsh_chap02.html#tag_03_02_09_21

"Threads are designed to be inexpensive enough
so that a separate thread may be created to
perform each separately cancelable operation;
for example, each possibly long running user
request."

;-)

regards,
alexander.

David Schwartz

unread,
Feb 12, 2002, 5:32:28 PM2/12/02
to
Alexander Terekhov wrote:

> Gee! David, I am long enough here... I know that you LOVE
> TASKS/JOBS (and probably *hate* thread-cancellation ;-)).

Yep. I love it because it makes all these problems go away.



> Consider:
>
> http://www.opengroup.org/onlinepubs/007904975/xrat/xsh_chap02.html#tag_03_02_09
> (first paragraph)
>
> and specifically:
>
> http://www.opengroup.org/onlinepubs/007904975/xrat/xsh_chap02.html#tag_03_02_09_21
>
> "Threads are designed to be inexpensive enough
> so that a separate thread may be created to
> perform each separately cancelable operation;
> for example, each possibly long running user
> request."

But don't you see that this doesn't work? It makes you too dependent
upon the implementation's exact semantics and sometimes you care about
the semantics.

DS

Sergey P. Derevyago

unread,
Feb 13, 2002, 4:02:30 AM2/13/02
to
Alexander Terekhov wrote:
> > BTW was it a good idea to make thread non-detached by default? It seems like
> > the most users "expect" their threads "to be detached" by default.
> But how would you then *join* -- get concurrently invoked function's
> return value?
Probably, using something like

pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);


pthread_create (&thread1, &attr, myfun_1, NULL);

;))

> I think that all these failures to join/detach/pthread_exit-main(),
> return/pthread_exit some local/stack address and "lets assume that
> pthread_create makes that pthread_t var update/store visible/in-sync
> wrt thread creation" bugs ARE the most frequent ones for less
> experienced/informed/educated threaders, at least that is my
> personal conclusion/observation after a year or so on this
> newsgroup.

I also think so.
However, I've just reviewed my code and come to the conclusion that the most
of my threads are detached. So (personally) I don't like "joinable by default"
threads.

> Anyway, any input/critique/help (and even flames ;-))
> is greatly appreciated!

Flames? Hmmm... BTW where is Mr. Butenhof? ;))

Alexander Terekhov

unread,
Feb 13, 2002, 5:58:06 AM2/13/02
to
David Schwartz <dav...@webmaster.com> wrote in message news:<3C6997FC...@webmaster.com>...

Well, NOT if the semantics that I need/like/love would become
some day part of POSIX.1-20XX (I won't live longer than that,
probably ;-)) *standard*. After all, the organization is
called "The Open Group" and... just in case I am indeed wrong/
have fallen into "over-engineering" trap, then there are
always more educated people (who designed/implemented all
that stuff) on this group to point it out!

> and sometimes you care about
> the semantics.

Yes, I do. As for *threads* and *cancel*, I have one
more perhaps relevant question:

Do you really want to have something along the lines of
Java's "interrupted()/The interrupted status of the
thread is cleared by this method/isInterrupted()/The
interrupted status of the thread is unaffected by
this method" which would allow you to eat "interrupt/
cancel" exceptions***?! How about thread exit()??

regards,
alexander.

------
[***] interrupt public void interrupt()

Interrupts this thread.
First the checkAccess method of this thread is invoked, which may
cause a SecurityException to be thrown.

If this thread is blocked in an invocation of the wait(), wait(long),
or wait(long, int) methods of the Object class, or of the join(), join
(long), join(long, int), sleep(long), or sleep(long, int), methods of
this class, then its interrupt status will be cleared and it will
receive an InterruptedException.

If this thread is blocked in an I/O operation upon an interruptible
channel then the channel will be closed, the thread's interrupt
status will be set, and the thread will receive a
ClosedByInterruptException.

If this thread is blocked in a Selector then the thread's interrupt
status will be set and it will return immediately from the selection
operation, possibly with a non-zero value, just as if the selector's
wakeup method were invoked.

If none of the previous conditions hold then this thread's interrupt
status will be set.
-------

Well, feel free call me an *idiot*, but I do *NOT* comprehend the
usefulness of Java's "interrupt" model with respect/"in comparison"
to much simpler and robust PTHREAD's cancel and exit "always-rethrow-
exceptions".

Perhaps someone could help me...

David Butenhof

unread,
Feb 13, 2002, 8:14:11 AM2/13/02
to
Alexander Terekhov wrote:

> Yes, I do. As for *threads* and *cancel*, I have one
> more perhaps relevant question:
>
> Do you really want to have something along the lines of
> Java's "interrupted()/The interrupted status of the
> thread is cleared by this method/isInterrupted()/The
> interrupted status of the thread is unaffected by
> this method" which would allow you to eat "interrupt/
> cancel" exceptions***?! How about thread exit()??

The basic problem here is that unlike Java, C lacks exceptions. So there's
no way to do this. As everyone probably knows by now, I think any
implementation that doesn't build cancelation (and thread exit) on top of a
pervasive common exception infrastructure is broken to the point of being
unusable. Nevertheless, the standard doesn't (and can't) require a correct
implementation, so those who do it wrong can get away with it as long as
their users allow them to. <wink, wink, ;-), ;-) >

Still, though, we wrestled with this issue long and hard during the
development of our CMA architecture (the main ancestor of POSIX threads,
which was based on exceptions). We originally had a way to deliver an
arbitrary exception in the context of another thread. However, the more we
got into the (quite elegant) design, the more we came to realise that there
was no way to use this without getting into far more complication, and with
little if any added value, than simply specializing threads and using
cancel. We eventually simplified our grand interrupt scheme closer to the
simplicity of the single "alert" found in several older thread systems.

The main problem is that added information is of no value unless the
threads are so closely synchronized that there are bound to be more
general, convenient, and cleaner ways to communicate. Delivering an
arbitrary exception at an arbitrary asynchronous point is chaos, not
communication! More importantly, this kind of asynchronous "communication"
moves from the structured parallelism of threads back into the messy
codependency of signals. We really don't want to go there.

David Butenhof

unread,
Feb 13, 2002, 8:32:14 AM2/13/02
to
Sergey P. Derevyago wrote:

> David Butenhof wrote:
>> You can either call pthread_join() for each thread you create at some
>> reasonable point, or, if you don't care WHEN they terminate, you can
>> simply create each thread DETACHED.
> BTW was it a good idea to make thread non-detached by default? It seems
> like the most users "expect" their threads "to be detached" by default.

Some do, some don't. However, without a way to dynamically change the
"detached" state of a running thread (which we didn't want to even try),
there's no way to JOIN the initial thread unless the default is "joinable".
We did want the initial thread to be "special" in as few ways as practical
given existing POSIX/UNIX implementation.

One draft actually did change the default to "detached". The change was
later reversed after much consideration. Unfortunately, I can't reconstruct
the reasons and I don't have any meeting notes that mention the change.
Nevertheless, this possibility WAS considered, and even tried; and
rejected. Making a change like this would be really bad now, because many
existing programs would break on a system support a new changed standard.
Which means even a lot of people who'd LIKE to agree with you would fight
hard against you. ;-)

Sergey P. Derevyago

unread,
Feb 13, 2002, 9:35:40 AM2/13/02
to
David Butenhof wrote:
> Some do, some don't. However, without a way to dynamically change the
> "detached" state of a running thread (which we didn't want to even try),
> there's no way to JOIN the initial thread unless the default is "joinable".
Yes, good point.

> One draft actually did change the default to "detached". The change was
> later reversed after much consideration.

Probably, it was decided not to break existing code.

> Which means even a lot of people who'd LIKE to agree with you would fight
> hard against you. ;-)

Please, don't tell them :)

Alexander Terekhov

unread,
Feb 13, 2002, 10:10:13 AM2/13/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6A2BA6...@iobox.com>...

> Alexander Terekhov wrote:
> > > BTW was it a good idea to make thread non-detached by default? It seems like
> > > the most users "expect" their threads "to be detached" by default.
> > But how would you then *join* -- get concurrently invoked function's
> > return value?
> Probably, using something like
>
> pthread_attr_t attr;
> pthread_attr_init (&attr);
> pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
> pthread_create (&thread1, &attr, myfun_1, NULL);
>
> ;))

Yeah, I see. ;-) Perhaps I was not clear enough... look, you could
always detach a joinable thread (IMHO you better do it on thread
termination, with no more references left hanging around), but on
the other hand, there is no way to "undo" a detach "operation".
Personally, I just do not want to care much about such low-level/
tedious things as thread-objects lifetime management. C++ c-tors/
d-tors:smart_ptrs are *smart* enough to do it for me! Also, C++
polymorphism/dynamic_cast is a nice way to make C++-"pthread_exit"
behave as TYPE-SAFE template, which would prohibit/enforce at
runtime the safety of abrupt-"returns". Well, it appears (from
what you wrote below) that you do not use/need it, but to me,
threads are just a mechanism to invoke arbitrary functions
CONCURRENTLY... and most/many functions just tend to return
something -- they are NOT necessarily/likely VOID! IMHO.

> > I think that all these failures to join/detach/pthread_exit-main(),
> > return/pthread_exit some local/stack address and "lets assume that
> > pthread_create makes that pthread_t var update/store visible/in-sync
> > wrt thread creation" bugs ARE the most frequent ones for less
> > experienced/informed/educated threaders, at least that is my
> > personal conclusion/observation after a year or so on this
> > newsgroup.
> I also think so.
> However, I've just reviewed my code and come to the conclusion that the most
> of my threads are detached. So (personally) I don't like "joinable by default"
> threads.
>
> > Anyway, any input/critique/help (and even flames ;-))
> > is greatly appreciated!
> Flames? Hmmm...

Yeah, mixed with some *technical* stuff, if possible. ;-)

regards,
alexander.

Sergey P. Derevyago

unread,
Feb 13, 2002, 10:33:13 AM2/13/02
to
Alexander Terekhov wrote:
> > > But how would you then *join* -- get concurrently invoked function's
> > > return value?
> > Probably, using something like
> >
> > pthread_attr_t attr;
> > pthread_attr_init (&attr);
> > pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
> > pthread_create (&thread1, &attr, myfun_1, NULL);
> >
> > ;))
>
> Yeah, I see. ;-) Perhaps I was not clear enough... look, you could
> always detach a joinable thread
Not, really. In particular, in the case of Java "setDaemon(boolean on) --
This method must be called before the thread is started", period.

> runtime the safety of abrupt-"returns". Well, it appears (from
> what you wrote below) that you do not use/need it, but to me,
> threads are just a mechanism to invoke arbitrary functions
> CONCURRENTLY...

Personally, I tend to use thread pools, so the join operation...
But it seems like you create a new thread for every "arbitrary function
call", don't you? I bet, this group is _not_ a good place for the promotion of
such approach ;))

> and most/many functions just tend to return
> something -- they are NOT necessarily/likely VOID! IMHO.

> > Flames? Hmmm...


> Yeah, mixed with some *technical* stuff, if possible. ;-)

I'll try... ;)

Sol Rosenberg

unread,
Feb 13, 2002, 10:54:25 AM2/13/02
to
Hi,

Thank you David - joining threads is the right solution to my problem!

Jesper

David Butenhof

unread,
Feb 14, 2002, 7:13:59 AM2/14/02
to
Sergey P. Derevyago wrote:

> David Butenhof wrote:
>> Some do, some don't. However, without a way to dynamically change the
>> "detached" state of a running thread (which we didn't want to even try),
>> there's no way to JOIN the initial thread unless the default is
>> "joinable".
> Yes, good point.
>
>> One draft actually did change the default to "detached". The change was
>> later reversed after much consideration.
> Probably, it was decided not to break existing code.

At the time, that was irrelevant; there was no "existing code" because
there wasn't yet a standard.

Certainly we broke a lot of existing "DCE thread" code, but that was
because we made a conscious decision that we would NOT be limited by those
idiots who decided to release a library based on a draft of a standard that
was specifically labelled "DO NOT IMPLEMENT". (As I've explained before in
this newsgroup, by the way, I can freely use the word "idiots" as I was one
of them. While I'm fairly sure I couldn't have talked them out of it, my
sense of guilt is rooted in the fact that I didn't even try because, at the
time, it sounded like fun. ;-) )

>> Which means even a lot of people who'd LIKE to agree with you would fight
>> hard against you. ;-)
> Please, don't tell them :)

Tell them what? ;-) ;-)

Alexander Terekhov

unread,
Feb 14, 2002, 7:22:32 AM2/14/02
to
<c.l.c++ folks, hit PAGE DOWN for C++ related stuff>

"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6A8739...@iobox.com>...


> Alexander Terekhov wrote:
> > > > But how would you then *join* -- get concurrently invoked function's
> > > > return value?
> > > Probably, using something like
> > >
> > > pthread_attr_t attr;
> > > pthread_attr_init (&attr);
> > > pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
> > > pthread_create (&thread1, &attr, myfun_1, NULL);
> > >
> > > ;))
> >
> > Yeah, I see. ;-) Perhaps I was not clear enough... look, you could
> > always detach a joinable thread
> Not, really. In particular, in the case of Java "setDaemon(boolean on) --
> This method must be called before the thread is started", period.

So what? What does this have to do with Pthreads/*C*-way
(i.e. rather error-prone, IMHO) of managing thread-objects/
-resources via pthread_join/_detach() (and detached thread
attribute)?

http://java.sun.com/j2se/1.4/docs/api/java/lang/Thread.html#setDaemon(boolean)

To me, this has nothing to do with the topic/problems
I am trying to address with mythread.c/thread_ptr.txt.
In Pthreads, all thread are NON-"daemons" (see "ders"
bit below, however ;-)) in the sense that the process
terminates on LAST thread termination (unless someone
explicitly exits/aborts or just returns from main()
function; instead of ending initial thread via
pthread_exit, btw, to me, that's just yet another
rather inconvenient "feature", which makes main() a
rather special function (TOO special in my view)...
I would prefer something along the lines of
"thread::main()" that would NOT terminate the process
on return -- would behave just like any other
*thread-routine*!).

> > runtime the safety of abrupt-"returns". Well, it appears (from
> > what you wrote below) that you do not use/need it, but to me,
> > threads are just a mechanism to invoke arbitrary functions
> > CONCURRENTLY...
> Personally, I tend to use thread pools, so the join operation...
> But it seems like you create a new thread for every "arbitrary function
> call", don't you? I bet, this group is _not_ a good place for the promotion of
> such approach ;))

No, I do not really want to "create a new thread for
every 'arbitrary function call'". All I want to is to
PROGRAM threads in less error-prone and more expressive
*LANGUAGE*, I mean *C++* and things along the lines of:
(NOT real code - just ideas)

#include <thread>

void write_message( const char* );

void thread::main()
{
new_thread( write_message,"Hello..." )->join();
new_thread( write_message,"World!!!");
}

---
#include <thread>

int my_operation( int );

class my_fancy_thread : public thread {
public:

class attr : public thread::attr {
public: /*...add some fancy stuff...*/ };

/*...add some fancy stuff...*/ };

// called by thread::attr::new_thread<> function(s)
thread* create_thread_object( const my_fancy_thread::attr& );

// overloads NOOP defaults; called in the context of NEW thread
void on_thread_start( my_fancy_thread* );
void on_thread_termination( my_fancy_thread* );

void thread::main()
{
joinable_thread_ptr< int,my_fancy_thread > pthread =
my_fancy_thread::attr().set_system_contention_scope()
.set_sched_policy( sched::FIFO )
.set_fancy_blabla()
.set_initialy_suspended( true )
.set_daemon( true ) // ders, that's for you ;-)
.new_thread( my_operation,
some_magic_number );

/*...*/
pthread->start();

// result is stored in joinable_thread_object< result,thread_type >
// managed by smart thread ptr (thread_ptr<> and joinable_thread_ptr<>)
int* presult = pthread->timedjoin( timeout::relative( 1000 ) );

if ( thread::timedout( presult ) &&
thread::canceled( presult = pthread->cancel().join() ) ) {

cout << "OOPS: timedout and canceled!";

}
else {

cout << "DONE: " << *presult;

}

return 0;

}

regards,
alexander.

Sergey P. Derevyago

unread,
Feb 14, 2002, 7:42:35 AM2/14/02
to
Alexander Terekhov wrote:
> > > Yeah, I see. ;-) Perhaps I was not clear enough... look, you could
> > > always detach a joinable thread
> > Not, really. In particular, in the case of Java "setDaemon(boolean on) --
> > This method must be called before the thread is started", period.
> So what? What does this have to do with Pthreads/*C*-way
> (i.e. rather error-prone, IMHO) of managing thread-objects/
> -resources via pthread_join/_detach() (and detached thread
> attribute)?
I said about threads "in general". Even about "Java threads" ;))

BTW I plan to create yet another threads library (for some new language) and
now I'm trying to find the rationale of certain "thread quirks". In
particular, I don't like the "joinable by default" quirk.

> No, I do not really want to "create a new thread for
> every 'arbitrary function call'". All I want to is to
> PROGRAM threads in less error-prone and more expressive
> *LANGUAGE*, I mean *C++*

BTW take a look at
http://groups.google.com/groups?as_umsgid=3C343DED...@iobox.com The
point is parametrized namespaces with regard to MT.

Alexander Terekhov

unread,
Feb 14, 2002, 9:54:14 AM2/14/02
to
David Butenhof <David.B...@compaq.com> wrote in message news:<DEta8.55$1h5...@news.cpqcorp.net>...
[...]

> Still, though, we wrestled with this issue long and hard during the
> development of our CMA architecture (the main ancestor of POSIX threads,
> which was based on exceptions). We originally had a way to deliver an
> arbitrary exception in the context of another thread. However, the more we
> got into the (quite elegant) design, the more we came to realise that there
> was no way to use this without getting into far more complication, and with
> little if any added value, than simply specializing threads and using
> cancel. We eventually simplified our grand interrupt scheme closer to the
> simplicity of the single "alert" found in several older thread systems.
>
> The main problem is that added information is of no value unless the
> threads are so closely synchronized that there are bound to be more
> general, convenient, and cleaner ways to communicate. Delivering an
> arbitrary exception at an arbitrary asynchronous point is chaos, not
> communication! More importantly, this kind of asynchronous "communication"
> moves from the structured parallelism of threads back into the messy
> codependency of signals. We really don't want to go there.

Well, I did not really mean something along the lines of Java's
*deprecated* STOP/"ThreadDeath" async-unsafe-"exception"! My point
is/was that Pthreads *C*-cancel is SIMPLE and ROBUST and I just
love it (EAGAINs aside ;-). Also, I think that with some "standard"
cancel_e exception (in POSIX++.1-200X ;-)) it should be possible
to define cancel-state/-type and "STOPPED-unwinding" interactions
such that one could then catch cancellation exceptions, just eat
them (do not rethrow) and continue do something... Well, I am not
quite sure whether it is really useful, but that is the way how
Java does it (unless I am missing something or have a wrong
understanding).

The idea is that if someone really want/need it he or she could
easily add/build it ON TOP of true-exception-based Pthread-
cancellation, which itself should know nothing about "interrupted
status" (that's user-coded add-on... or perhaps something that
could magically appear due to some
PTHREAD_C_PLUS_PLUS_CREATE_INTERRUPTIBLE *non-default* thread
attr's value ;-))!

Anyway, what remains a real MYSTERY to me, is how JVM folks
implement their thread's "interrupt" model layered on top of
current (*C* without standard cancel_e exception and some
way to catch-and-not-rethrow-it) Pthreads/POSIX?!

Perhaps someone could illuminate...

regards,
alexander.

Pete Becker

unread,
Feb 14, 2002, 10:28:32 AM2/14/02
to
Alexander Terekhov wrote:
>
> Anyway, what remains a real MYSTERY to me, is how JVM folks
> implement their thread's "interrupt" model layered on top of
> current (*C* without standard cancel_e exception and some
> way to catch-and-not-rethrow-it) Pthreads/POSIX?!
>
> Perhaps someone could illuminate...
>

As usual, Java does far less than it sounds like it does. Most of the
time, calling interrupt() just sets a flag, and the programmer is
responsible for checking it. If a thread is blocked in wait() (think
pthread_cond_wait) or in an I/O operation it unblocks, does some
cleanup, and throws an object of class InterruptedException. So the
implementation is straightforward: before blocking a thread makes a note
of the condition variable that it's blocking on. When called,
interrupt() sets the interrupted flag, and if the thread is blocked it
signals the condition variable. When the thread wakes up it checks the
interrupted flag. This can all be done in the library. In mongrel
pseudo-code:

// blocking code:
blocker = /* whatever */
while (!done && !interrupted)
pthread_cond_wait(blocker, ...)
blocker = null;
if (interrupted)
throw new InterruptedException();

// interrupt:
thread.interrupted = true;
if (thread.blocker != null)
pthread_cond_signal(thread.blocker);

On the other hand, the documentation for Thread.sleep says that it
throws InterruptedException if the thread is interrupted, but doesn't
mention whether that cuts the sleep short. It seems like it should, but
that doesn't match the specification for interrupt(), paraphrased above,
which lists the cases I mentioned where the exception is thrown, and
says that in all other cases it just sets the interrupted flag.

--
Pete Becker
Dinkumware, Ltd. (http://www.dinkumware.com)

Chris Smith

unread,
Feb 14, 2002, 12:24:16 PM2/14/02
to
Pete Becker wrote ...

> As usual, Java does far less than it sounds like it does. Most of the
> time, calling interrupt() just sets a flag, and the programmer is
> responsible for checking it. If a thread is blocked in wait() (think
> pthread_cond_wait) or in an I/O operation it unblocks, does some
> cleanup, and throws an object of class InterruptedException.

This is incorrect. If a thread is blocked in most I/O, interrupt() again
simply sets the flag. Newly in the 1.4 version, you can create an
interruptable I/O channel, which throws a ClosedByInterruptException
(*not* an InterruptedException) if an interrupt occurs.

In any case, this is a good thing. Otherwise, you'd end up with the same
problems as other asynchronous exceptions: you would end up having
threads release monitors by stack-unwinding while the object data is
still potentially inconsistent. Under the existing system,
InterruptedException (and ClosedByInterruptException) can be made into
checked exceptions, and the programmer calling those methods can perform
any needed cleanup before the monitors are released.

By allowing completely asynchronous InterruptedExceptions, you'd have an
infinitely recursive problem of "what if I'm interrupted while cleaning
up after an interrupt?"

> On the other hand, the documentation for Thread.sleep says that it
> throws InterruptedException if the thread is interrupted, but doesn't
> mention whether that cuts the sleep short. It seems like it should, but
> that doesn't match the specification for interrupt(), paraphrased above,
> which lists the cases I mentioned where the exception is thrown, and
> says that in all other cases it just sets the interrupted flag.

My copy of the API spec lists the Thread.sleep methods as a situation in
which InterruptedException is thrown. On the theory that you may have
been reading older documentation, I checked the spec for 1.3, which just
says that the method "interrupts this thread", and nothing more, and I
suspect anything older does the same... woefully inadequate, but does not
exclude the possibility of Thread.sleep(long) throwing the exception.

To be honest, I much prefer that they don't list situations in which
InterruptedException is thrown, since third-party library implementors
may want to declare which of their methods throw the exception on their
own.

As for whether the sleep is cut short, I believe the theory behind this
one is this: First, it's clearly the case that the *intent* is that the
effects of the sleep call no longer be in effect, and any implementation
worth its salt will do so. Second, since it's perfectly legal for a
thread to not execute for an arbitrary time anyway, the spec can't
require that the thread immediate start running again.

Chris Smith

Pete Becker

unread,
Feb 14, 2002, 12:43:35 PM2/14/02
to
Chris Smith wrote:
>
> Pete Becker wrote ...
> > As usual, Java does far less than it sounds like it does. Most of the
> > time, calling interrupt() just sets a flag, and the programmer is
> > responsible for checking it. If a thread is blocked in wait() (think
> > pthread_cond_wait) or in an I/O operation it unblocks, does some
> > cleanup, and throws an object of class InterruptedException.
>
> This is incorrect. If a thread is blocked in most I/O, interrupt() again
> simply sets the flag. Newly in the 1.4 version, you can create an
> interruptable I/O channel, which throws a ClosedByInterruptException
> (*not* an InterruptedException) if an interrupt occurs.

Yup, wrong exception. This wasn't intended as a treatise on Java, but a
sketch of what interrupt does.

> My copy of the API spec lists the Thread.sleep methods as a situation in
> which InterruptedException is thrown. On the theory that you may have
> been reading older documentation, I checked the spec for 1.3, which just
> says that the method "interrupts this thread", and nothing more, and I
> suspect anything older does the same... woefully inadequate, but does not
> exclude the possibility of Thread.sleep(long) throwing the exception.

I paraphrased the documentation for Thread.interrupt() from JDK 1.4.

Alexander Terekhov

unread,
Feb 15, 2002, 11:15:22 AM2/15/02
to
Pete Becker <peteb...@acm.org> wrote in message news:<3C6BF747...@acm.org>...

> Chris Smith wrote:
> >
> > Pete Becker wrote ...
> > > As usual, Java does far less than it sounds like it does. Most of the
> > > time, calling interrupt() just sets a flag, and the programmer is
> > > responsible for checking it. If a thread is blocked in wait() (think
> > > pthread_cond_wait) or in an I/O operation it unblocks, does some
> > > cleanup, and throws an object of class InterruptedException.
> >
> > This is incorrect. If a thread is blocked in most I/O, interrupt() again
> > simply sets the flag. Newly in the 1.4 version, you can create an
> > interruptable I/O channel, which throws a ClosedByInterruptException
> > (*not* an InterruptedException) if an interrupt occurs.

Uhmm.. and how would you implement something along the lines of:
(File[Input/Output]Stream.getChannel(), for example)

http://java.sun.com/j2se/1.4/docs/api/java/nio/channels/FileChannel.html
(interruptible read/write(ByteBuffer src,long position))

if all you have is just POSIX read()/write() Pthread-*C*-cancellation
points and you do NOT have things along the lines of <aio.h>?

regards,
alexander.

Alexander Terekhov

unread,
Feb 15, 2002, 1:01:39 PM2/15/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6BB0BB...@iobox.com>...
[...]

> BTW I plan to create yet another threads library (for some new language) and
> now I'm trying to find the rationale of certain "thread quirks". In
> particular, I don't like the "joinable by default" quirk.

Hmmm.. seems that you still do NOT get it :( Just forget
that "detach" thing! That's low level stuff and its
done AUTOMATICALLY under the cover IF you never JOIN!
see http://www.terekhov.de/mythread.c

Also, please consider again that "Hello world" example
I've posted previously in this thread:

#include <thread>

void write_message( const char* );

void thread::main()
{
new_thread( write_message,"Hello..." )->join();
new_thread( write_message,"World!!!");
}

Here we have only one thread that is JOINED -- "Hello..."
thread. Both "World!!!" and INITIAL (main) threads ARE
DETACHED automatically on their termination (or return
from new_thread() -- there is a race with respect to
"World!!!" thread termination). And for the last thread
it does not really matter whether it gets detached or not
because the whole process terminates on LAST thread termination
(btw, even native Win-threads do this).

Still something NOT clear, ders?

> BTW take a look at
> http://groups.google.com/groups?as_umsgid=3C343DED...@iobox.com The
> point is parametrized namespaces with regard to MT.

I think that the point you are trying to make with
"parametrized namespace std" is fully addressed here:

http://groups.google.com/groups?as_umsgid=3AC4C103...@compaq.com

and here:

http://groups.google.com/groups?as_umsgid=3AC75373.21EFE459%40dvv.org

regards,
alexander.

Pete Becker

unread,
Feb 15, 2002, 7:26:41 PM2/15/02
to
Alexander Terekhov wrote:
>
> Uhmm.. and how would you implement something along the lines of:
> (File[Input/Output]Stream.getChannel(), for example)
>
> if all you have is just POSIX read()/write() Pthread-*C*-cancellation
> points and you do NOT have things along the lines of <aio.h>?
>

Sorry, haven't implemented that yet. <g>

Pete Becker

unread,
Feb 15, 2002, 8:33:38 PM2/15/02
to
Alexander Terekhov wrote:
>
> Uhmm.. and how would you implement something along the lines of:
> (File[Input/Output]Stream.getChannel(), for example)
>
> http://java.sun.com/j2se/1.4/docs/api/java/nio/channels/FileChannel.html
> (interruptible read/write(ByteBuffer src,long position))
>
> if all you have is just POSIX read()/write() Pthread-*C*-cancellation
> points and you do NOT have things along the lines of <aio.h>?
>

Despite my other answer, there doesn't appear to be a problem here. The
requirement as given for Thread.interrupt is:

If this thread is blocked in an I/O operation upon a Channel


then the channel will be closed, the thread's interrupt status
will be set, and the thread will receive a
ClosedByInterruptException.

Contrast with:

If this thread is blocked in a Selector then the thread's
interrupt status will be set and it will return immediately
from the selection operation, possibly with a non-zero value,
just as if the selector's wakeup method were invoked.

In particular, note the words "it will return immediately," which have
no analog in the specification for the behavior of an I/O operation. So
I/O operations are not required to respond immediately on a call to
interrupt.

Sergey P. Derevyago

unread,
Feb 16, 2002, 8:00:18 AM2/16/02
to
Alexander Terekhov wrote:
> void thread::main()
> {
> new_thread( write_message,"Hello..." )->join();
> new_thread( write_message,"World!!!");
> }
>
> Here we have only one thread that is JOINED -- "Hello..."
> thread. Both "World!!!" and INITIAL (main) threads ARE
> DETACHED automatically on their termination
I.e. I _must_ inform thread from the beginning that it can be joined.
Correct?

> > http://groups.google.com/groups?as_umsgid=3C343DED...@iobox.com The
> > point is parametrized namespaces with regard to MT.
> I think that the point you are trying to make with
> "parametrized namespace std" is fully addressed here:
> http://groups.google.com/groups?as_umsgid=3AC4C103...@compaq.com
> and here:
> http://groups.google.com/groups?as_umsgid=3AC75373.21EFE459%40dvv.org

Not, really. These links point to the "do we really need threads?" issue.

While the "parametrized namespace std" issue may help us to write
"thread-neutral" code. Fill the difference! :)

Alexander Terekhov

unread,
Feb 16, 2002, 10:23:41 AM2/16/02
to
Pete Becker <peteb...@acm.org> wrote in message news:<3C6DB6F2...@acm.org>...
[...]

> In particular, note the words "it will return immediately," which have
> no analog in the specification for the behavior of an I/O operation. So
> I/O operations are not required to respond immediately on a call to
> interrupt.

test_cancel();
state = set_cancel_state( NO_CANCEL );
read_10MB_from_tape(); // does NOT throw now
set_cancel_state( state );
test_cancel();

IS JUST SILLY, IMHO!

regards,
alexander.

Pete Becker

unread,
Feb 16, 2002, 2:18:29 PM2/16/02
to

There are many silly things in Java.

Alexander Terekhov

unread,
Feb 16, 2002, 2:51:13 PM2/16/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6E57E2...@iobox.com>...

> Alexander Terekhov wrote:
> > void thread::main()
> > {
> > new_thread( write_message,"Hello..." )->join();
> > new_thread( write_message,"World!!!");
> > }
> >
> > Here we have only one thread that is JOINED -- "Hello..."
> > thread. Both "World!!!" and INITIAL (main) threads ARE
> > DETACHED automatically on their termination
> I.e. I _must_ inform thread from the beginning that it can be joined.
> Correct?

No. Does this help:

#include <thread>

void write_message( const char* );

thread_ptr pmain_thread( thread::current() );

void cancel_main_thread()
{ pmain_thread->cancel(); }

void thread::main()
{
new_thread( cancel_main_thread );
// new_thread() is not a cancellation point


new_thread( write_message,"Hello..." )->join();
new_thread( write_message,"World!!!");

// sleep() is a cancellation point
for ( ;; ) { thread::sleep( timeout::relative( 1000 ) ); /**/ }
}

also, consider another "example":

#include <thread>

void write_message( const char* );

joinable_thread_ptr< void > pmain_thread( thread::current() );

void cancel_and_join_main_thread()
{ pmain_thread->cancel().join(); }

void thread::main()
{
new_thread( cancel_and_join_main_thread );
// new_thread() is not a cancellation point


new_thread( write_message,"Hello..." )->join();
new_thread( write_message,"World!!!");

// sleep() is a cancellation point
for ( ;; ) { thread::sleep( timeout::relative( 1000 ) ); /**/ }
}

regards,
alexander.

Pete Becker

unread,
Feb 16, 2002, 2:54:05 PM2/16/02
to

Yup. But that's not required, either. The documentation is silent on how
soon a channel I/O operation must respond to a call to interrupt. So any
time from immediately to whenever is permitted. Obviously immediately is
preferable, but if it's unimplementable then it has to be sometime
later.

Alexander Terekhov

unread,
Feb 16, 2002, 4:52:50 PM2/16/02
to
Pete Becker <peteb...@acm.org> wrote in message news:<3C6EB8DD...@acm.org>...

That's OK. I am just trying to find something that would
explain to me WHY the hell Java designers just refused to
adopt *Pthreads* cancellation model (and anything else
along the lines of simple/robust/"fast" cond.vars
(vs poor Object.wait family), etc...) !?

regards,
alexander.

Pete Becker

unread,
Feb 16, 2002, 5:08:52 PM2/16/02
to
Alexander Terekhov wrote:
>
> That's OK. I am just trying to find something that would
> explain to me WHY the hell Java designers just refused to
> adopt *Pthreads* cancellation model (and anything else
> along the lines of simple/robust/"fast" cond.vars
> (vs poor Object.wait family), etc...) !?
>

My view is that the Java libraries were designed by beginners. You can
tell because they make a bunch of beginner's mistakes. And that's also
why Java has so much appeal for beginners -- it's designed the way they
think.

Sergey P. Derevyago

unread,
Feb 17, 2002, 6:19:12 AM2/17/02
to
Alexander Terekhov wrote:
> > > thread. Both "World!!!" and INITIAL (main) threads ARE
> > > DETACHED automatically on their termination
> > I.e. I _must_ inform thread from the beginning that it can be joined.
> > Correct?
> No. Does this help:
I.e. (in your implementation) it's possible to join threads that wasn't
informed from the beginning that they can be joined?
Too bad. Such implementation has obvious race condition (pthread_ts, unlike
pid_ts, can easily be reused by newborn threads).

Alexander Terekhov

unread,
Feb 17, 2002, 11:09:02 AM2/17/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6F91B0...@iobox.com>...

> Alexander Terekhov wrote:
> > > > thread. Both "World!!!" and INITIAL (main) threads ARE
> > > > DETACHED automatically on their termination
> > > I.e. I _must_ inform thread from the beginning that it can be joined.
> > > Correct?
> > No. Does this help:
> I.e. (in your implementation) it's possible to join threads that wasn't
> informed from the beginning that they can be joined?

Ever heard of things along the lines of ref.counting C++ smart_ptrs?

The only difference with respect to thread objects managed by some
C++ lib is that on destruction of LAST ref/ptr, the C++ add-on
code invoked by destructor does something along the lines of:

if ( !managed_thread.was_joined() )
detach( managed_thread.this_pthread_t );

Still something NOT clear, ders?

> Too bad. Such implementation has obvious race condition (pthread_ts, unlike


> pid_ts, can easily be reused by newborn threads).

How many bottles of GOOD German Bier should I send to
you PER RACE CONDITION that you HAVE ALREADY identified
here:

http://www.terekhov.de/mythread.c

<?!?>

regards,
alexander.

Sergey P. Derevyago

unread,
Feb 17, 2002, 12:06:06 PM2/17/02
to
Alexander Terekhov wrote:
> > Too bad. Such implementation has obvious race condition (pthread_ts, unlike
> > pid_ts, can easily be reused by newborn threads).
> How many bottles of GOOD German Bier should I send to
> you PER RACE CONDITION that you HAVE ALREADY identified
> here: http://www.terekhov.de/mythread.c
IMHO about 20 bottles would be OK.

Well, consider the following code:

void f()
{
pthread_t thid=start_new_tread(/* ... */);
g();
join(thid);
}
And the following scenario:

1. thid thread was started.
2. main thread enters g().
3. thid thread exits.
4. main thread leaves g().

Now:
- thid was invalidated and join(thid) is an error or
- g() have created another thread which reuses thid, so join(thid) is valid
but have the different meaning.

The point is that you can't prevent this race condition if newborn thread
doesn't know that it can be joined from the beginning.

Here is your race condition. Where is my "GOOD German Bier"?!

Alexander Terekhov

unread,
Feb 17, 2002, 6:55:56 PM2/17/02
to
"Sergey P. Derevyago" <non-ex...@iobox.com> wrote in message news:<3C6FE2FE...@iobox.com>...

> Alexander Terekhov wrote:
> > > Too bad. Such implementation has obvious race condition (pthread_ts, unlike
> > > pid_ts, can easily be reused by newborn threads).
> > How many bottles of GOOD German Bier should I send to
> > you PER RACE CONDITION that you HAVE ALREADY identified
> > here: http://www.terekhov.de/mythread.c
> IMHO about 20 bottles would be OK.

OK.

> Well, consider the following code:
>
> void f()
> {
> pthread_t thid=start_new_tread(/* ... */);

^^^^^^^^^ ^^^^^^^^^^^^^^^

On which line number (in http://www.terekhov.de/mythread.c)
did you find that misterious pthread_t start_new_tread()?
Had someone hacked my poor website just in time for your
download?! Gee!!

> g();
> join(thid);
> }
> And the following scenario:
>
> 1. thid thread was started.
> 2. main thread enters g().
> 3. thid thread exits.
> 4. main thread leaves g().
>
> Now:
> - thid was invalidated and join(thid) is an error or
> - g() have created another thread which reuses thid, so join(thid) is valid
> but have the different meaning.
>
> The point is that you can't prevent this race condition if newborn thread
> doesn't know that it can be joined from the beginning.
>
> Here is your race condition. Where is my "GOOD German Bier"?!

Sorry, race condition(s) (in the http://www.terekhov.de/mythread.c code)
FIRST; "GOOD German Bier" - NEXT/WILL FOLLOW! I promise.

regards,
alexander.

0 new messages