title: dispatch_semaphore_t reuse - What am I missing here?
body: <p>I have some code where I am using dispatch_semaphore_t to signal operation completion. When the semaphore is a member variable, it does not seem to behave correctly. I will show example code that works and an example that does not seem to work:</p>
  
  <pre><code>@implementation someClass  
  {  
    dispatch_semaphore_t memberSem;  
    dispatch_semaphore_t* semPtr;  
    NSThread* worker;
    BOOL taskDone;  
  }  
  
  - (id)init  
  {  
    // Set up the worker thread and launch it - not shown here.  
    memberSem= dispatch_semaphore_create(0); 
    semPtr= NULL;  
    taskDone= FALSE;  
  }  
  
  - (void)dealloc  
  {  
    // Clean up the worker thread as needed - not shown here.  
    if((NULL != semPtr) &amp;&amp; (NULL != *semPtr))  
      disptatch_release(*semPtr);  
  
    dispatch_release(memberSem);  
  }  
  
  - (void)doSomethingArduous  
  {  
    while([self notDone])  // Does something like check a limit.  
      [self doIt];  // Does something like process data and increment a counter.  
  
    taskDone= TRUE;  // I know this should be protected, but keeping the example simple for now.  
  
    if((NULL != semPtr) &amp;&amp; (NULL != *semPtr))  
      dispatch_semaphore_signal(*semPtr);  // I will put a breakpoint here, call it  "SIGNAL"  
  }  
  
  - (BOOL)getSomethingDoneUseLocalSemaphore  
  {  
    taskDone= FALSE;  // I know this should be protected, but keeping the example simple for now.  
    dispatch_semaphore_t localSem= dispatch_semaphore_create(0);  
    semPtr= &amp;localSem;  
    [self performSelector:doSomethingArduous onThread:worker withObject:nil waitUntilDone:NO];  
  
    dispatch_time_t timeUp= dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(2.5 * NSEC_PER_SEC));  
    dispatch_semaphore_wait(localSem, timeUp);  
  
    semPtr= NULL;  
    dispatch_release(localSem);  
  
    // I know I could just return taskDone. The example is this way to show what the problem is.  
    if(taskDone)  // Again with thread safety.  
      return TRUE;    
  
    return FALSE;  
  }  
  
  - (BOOL)getSomethingDoneUseMemberSemaphore  
  {  
    taskDone= FALSE;  // I know this should be protected, but keeping the example simple for now.  
  
    semPtr= &amp;memberSem;  // I will put a breakpoint here, call it "START"  
    [self performSelector:doSomethingArduous onThread:worker withObject:nil waitUntilDone:NO];  
  
    dispatch_time_t timeUp= dispatch_time(DISPATCH_TIME_NOW, (uint64_t)(2.5 * NSEC_PER_SEC));  
    dispatch_semaphore_wait(memberSem, timeUp);  
  
    semPtr= NULL;  
  
    // I know I could just return taskDone. The example is this way to show what the problem is.  
    if(taskDone)  // Again with thread safety.  
      return TRUE;  // I will put a breakpoint here, call it "TASK_DONE"   
  
    return FALSE;  // I will put a breakpoint here, call it "TASK_NOT_DONE"  
  }  
  
  - (void)hereIsWhereWeBringItTogether  
  {  
    BOOL gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore];  // Will return TRUE.  
    gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore];  // Will return TRUE.  
    gotItDoneLocal= [self getSomethingDoneUseLocalSemaphore];  // Will return TRUE.  
  
    BOOL gotItDoneMember= [self getSomethingDoneUseMemberSemaphore];  // Will return TRUE. I will put a breakpoint here, call it "RUN_TEST"  
    gotItDoneMember= [self getSomethingDoneUseMemberSemaphore];  // Will return FALSE.  
  }  
  </code></pre>
  
  <p>So, given that code and the results I get/got, I put the breakpoints as described in my real code: One in the main function, one to start in the work function, one where the member semaphore is signaled, and two after the wait.</p>
  
  <p>What I found was in the case where I use the member semaphore, in the first round I stop at breakpoint "RUN_TEST", run and hit breakpoint "START", run then hit breakpoint "SIGNAL", run then hit breakpoint "TASK_DONE" - all as expected.</p>
  
  <p>When I continue to run, I hit breakpoint "START", run then hit breakpoint "TASK_NOT_DONE", run then hit breakpoint "SIGNAL"</p>
  
  <p>That is, when I run the sequence using a semaphore that is a member, and do what looks like proper signal/wait, the second time I try to wait on that semaphore I seem to blow by and it gets signaled after I have exited the wait.</p>
  
  <p>I seem to either be not managing the counting right (signal/wait pairings) or that member semaphore will not go back to an un-signaled state.</p>
  
  <p>My feeling is there is something fundamental I am missing here. Any input would be appreciated.</p>
  
  <p>EDIT: Ultimately what I seemed to be missing was due to my actual code being a bit more complicated. Instead of a clean return from the arduous task, there are multiple threads involved and a postNotification. I replaced the postNotification with the code in the notification handler - it sets a flag and signals the semaphore. That way any delay that might have been introduced by the notification handler is eliminated.</p>