home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / nsprpub / pr / src / threads / prsem.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  4.1 KB  |  156 lines

  1. /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /*
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  * 
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  * 
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "primpl.h"
  20. #if defined(XP_MAC)
  21. #include "prsem.h"
  22. #else
  23. #include "obsolete/prsem.h"
  24. #endif
  25.  
  26. /************************************************************************/
  27.  
  28. /*
  29. ** Create a new semaphore.
  30. */
  31. PR_IMPLEMENT(PRSemaphore*) PR_NewSem(PRUintn value)
  32. {
  33.     PRSemaphore *sem;
  34.     PRCondVar *cvar;
  35.     PRLock *lock;
  36.  
  37.     sem = PR_NEWZAP(PRSemaphore);
  38.     if (sem) {
  39. #ifdef HAVE_CVAR_BUILT_ON_SEM
  40.         _PR_MD_NEW_SEM(&sem->md, value);
  41. #else
  42.         lock = PR_NewLock();
  43.         if (!lock) {
  44.             PR_DELETE(sem);
  45.             return NULL;
  46.         }
  47.  
  48.         cvar = PR_NewCondVar(lock);
  49.         if (!cvar) {
  50.             PR_DestroyLock(lock);
  51.             PR_DELETE(sem);
  52.             return NULL;
  53.         }
  54.         sem->cvar = cvar;
  55.         sem->count = value;
  56. #endif
  57.     }
  58.     return sem;
  59. }
  60.  
  61. /*
  62. ** Destroy a semaphore. There must be no thread waiting on the semaphore.
  63. ** The caller is responsible for guaranteeing that the semaphore is
  64. ** no longer in use.
  65. */
  66. PR_IMPLEMENT(void) PR_DestroySem(PRSemaphore *sem)
  67. {
  68. #ifdef HAVE_CVAR_BUILT_ON_SEM
  69.     _PR_MD_DESTROY_SEM(&sem->md);
  70. #else
  71.     PR_ASSERT(sem->waiters == 0);
  72.  
  73.     PR_DestroyLock(sem->cvar->lock);
  74.     PR_DestroyCondVar(sem->cvar);
  75. #endif
  76.     PR_DELETE(sem);
  77. }
  78.  
  79. /*
  80. ** Wait on a Semaphore.
  81. ** 
  82. ** This routine allows a calling thread to wait or proceed depending upon the 
  83. ** state of the semahore sem. The thread can proceed only if the counter value 
  84. ** of the semaphore sem is currently greater than 0. If the value of semaphore 
  85. ** sem is positive, it is decremented by one and the routine returns immediately 
  86. ** allowing the calling thread to continue. If the value of semaphore sem is 0, 
  87. ** the calling thread blocks awaiting the semaphore to be released by another 
  88. ** thread.
  89. ** 
  90. ** This routine can return PR_PENDING_INTERRUPT if the waiting thread 
  91. ** has been interrupted.
  92. */
  93. PR_IMPLEMENT(PRStatus) PR_WaitSem(PRSemaphore *sem)
  94. {
  95.     PRStatus status = PR_SUCCESS;
  96.  
  97. #ifdef HAVE_CVAR_BUILT_ON_SEM
  98.     return _PR_MD_WAIT_SEM(&sem->md);
  99. #else
  100.     PR_Lock(sem->cvar->lock);
  101.     while (sem->count == 0) {
  102.         sem->waiters++;
  103.         status = PR_WaitCondVar(sem->cvar, PR_INTERVAL_NO_TIMEOUT);
  104.         sem->waiters--;
  105.         if (status != PR_SUCCESS)
  106.             break;
  107.     }
  108.     if (status == PR_SUCCESS)
  109.         sem->count--;
  110.     PR_Unlock(sem->cvar->lock);
  111. #endif
  112.     
  113.     return (status);
  114. }
  115.  
  116. /*
  117. ** This routine increments the counter value of the semaphore. If other threads 
  118. ** are blocked for the semaphore, then the scheduler will determine which ONE 
  119. ** thread will be unblocked.
  120. */
  121. PR_IMPLEMENT(void) PR_PostSem(PRSemaphore *sem)
  122. {
  123. #ifdef HAVE_CVAR_BUILT_ON_SEM
  124.     _PR_MD_POST_SEM(&sem->md);
  125. #else
  126.     PR_Lock(sem->cvar->lock);
  127.     if (sem->waiters)
  128.         PR_NotifyCondVar(sem->cvar);
  129.     sem->count++;
  130.     PR_Unlock(sem->cvar->lock);
  131. #endif
  132. }
  133.  
  134. #if DEBUG
  135. /*
  136. ** Returns the value of the semaphore referenced by sem without affecting
  137. ** the state of the semaphore.  The value represents the semaphore vaule
  138. ** at the time of the call, but may not be the actual value when the
  139. ** caller inspects it. (FOR DEBUGGING ONLY)
  140. */
  141. PR_IMPLEMENT(PRUintn) PR_GetValueSem(PRSemaphore *sem)
  142. {
  143.     PRUintn rv;
  144.  
  145. #ifdef HAVE_CVAR_BUILT_ON_SEM
  146.     rv = _PR_MD_GET_VALUE_SEM(&sem->md);
  147. #else
  148.     PR_Lock(sem->cvar->lock);
  149.     rv = sem->count;
  150.     PR_Unlock(sem->cvar->lock);
  151. #endif
  152.     
  153.     return rv;
  154. }
  155. #endif
  156.