/* ** Create a new condition variable. ** "lock" is the lock to use with the condition variable. ** ** Condition variables are synchronization objects that threads can use ** to wait for some condition to occur. ** ** This may fail if memory is tight or if some operating system resource ** is low. */ PR_IMPLEMENT(PRCondVar*) PR_NewCondVar(PRLock *lock) { PRCondVar *cvar; PR_ASSERT(lock != NULL); cvar = PR_NEWZAP(PRCondVar); if (cvar) { #ifdef _PR_GLOBAL_THREADS_ONLY if(_PR_MD_NEW_CV(&cvar->md)) { PR_DELETE(cvar); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; } #endif if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) { PR_DELETE(cvar); PR_SetError(PR_INSUFFICIENT_RESOURCES_ERROR, 0); return NULL; } cvar->lock = lock; PR_INIT_CLIST(&cvar->condQ); } else { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); } return cvar; }
PRStatus _PR_InitLock(PRLock *lock) { if (_PR_MD_NEW_LOCK(&lock->ilock) != PR_SUCCESS) { return PR_FAILURE; } PR_INIT_CLIST(&lock->links); PR_INIT_CLIST(&lock->waitQ); return PR_SUCCESS; }
PR_IMPLEMENT(PRLock*) PR_NewLock(void) { PRLock *lock; if (!_pr_initialized) _PR_ImplicitInitialization(); lock = PR_NEWZAP(PRLock); if (lock) { if (_PR_MD_NEW_LOCK(&lock->ilock) == PR_FAILURE) { PR_DELETE(lock); return(NULL); } PR_INIT_CLIST(&lock->links); PR_INIT_CLIST(&lock->waitQ); } return lock; }
PR_IMPLEMENT(PRCondVar*) PRP_NewNakedCondVar(void) { PRCondVar *cvar = PR_NEWZAP(PRCondVar); if (NULL != cvar) { if (_PR_MD_NEW_LOCK(&(cvar->ilock)) == PR_FAILURE) { PR_DELETE(cvar); cvar = NULL; } else { PR_INIT_CLIST(&cvar->condQ); cvar->lock = _PR_NAKED_CV_LOCK; } } return cvar; }
PR_IMPLEMENT(PRWaitGroup*) PR_CreateWaitGroup(PRInt32 size /* ignored */) { PRWaitGroup *wg; if (NULL == (wg = PR_NEWZAP(PRWaitGroup))) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto failed; } /* the wait group itself */ wg->ml = PR_NewLock(); if (NULL == wg->ml) goto failed_lock; wg->io_taken = PR_NewCondVar(wg->ml); if (NULL == wg->io_taken) goto failed_cvar0; wg->io_complete = PR_NewCondVar(wg->ml); if (NULL == wg->io_complete) goto failed_cvar1; wg->new_business = PR_NewCondVar(wg->ml); if (NULL == wg->new_business) goto failed_cvar2; wg->mw_manage = PR_NewCondVar(wg->ml); if (NULL == wg->mw_manage) goto failed_cvar3; PR_INIT_CLIST(&wg->group_link); PR_INIT_CLIST(&wg->io_ready); /* the waiters sequence */ wg->waiter = (_PRWaiterHash*)PR_CALLOC( sizeof(_PRWaiterHash) + (_PR_DEFAULT_HASH_LENGTH * sizeof(PRRecvWait*))); if (NULL == wg->waiter) { PR_SetError(PR_OUT_OF_MEMORY_ERROR, 0); goto failed_waiter; } wg->waiter->count = 0; wg->waiter->length = _PR_DEFAULT_HASH_LENGTH; #ifdef WINNT _PR_MD_NEW_LOCK(&wg->mdlock); PR_INIT_CLIST(&wg->wait_list); #endif /* WINNT */ PR_Lock(mw_lock); PR_APPEND_LINK(&wg->group_link, &mw_state->group_list); PR_Unlock(mw_lock); return wg; failed_waiter: PR_DestroyCondVar(wg->mw_manage); failed_cvar3: PR_DestroyCondVar(wg->new_business); failed_cvar2: PR_DestroyCondVar(wg->io_complete); failed_cvar1: PR_DestroyCondVar(wg->io_taken); failed_cvar0: PR_DestroyLock(wg->ml); failed_lock: PR_DELETE(wg); wg = NULL; failed: return wg; } /* MW_CreateWaitGroup */