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
> 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 ]-----/
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.
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.
> 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
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.
> 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
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? ;))
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...
> 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 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. ;-)
> 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 :)
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.
> 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... ;)
Thank you David - joining threads is the right solution to my problem!
Jesper
> 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? ;-) ;-)
"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.
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.
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.
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)
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
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.
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.
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.
Sorry, haven't implemented that yet. <g>
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.
> > 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! :)
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.
There are many silly things in Java.
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.
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.
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.
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.
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.
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"?!
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.