public inbox for pthreads-win32@sourceware.org
 help / color / mirror / Atom feed
* C++ cleanup handler execution
       [not found] <000601bf578e$3c89a750$208e08d0@fflaptop>
@ 2000-01-05 17:35 ` Ross Johnson
  2000-01-06 14:11   ` Kevin D. Clark
  0 siblings, 1 reply; 10+ messages in thread
From: Ross Johnson @ 2000-01-05 17:35 UTC (permalink / raw)
  To: Fred Forester; +Cc: Pthreads Developers List

On Wed, 5 Jan 2000, Fred Forester wrote:

> Hi Ross, 
> 
> I can't use the mail list due to  my ISP's spam policy. 
> 
> I have a version of pthreads that builds with the new MING egcs 2.9x
> w/ msvcrt. it C++ exceptions handling seems to be thread safe now. 
> 
> The destructor for the C++ class wraper used for cancel cleanup 
> was not getting called for some reason. I replaced that with a LIFO 
> stack chained from the pthread_t object.  linuxthreads seem to handle 
> it this way. also have gmake files for both ming and MSVC. 
> can send the mess if you want to sort through it.
> 
> Fred Forester

Hi Fred,

Tests to explicitly check cleanup handler execution were missing
from the test suite, which would explain why the problem hasn't been
noticed already. I've just written three more tests for this which
pass under the SEH implementation. Could you grab these from the CVS
repository and run them with your mingw build. They are called
cleanup*.c in the tests directory.

http://sourceware.cygnus.com/cgi-bin/cvsweb.cgi/pthreads/?cvsroot=pthreads-win32

I'd like to retain the C++ destructor approach and fix whatever is
causing the problem you see. I'll forward your email to the list for
comment though.

Thanks again.

Ross

+----------------------+---+
| Ross Johnson         |   | E-Mail: rpj@ise.canberra.edu.au
| Info Sciences and Eng|___|
| University of Canberra   | FAX:    +61 6 2015227
| PO Box 1                 |
| Belconnen  ACT    2616   | WWW:    http://willow.canberra.edu.au/~rpj/
| AUSTRALIA                |
+--------------------------+


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-05 17:35 ` C++ cleanup handler execution Ross Johnson
@ 2000-01-06 14:11   ` Kevin D. Clark
  2000-01-06 18:17     ` Ross Johnson
  0 siblings, 1 reply; 10+ messages in thread
From: Kevin D. Clark @ 2000-01-06 14:11 UTC (permalink / raw)
  To: Ross Johnson; +Cc: Fred Forester, Pthreads Developers List

Ross Johnson writes:

> On Wed, 5 Jan 2000, Fred Forester wrote:
>
> > I have a version of pthreads that builds with the new MING egcs 2.9x
> > w/ msvcrt. it C++ exceptions handling seems to be thread safe now. 

I'm playing around with pthreads/C++ exceptions today.  I'm seeing the
following:

Environment: VC++ 6.0 on a NT 4.x box with service pack 5.
             Pthreads-win32 snapshot 1999-11-02
	     I am compiling a C++ program that uses C++ exceptions,
             pthread_cancel(), pthread_cleanup_push(), and
             pthread_cleanup_pop(). 
	     
Also:  I'm not exactly an experienced Windows programmer, so please
       forgive me if anything that I write seems to be odd.

	     	     
I am seeing the following compile errors:

: TcpWriter3.cc
: TcpWriter3.cc(346) : warning C4509: nonstandard extension used: 'run' uses SEH a
: nd '_guard_synch_' has destructor
:         TcpWriter3.cc(341) : see declaration of '_guard_synch_'
: TcpWriter3.cc(379) : warning C4509: nonstandard extension used: 'run' uses SEH a
: nd 'bufStrm' has destructor
:         TcpWriter3.cc(372) : see declaration of 'bufStrm'
: TcpWriter3.cc(379) : warning C4509: nonstandard extension used: 'run' uses SEH a
: nd '_guard_synch_' has destructor
:         TcpWriter3.cc(361) : see declaration of '_guard_synch_'
: TcpWriter3.cc(392) : error C2712: Cannot use __try in functions that require object unwinding

So I went poking around in the code to see what was going on here.  I
ran my code through the preprocessor and noticed that "__try" was
being placed in my code.

So I looked in pthread.h and looked at the following code:
(slightly edited for brevity)

#ifdef _MSC_VER
	/*
	 * WIN32 SEH version of cancel cleanup.
	 */

/* kclark: stuff with __try is here */
...
	 
#else /* _MSC_VER */

#ifndef __cplusplus

	/*
	 * C implementation of PThreads cancel cleanup
	 */

...

#else /* !__cplusplus */

	/*
	 * C++ version of cancel cleanup.
	 * - John E. Bossom.
	 */
...
#endif /* !__cplusplus */

#endif /* _MSC_VER */


Remember, I'm getting the SEH version of the cancel cleanup code.
Now, it is my understanding that I shouldn't be using the SEH stuff in
my C++ environment.

Assuming I'm right about this, I don't know if checking for _MSC_VER
in the code is correct.  The Microsoft VC++ documentation that I have
says that:

: Compiler                           _MSC_VER value
:    --------                           --------------
:    C Compiler version 6.0                  600
:    C/C++ compiler version 7.0              700
:    Visual C++, Windows, version 1.0        800
:    Visual C++, 32-bit, version 1.0         800
:    Visual C++, Windows, version 2.0        900
:    Visual C++, 32-bit, version 2.x         900
:    Visual C++, 32-bit, version 4.0         1000
:    Visual C++, 32-bit, version 5.0         1100
(and I see "1200" with the VC++ 6.x compiler)



After modifying the code a little bit, I am able to get past these
compile errors.  I'm not quite yet at the point where I'm able to run
my test program though.

So I guess my questions are as follows:

1:  is my assumption correct that I shouldn't be using the SEH cleanup
    code in this C++ environment?

2:  If my assumption is correct in question #1, how should the
    "_MSC_VER check" be modified?
        
2:  Are there any obvious caveats that I should look out for when
    using the C++ cleanup code?  For example, while I was playing around
    with this, I changed the definition of this:

#define pthread_cleanup_push( _rout, _arg ) \
        { \
	    PThreadCleanup  cleanup((void (PT_STDCALL *)(void *))(_rout), \
				    (void *) (_arg) );
    to be like this:
				    
#define pthread_cleanup_push( _rout, _arg ) \
        { \
	    PThreadCleanup  cleanup((void (*)(void *))(_rout), \
				    (void *) (_arg) );
				    
because I was having a hard time compiling my code any other way.  Am
I going to get bitten by any subtle calling convention bugs here?
Should I have had to modify this code in the first place? (it compiles
and runs fine on Solaris and Linux)


Assuming that I get this working, of course I will be more than glad
to provide you with any changes that I made to the code.


Thanks for any assistance you can provide!  And thanks for such a
high-quality pthreads implementation!

--kevin
-- 
Kevin D. Clark          |                          |
kclark@NOSPAM.ctron.com | kdcNOSPAM@alumni.unh.edu |  Give me a decent UNIX
Cabletron Systems, Inc. | PGP Key Available        | and I can move the world
Durham, N.H. (USA)      |                          |

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-06 14:11   ` Kevin D. Clark
@ 2000-01-06 18:17     ` Ross Johnson
  2000-01-14  8:19       ` Kevin D. Clark
  0 siblings, 1 reply; 10+ messages in thread
From: Ross Johnson @ 2000-01-06 18:17 UTC (permalink / raw)
  To: Kevin D. Clark; +Cc: Fred Forester, Pthreads Developers List

On Thu, 6 Jan 2000, Kevin D. Clark wrote:

> Environment: VC++ 6.0 on a NT 4.x box with service pack 5.
>              Pthreads-win32 snapshot 1999-11-02
> 	     I am compiling a C++ program that uses C++ exceptions,
>              pthread_cancel(), pthread_cleanup_push(), and
>              pthread_cleanup_pop(). 
[snip]
> 	     
> So I went poking around in the code to see what was going on here.  I
> ran my code through the preprocessor and noticed that "__try" was
> being placed in my code.
> 
[snip]
> 
> Remember, I'm getting the SEH version of the cancel cleanup code.
> Now, it is my understanding that I shouldn't be using the SEH stuff in
> my C++ environment.
> 
> Assuming I'm right about this, I don't know if checking for _MSC_VER
> in the code is correct.  The Microsoft VC++ documentation that I have
> says that:
> 

Hi Kevin,

I agree that _MSC_VER needs to be changed to be more specific around
SEH related code.

Presumably something like the following should be used:

#if defined(_MSC_VER) && ! defined(__cplusplus)

or perhaps this might be tighter:

#if defined(_MSC_VER) && defined(_INC_EXCPT)

I'm also wondering if it's worth building the library only with C++
EH. That is, removing the SEH implementation, but not before
soliciting comments from the list. I've never actually built the
library using MSVC and C++ EH.

>         
> 2:  Are there any obvious caveats that I should look out for when
>     using the C++ cleanup code?  For example, while I was playing around
>     with this, I changed the definition of this:
> 
> #define pthread_cleanup_push( _rout, _arg ) \
>         { \
> 	    PThreadCleanup  cleanup((void (PT_STDCALL *)(void *))(_rout), \
> 				    (void *) (_arg) );
>     to be like this:
> 				    
> #define pthread_cleanup_push( _rout, _arg ) \
>         { \
> 	    PThreadCleanup  cleanup((void (*)(void *))(_rout), \
> 				    (void *) (_arg) );
> 				    
> because I was having a hard time compiling my code any other way.  Am
> I going to get bitten by any subtle calling convention bugs here?
> Should I have had to modify this code in the first place? (it compiles
> and runs fine on Solaris and Linux)
> 

PT_STDCALL is defined in the current version of pthread.h as:

#ifdef __MINGW32__
#define PT_STDCALL
#else
#define PT_STDCALL __stdcall
#endif

In the version that you have (snap-99-11-02) it's defined in
implement.h, which applications don't (must not) include. That was
an omission.

> 
> Thanks for any assistance you can provide!  And thanks for such a
> high-quality pthreads implementation!
> 

On behalf of all the contributors, thanks. And thank you for the
feedback and bug report. Your fix should be in the next snapshot.

I'm in the process of automating the build/test cycle so that I can
easily test both library and applications in all of the following
environments and cross-environments.

Eg.
	   Applications | SEH | C++ | G++ |  C  | GCC |
	Library		|     |     |     |     |     |
	----------------+-----+-----+-----+-----+-----+
	SEH		|  X  |  X  |  X  |  X  |  X  |
	----------------+-----+-----+-----+-----+-----+
	C++ (MSC)	|  X  |  X  |  X  |  X  |  X  |
	----------------+-----+-----+-----+-----+-----+
	G++ (GNU)	|  ?  |  ?  |  X  |  ?  |  X  |
	----------------+-----+-----+-----+-----+-----+

'?' indicates combinations that I'm not sure are doable.

Ross

+----------------------+---+
| Ross Johnson         |   | E-Mail: rpj@ise.canberra.edu.au
| Info Sciences and Eng|___|
| University of Canberra   | FAX:    +61 6 2015227
| PO Box 1                 |
| Belconnen  ACT    2616   | WWW:    http://willow.canberra.edu.au/~rpj/
| AUSTRALIA                |
+--------------------------+


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-06 18:17     ` Ross Johnson
@ 2000-01-14  8:19       ` Kevin D. Clark
  2000-01-14  8:27         ` Kevin D. Clark
  2000-06-14 18:06         ` Question about condition variable Taci Ãœlker
  0 siblings, 2 replies; 10+ messages in thread
From: Kevin D. Clark @ 2000-01-14  8:19 UTC (permalink / raw)
  To: Pthreads Developers List

Ross Johnson writes:

> I'm in the process of automating the build/test cycle so that I can
> easily test both library and applications in all of the following
> environments and cross-environments.

OK, I might have a small test program for you to include in your test
suite.

The reason why I'm sending it to you is because I don't think that it
is working correctly.  Specifically, I can't seem to get the cleanup
handler that goes along with pthread_cleanup_push() and
pthread_cancel() to be called.  I'm currently trying to figure out why
this is happening.

Just as a reminder, my environment:

     VC++ 6.0 on a NT 4.x box with service pack 5.
     Pthreads-win32 snapshot 1999-11-02

Any suggestions as to why this is happening would be greatly
appreciated.  Thanks!

--kevin

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-14  8:19       ` Kevin D. Clark
@ 2000-01-14  8:27         ` Kevin D. Clark
  2000-01-14  8:30           ` Kevin D. Clark
  2000-01-14  8:36           ` Kevin D. Clark
  2000-06-14 18:06         ` Question about condition variable Taci Ãœlker
  1 sibling, 2 replies; 10+ messages in thread
From: Kevin D. Clark @ 2000-01-14  8:27 UTC (permalink / raw)
  To: Pthreads Developers List

Sorry, in my previous email my test file got garbled.  
My fault.

--kevin

Here's the test file:


// this is a C++ program

#ifdef __unix
#include <unistd.h>
#else

#endif
#include <pthread.h>
#include "stdio.h"

void *canceledRoutine(void *), *anotherRoutine(void *);

pthread_t canceledThread, anotherThread;

int
main(int argc, char *argv[])
{
  int i = 0;
  pthread_attr_t tattr;
  pthread_attr_init(&tattr);
  pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);

  for (i=0; i<10000; i++) {
    pthread_create(&canceledThread, &tattr, canceledRoutine, (void *)i);
    pthread_create(&anotherThread, 0, anotherRoutine, (void *)i);

    pthread_join(anotherThread, 0);
  }

  sleep(5);
}

void cancelCleanup(void *arg)
{
  int i = (int)arg;

  fprintf(stderr, "%d -- Hey, I've been canceled!\n", i);
}


void *
canceledRoutine(void *arg)
{
  int i = (int)arg;

  pthread_cleanup_push(cancelCleanup, i);

  while(1) {
    // sleep() is defined to be a cancelation point
    sleep(1);
  }
  
  pthread_cleanup_pop(0);
  
  return 0;
}

void *
anotherRoutine(void *arg)
{
  int i = (int)arg;

  pthread_cancel(canceledThread);
  
  return 0;
}

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-14  8:27         ` Kevin D. Clark
@ 2000-01-14  8:30           ` Kevin D. Clark
  2000-01-14  8:36           ` Kevin D. Clark
  1 sibling, 0 replies; 10+ messages in thread
From: Kevin D. Clark @ 2000-01-14  8:30 UTC (permalink / raw)
  To: kclark; +Cc: Pthreads Developers List



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: C++ cleanup handler execution
  2000-01-14  8:27         ` Kevin D. Clark
  2000-01-14  8:30           ` Kevin D. Clark
@ 2000-01-14  8:36           ` Kevin D. Clark
  2000-02-02 10:08             ` pthread_cancel() problems Kevin D. Clark
  1 sibling, 1 reply; 10+ messages in thread
From: Kevin D. Clark @ 2000-01-14  8:36 UTC (permalink / raw)
  To: Pthreads Developers List

Kevin D. Clark writes:

> Sorry, in my previous email my test file got garbled.  
> My fault.

Sorry, now I've made *three* mistakes.  I've been up for too long...

*This* is the correct version of my test file.  The previous versions
that I sent were faulty.

Sorry.

--kevin (time to take a nap!)


// Compiling this file as a C++ program versus being a C program doesn't
// seem to affect the fact that the cleanup handler doesn't seem to be called.

#ifdef __unix
#include <unistd.h>
#endif
#include <pthread.h>
#include "stdio.h"

static void *canceledRoutine(void *), *anotherRoutine(void *);
static volatile int counter = 0;
static pthread_t canceledThread, anotherThread;

int
main(int argc, char *argv[])
{
  int i = 0;
  pthread_attr_t tattr;

  pthread_attr_init(&tattr);
  pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);

  for (i=0; i<1000; i++) {
    fprintf(stderr, "iteration %d\n", i);
    pthread_create(&canceledThread, &tattr, canceledRoutine, (void *)i);
    pthread_create(&anotherThread, 0, anotherRoutine, (void *)i);

    pthread_join(anotherThread, 0);
    fprintf(stderr, "counter is %d\n", counter);
  }

  // kludge
#ifdef __unix
  sleep(5);
#else
  Sleep(5000);
#endif

  return 0;
}

static void cancelCleanup(void *arg)
{
  int i = (int)arg;
  counter++;
  fprintf(stderr, "%d -- Hey, I've been canceled!\n", i);
}


static void *
canceledRoutine(void *arg)
{
  int i = (int)arg;

  pthread_cleanup_push(cancelCleanup, (void *)i);

  while(1) {
#ifdef __unix
    // sleep() is defined to be a cancelation point
    sleep(1);
#else
    // I'm not totally sure what is defined to be a cancelation point here.
    // This probably needs to be documented.
    Sleep(1000);
#endif
  }
  
  pthread_cleanup_pop(0);
  
  return 0;
}

static void *
anotherRoutine(void *arg)
{
  int i = (int)arg;

  pthread_cancel(canceledThread);
  
  return 0;
}


^ permalink raw reply	[flat|nested] 10+ messages in thread

* pthread_cancel() problems
  2000-01-14  8:36           ` Kevin D. Clark
@ 2000-02-02 10:08             ` Kevin D. Clark
  0 siblings, 0 replies; 10+ messages in thread
From: Kevin D. Clark @ 2000-02-02 10:08 UTC (permalink / raw)
  To: Pthreads Developers List

Hi,

Is anybody else successfully using pthread_cancel() with this library?

I can't seem to get it to work, and I haven't been able to track down
the cause of the problem yet.  I'm not using asynchronous cancelation
either.

At the end of this mail I will include another test program that
shows off this problem.  If the program ran correctly then you'd see a
stream of increasing numbers on your screen.  However, since the
cleanup routine (associated with pthread_cleanup_push()) is never
called, the counter remains at zero.

So I strongly suspect that there's a bug in the library here.  I just
wish I could find it.

--kevin

PS  The program works as expected on a Solaris 2.6 box.


/*  Compiling this program as a C or C++ program doesn't seem to have
 *  an effect on the fact that calling pthread_cancel() doesn't cause
 *  the canceledRoutine() to be invoked.
 *
 *  Environment:  VC++ 6.x, NT 4.x, service pack 5
 *                Pthreads-win32 snapshot 1999-11-02
 */

#include <stdio.h>
#include <errno.h>
#ifdef __unix
#include <unistd.h>
#endif

#include <pthread.h>

void *canceledRoutine(void *);
static volatile int counter = 0; /* volatile thrown in out of desperation */
pthread_t canceledThread;

pthread_mutex_t mu = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cv = PTHREAD_COND_INITIALIZER;
static int okToCancel = 0;

int
main(int argc, char *argv[])
{
  int i = 0;
  pthread_attr_t tattr;

  pthread_attr_init(&tattr);
  pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);

  for (i=0; i<100; i++) {
    /*    fprintf(stderr, "iteration %d\n", i); */
    pthread_create(&canceledThread, &tattr, canceledRoutine, (void *)i);

    pthread_mutex_lock(&mu);
    while (! okToCancel) {
      int result;
      result = pthread_cond_wait(&cv, &mu);
      if (result == EINTR) {
        fprintf(stderr, "%s:%d: interupted!\n", __FILE__, __LINE__);
      }
    }
    pthread_mutex_unlock(&mu);

    /* at this point we know that the other thread has pushed a cleanup
       handler onto its stack */
    pthread_cancel(canceledThread);

    okToCancel = 0;
    
    fprintf(stderr, "counter is %d\n", counter);
  }
  
  return 0;
}

void cancelCleanup(void *arg)
{
  int i = (int)arg;
  counter++;
  fprintf(stderr, "%d -- Hey, I've been canceled!\n", i);
}


void *
canceledRoutine(void *arg)
{
  int i = (int)arg;
  int ignored;
  
  /*
   *  My understanding is that the default is for deferred
   *  cancelation, but I'll do this anyways here just to be absolutely
   *  sure.
   */
  if (pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &ignored) != 0) {
    fprintf(stderr, "problem with pthread_setcanceltype()\n";
  }
  
  pthread_cleanup_push(cancelCleanup, (void *)i);
  pthread_mutex_lock(&mu);
  okToCancel = 1;
  pthread_mutex_unlock(&mu);
  pthread_cond_signal(&cv);
  
  while(1) {
#ifdef __unix
    /* sleep() is defined to be a cancelation point */
    sleep(1);
#else
    /*  I'm not totally sure what is defined to be a cancelation point.
     *  Perhaps this needs to be documented?
     */
    Sleep(1000);
#endif
  }
  
  pthread_cleanup_pop(0);
  
  return 0;
}


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Question about condition variable
  2000-01-14  8:19       ` Kevin D. Clark
  2000-01-14  8:27         ` Kevin D. Clark
@ 2000-06-14 18:06         ` Taci Ãœlker
       [not found]           ` <3949054F.3127@surfnshop.com>
  1 sibling, 1 reply; 10+ messages in thread
From: Taci Ülker @ 2000-06-14 18:06 UTC (permalink / raw)
  To: Pthreads Developers List

Hello all,

I am developing a software based on win32-pthreads (latest available).
My problem I encountered is:

I have an object for message queuing, wich is intended to let the
callers thread wait by getMessage(LPSSMSG lpMsg), until a new 
message is posted by any other thread. Now imagine, the thread
which is waiting for new messages is in status ACTIVE (sleeping or
not running) in operating system. The thread wich is posting a new 
message is in status RUNNING. This running thread pushes at first 
a new message into the queue and signals the waiting thread to be 
waked up and unlocks the mutex immediately, so that other threads 
can push further new messages. 

Now, the problem is when the signal is given to wake up the waiting
thread by the first message pushing thread then the OS dont switch 
automatically its thread execution. This means if the thread is not 
waked up, because it is not switched to stutus RUNNING and an other 
thread pushes further new message in to the queue and signals also 
the waiting thread then what is about the first and second signals?

I am actually switching thread execution with sleep(0) function,
after each message posting.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: Question about condition variable
       [not found]           ` <3949054F.3127@surfnshop.com>
@ 2000-06-16  7:33             ` Taci Ãœlker
  0 siblings, 0 replies; 10+ messages in thread
From: Taci Ülker @ 2000-06-16  7:33 UTC (permalink / raw)
  To: jean.andre; +Cc: Pthreads Developers List

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 9102 bytes --]

Hello jean,

first at all thank you for your help. Look at page 81 in the book
PTHREADS programming. There is a sample, how to deal with pthread
condition varaibles. The previosly described problem encounteres on 
a single processor system with WINNT 4.0 also in this example. Try 
this out fist without Sleep(0) line in inc_count function then 
uncomment Sleep(0) and try it again you will see what happens.
What you can also try is to create first the watch_count thread, to
let him enter in to the while, so that pthread_cond_wait function
unlocks the count_mutex while waiting. Then start inc_count with
and whithout Sleep(0).

#include <stdio.h>
#include "pthread.h"

#define TCOUNT 10
#define WATCH_COUNT 12

int count=0 ;

pthread_mutex_t count_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  count_treshold_cv = PTHREAD_COND_INITIALIZER;

int thread_ids[3] = {0,1,2};

void* watch_count(int *idp)
{
  pthread_mutex_lock(&count_mutex) ;
  while( count<=WATCH_COUNT){
    pthread_cond_wait(&count_treshold_cv, &count_mutex);
    printf( "watch_count(): Thread %d, count is %d\n", *idp, count);
  }
  pthread_mutex_unlock(&count_mutex) ;

  return NULL ;
}


void* inc_count(int *idp)
{
  int i;

  for(i=0;i<TCOUNT; i++){
    pthread_mutex_lock(&count_mutex) ;

    count++;
    printf( "inc_count(): Thread %d, old count %d,\
             new count %d\n", *idp, count-1, count );
    if(count==WATCH_COUNT)
      pthread_cond_signal(&count_treshold_cv);

    pthread_mutex_unlock(&count_mutex) ;
    // Sleep(0) ; //<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< uncomment
this line
  }
  return NULL ;
}


int main()
{
  int i ;
  pthread_t threads[3] ;

  pthread_create( &threads[0],NULL,inc_count, &thread_ids[0] );
  pthread_create( &threads[1],NULL,inc_count, &thread_ids[1] );
  pthread_create( &threads[2],NULL,watch_count, &thread_ids[2] );

  for(i=0; i<3; i++){
    pthread_join(&threads[i],NULL) ;
  }

  getchar() ;

  return 0;
}


What happens now? What is, if the signal from inc_count is not 
treated early enough, before the next thread holds the count_mutex.

** Output with Sleep(0):
inc_count(): Thread 0, old count 0,             new count 1
inc_count(): Thread 1, old count 1,             new count 2
inc_count(): Thread 0, old count 2,             new count 3
inc_count(): Thread 1, old count 3,             new count 4
inc_count(): Thread 0, old count 4,             new count 5
inc_count(): Thread 1, old count 5,             new count 6
inc_count(): Thread 0, old count 6,             new count 7
inc_count(): Thread 1, old count 7,             new count 8
inc_count(): Thread 0, old count 8,             new count 9
inc_count(): Thread 1, old count 9,             new count 10
inc_count(): Thread 0, old count 10,             new count 11
inc_count(): Thread 1, old count 11,             new count 12
watch_count(): Thread 2, count is 12
inc_count(): Thread 0, old count 12,             new count 13
inc_count(): Thread 1, old count 13,             new count 14
inc_count(): Thread 0, old count 14,             new count 15
inc_count(): Thread 1, old count 15,             new count 16
inc_count(): Thread 0, old count 16,             new count 17
inc_count(): Thread 1, old count 17,             new count 18
inc_count(): Thread 0, old count 18,             new count 19
inc_count(): Thread 1, old count 19,             new count 20

** Output without Sleep(0):
inc_count(): Thread 0, old count 0,             new count 1
inc_count(): Thread 0, old count 1,             new count 2
inc_count(): Thread 0, old count 2,             new count 3
inc_count(): Thread 0, old count 3,             new count 4
inc_count(): Thread 0, old count 4,             new count 5
inc_count(): Thread 0, old count 5,             new count 6
inc_count(): Thread 0, old count 6,             new count 7
inc_count(): Thread 0, old count 7,             new count 8
inc_count(): Thread 0, old count 8,             new count 9
inc_count(): Thread 0, old count 9,             new count 10
inc_count(): Thread 1, old count 10,             new count 11
inc_count(): Thread 1, old count 11,             new count 12
inc_count(): Thread 1, old count 12,             new count 13
inc_count(): Thread 1, old count 13,             new count 14
inc_count(): Thread 1, old count 14,             new count 15
inc_count(): Thread 1, old count 15,             new count 16
inc_count(): Thread 1, old count 16,             new count 17
inc_count(): Thread 1, old count 17,             new count 18
inc_count(): Thread 1, old count 18,             new count 19
inc_count(): Thread 1, old count 19,             new count 20

here the watch_count thread could not enter into the while,
because it had no chance to get the count_mutex


** Output with watch_count created first and without Sleep(0):
inc_count(): Thread 0, old count 0,             new count 1
inc_count(): Thread 0, old count 1,             new count 2
inc_count(): Thread 0, old count 2,             new count 3
inc_count(): Thread 0, old count 3,             new count 4
inc_count(): Thread 0, old count 4,             new count 5
inc_count(): Thread 0, old count 5,             new count 6
inc_count(): Thread 0, old count 6,             new count 7
inc_count(): Thread 0, old count 7,             new count 8
inc_count(): Thread 0, old count 8,             new count 9
inc_count(): Thread 0, old count 9,             new count 10
inc_count(): Thread 1, old count 10,             new count 11
inc_count(): Thread 1, old count 11,             new count 12
inc_count(): Thread 1, old count 12,             new count 13
inc_count(): Thread 1, old count 13,             new count 14
inc_count(): Thread 1, old count 14,             new count 15
inc_count(): Thread 1, old count 15,             new count 16
inc_count(): Thread 1, old count 16,             new count 17
inc_count(): Thread 1, old count 17,             new count 18
inc_count(): Thread 1, old count 18,             new count 19
inc_count(): Thread 1, old count 19,             new count 20
watch_count(): Thread 2, count is 20

here the watch_count is not waked up early enough. But the program
semantic requeires the watch_count should be waked up when the 
count variable reaches 12!


jean andre schrieb:
> 
> Hello,
> 
> Inside your thread, it sould waiting for a specfic signal and make
> broadcast the signal for every thread that running.
> 
> For ex: inside all thread except the nain thread:
> 
>         for ever {
> 
>                 wait until specific signal
>         }
> 
> in the main thread :
>         post a message in queue thread.
>         wake up thread by BROADCASITING message for all thread.
> 
> --------------------------------------------------------------------
> EX : C++ code.
> Si Main thread and all other thread sshould wait on the same condion
> variable and mutex.
> A good sample how to deal with queue and threads can be found in the
> book :
>         PTHREADS programming of O'Reilly, Nichols, Buttlar & Farell. ISBN-
> 1-56592-115-1
> Buy it, very good investisment !
> Hope, this help you.
> 
> Waiting thread:
> -------------
> macro : SNS_COND_WAIT = pthread_cond_wait
> macro : SNS_COND_BROADCAST = pthread_cond_broadcast
> 
> LONG BaseQueue::Q_WaitForEvent( VOID ) {
> 
>         while ( (m_lQueueSize == 0) && (!m_bQueueShutdown) ) {
> 
>                 if ( SNS_COND_WAIT(&m_condQueueNotEmpty, &m_mutexQueueLock ) != 0 )
> 
>                         return Q_LogError( m_szQName, SNSLOG_ERROR, SNS_E_SYS_COND_WAIT,
> "Q_WaitForEvent" );
>         }
> 
>  return NO_ERROR;
> }
> 
> Main thread:
> -----------
> 
> if ( SNS_COND_BROADCAST(&m_condQueueNotEmpty) != 0 )
>         Q_LogError( m_szQName, SNSLOG_ERROR, SNS_E_SYS_COND_BROADCAST,
> "Q_AddEvent" );
> 
> --
> Jean
> 
> Taci Ãœlker wrote:
> >
> > Hello all,
> >
> > I am developing a software based on win32-pthreads (latest available).
> > My problem I encountered is:
> >
> > I have an object for message queuing, wich is intended to let the
> > callers thread wait by getMessage(LPSSMSG lpMsg), until a new
> > message is posted by any other thread. Now imagine, the thread
> > which is waiting for new messages is in status ACTIVE (sleeping or
> > not running) in operating system. The thread wich is posting a new
> > message is in status RUNNING. This running thread pushes at first
> > a new message into the queue and signals the waiting thread to be
> > waked up and unlocks the mutex immediately, so that other threads
> > can push further new messages.
> >
> > Now, the problem is when the signal is given to wake up the waiting
> > thread by the first message pushing thread then the OS dont switch
> > automatically its thread execution. This means if the thread is not
> > waked up, because it is not switched to stutus RUNNING and an other
> > thread pushes further new message in to the queue and signals also
> > the waiting thread then what is about the first and second signals?
> >
> > I am actually switching thread execution with sleep(0) function,
> > after each message posting.
> 
> --
> Jean ANDRE
> Tel: (514) 398-9799 #24  Fax: (514) 398-9353

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2000-06-16  7:33 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <000601bf578e$3c89a750$208e08d0@fflaptop>
2000-01-05 17:35 ` C++ cleanup handler execution Ross Johnson
2000-01-06 14:11   ` Kevin D. Clark
2000-01-06 18:17     ` Ross Johnson
2000-01-14  8:19       ` Kevin D. Clark
2000-01-14  8:27         ` Kevin D. Clark
2000-01-14  8:30           ` Kevin D. Clark
2000-01-14  8:36           ` Kevin D. Clark
2000-02-02 10:08             ` pthread_cancel() problems Kevin D. Clark
2000-06-14 18:06         ` Question about condition variable Taci Ãœlker
     [not found]           ` <3949054F.3127@surfnshop.com>
2000-06-16  7:33             ` Taci Ãœlker

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).