bool MultiLocker::ReadUnlock() { #if TIMING bigtime_t start = system_time(); #endif bool unlocked = false; if (IsWriteLocked()) { //writers simply decrement the nesting count fWriterNest--; unlocked = true; } else { //decrement and retrieve the read counter int32 current_count = atomic_add(&fReadCount, -1); if (current_count < 0) { //a writer is waiting for the lock so release fWriteSem unlocked = (release_sem_etc(fWriteSem, 1, B_DO_NOT_RESCHEDULE) == B_OK); } else unlocked = true; //unregister if we released the lock and are debugging if (fDebugArray && unlocked) unregister_thread(); } #if TIMING bigtime_t end = system_time(); ru_time += (end - start); ru_count++; #endif return unlocked; }
void CDestination::ReadChunk( CIFFReader &reader) { ASSERT(IsWriteLocked()); switch (reader.ChunkID()) { case DESTINATION_HEADER_CHUNK: { reader >> m_id; reader >> m_latency; reader >> m_flags; reader >> m_color; ColorChanged(m_color); break; } case DESTINATION_NAME_CHUNK: { reader.MustRead(m_name, MIN((size_t)reader.ChunkLength(), DESTINATION_NAME_LENGTH)); NameChanged(m_name); break; } default: { CSerializable::ReadChunk(reader); } } }
bool MultiLocker::WriteLock() { #if TIMING bigtime_t start = system_time(); #endif bool locked = false; if (fInit == B_OK) { uint32 stack_base = 0; thread_id thread = -1; if (IsWriteLocked(&stack_base, &thread)) { //already the writer - increment the nesting count fWriterNest++; locked = true; } else { //new writer acquiring the lock if (atomic_add(&fLockCount, 1) >= 1) { //another writer in the lock - acquire the semaphore locked = (acquire_sem_etc(fWriterLock, 1, B_DO_NOT_RESCHEDULE, B_INFINITE_TIMEOUT) == B_OK); } else locked = true; if (locked) { //new holder of the lock //decrement fReadCount by a very large number //this will cause new readers to block on fReadSem int32 readers = atomic_add(&fReadCount, -MAX_READERS); if (readers > 0) { //readers hold the lock - acquire fWriteSem locked = (acquire_sem_etc(fWriteSem, readers, B_DO_NOT_RESCHEDULE, B_INFINITE_TIMEOUT) == B_OK); } if (locked) { ASSERT(fWriterThread == -1); //record thread information fWriterThread = thread; fWriterStackBase = stack_base; } } } } #if TIMING bigtime_t end = system_time(); wl_time += (end - start); wl_count++; #endif return locked; }
bool MultiLocker::WriteUnlock() { #if TIMING bigtime_t start = system_time(); #endif bool unlocked = false; if (IsWriteLocked()) { //if this is a nested lock simply decrement the nest count if (fWriterNest > 0) { fWriterNest--; unlocked = true; } else { //writer finally unlocking //increment fReadCount by a large number //this will let new readers acquire the read lock //retrieve the number of current waiters int32 readersWaiting = atomic_add(&fReadCount, MAX_READERS) + MAX_READERS; if (readersWaiting > 0) { //readers are waiting to acquire the lock unlocked = (release_sem_etc(fReadSem, readersWaiting, B_DO_NOT_RESCHEDULE) == B_OK); } else unlocked = true; if (unlocked) { //clear the information fWriterThread = -1; fWriterStackBase = 0; //decrement and retrieve the lock count if (atomic_add(&fLockCount, -1) > 1) { //other writers are waiting so release fWriterLock unlocked = (release_sem_etc(fWriterLock, 1, B_DO_NOT_RESCHEDULE) == B_OK); } } } } else debugger("Non-writer attempting to WriteUnlock()\n"); #if TIMING bigtime_t end = system_time(); wu_time += (end - start); wu_count++; #endif return unlocked; }
void CDestination::SetLatency( bigtime_t latency) { D_ACCESS(("CDestination::SetLatency(%Ld)\n", latency)); ASSERT(IsWriteLocked()); if (latency != m_latency) { m_latency = latency; Document()->SetModified(); CUpdateHint hint; hint.AddInt32("DestID", m_id); hint.AddInt32("DestAttrs", Update_Latency); PostUpdate(&hint); } }
void CDestination::SetName( const char *name) { D_ACCESS(("CDestination::SetName(%s)\n", name)); ASSERT(IsWriteLocked()); if (strcmp(m_name, name) != 0) { strncpy(m_name, name, DESTINATION_NAME_LENGTH); NameChanged(name); Document()->SetModified(); CUpdateHint hint; hint.AddInt32("DestID", m_id); hint.AddInt32("DestAttrs", Update_Name); PostUpdate(&hint); } }
MultiLocker::~MultiLocker() { //become the writer if (!IsWriteLocked()) WriteLock(); //set locker to be uninitialized fInit = B_NO_INIT; //delete the semaphores delete_sem(fReadSem); delete_sem(fWriteSem); delete_sem(fWriterLock); #if DEBUG //we are in debug mode! //clear and delete the reader tracking list free(fDebugArray); #endif #if TIMING //let's produce some performance numbers printf("MultiLocker Statistics:\n" "Avg ReadLock: %lld\n" "Avg ReadUnlock: %lld\n" "Avg WriteLock: %lld\n" "Avg WriteUnlock: %lld\n" "Avg IsWriteLocked: %lld\n", rl_count > 0 ? rl_time / rl_count : 0, ru_count > 0 ? ru_time / ru_count : 0, wl_count > 0 ? wl_time / wl_count : 0, wu_count > 0 ? wu_time / wu_count : 0, islock_count > 0 ? islock_time / islock_count : 0 ); #if DEBUG printf( "Avg register_thread: %lld\n" "Avg unregister_thread: %lld\n", reg_count > 0 ? reg_time / reg_count : 0, unreg_count > 0 ? unreg_time / unreg_count : 0 ); #endif #endif }
bool MultiLocker::ReadLock() { #if TIMING bigtime_t start = system_time(); #endif bool locked = false; //the lock must be initialized if (fInit == B_OK) { if (IsWriteLocked()) { //the writer simply increments the nesting fWriterNest++; locked = true; } else { //increment and retrieve the current count of readers int32 current_count = atomic_add(&fReadCount, 1); if (current_count < 0) { //a writer holds the lock so wait for fReadSem to be released locked = (acquire_sem_etc(fReadSem, 1, B_DO_NOT_RESCHEDULE, B_INFINITE_TIMEOUT) == B_OK); } else locked = true; #if DEBUG //register if we acquired the lock if (locked) register_thread(); #endif } } #if TIMING bigtime_t end = system_time(); rl_time += (end - start); rl_count++; #endif return locked; }
void CDestination::SetColor( rgb_color color) { D_ACCESS(("CDestination::SetColor(%d, %d, %d, %d)\n", color.red, color.green, color.blue, color.alpha)); ASSERT(IsWriteLocked()); if ((color.red != m_color.red) || (color.green != m_color.green) || (color.blue != m_color.blue)) { m_color = color; ColorChanged(color); Document()->SetModified(); CUpdateHint hint; hint.AddInt32("DestID", m_id); hint.AddInt32("DestAttrs", Update_Color); PostUpdate(&hint); } }
void CDestination::SetSolo( bool solo) { D_ACCESS(("CDestination::SetSolo(%s)\n", solo ? "true" : "false")); ASSERT(IsWriteLocked()); bool changed = false; if (solo) changed = _addFlag(SOLO); else changed = _removeFlag(SOLO); if (changed) { Soloed(solo); Document()->SetModified(); CUpdateHint hint; hint.AddInt32("DestID", m_id); hint.AddInt32("DestAttrs", Update_Flags); PostUpdate(&hint); } }
void CDestination::SetMuted( bool muted) { D_ACCESS(("CDestination::SetMuted(%s)\n", muted ? "true" : "false")); ASSERT(IsWriteLocked()); bool changed = false; if (muted) changed = _addFlag(MUTED); else changed = _removeFlag(MUTED); if (changed) { Muted(muted); Document()->SetModified(); CUpdateHint hint; hint.AddInt32("DestID", m_id); hint.AddInt32("DestAttrs", Update_Flags); PostUpdate(&hint); } }