diff --git a/src/apps/icon-o-matic/generic/support/RWLocker.h b/headers/private/shared/RWLocker.h similarity index 100% rename from src/apps/icon-o-matic/generic/support/RWLocker.h rename to headers/private/shared/RWLocker.h diff --git a/src/apps/icon-o-matic/Jamfile b/src/apps/icon-o-matic/Jamfile index f66c48b252c..9e91542793d 100644 --- a/src/apps/icon-o-matic/Jamfile +++ b/src/apps/icon-o-matic/Jamfile @@ -199,7 +199,6 @@ Application Icon-O-Matic : Selection.cpp # generic/support - RWLocker.cpp support.cpp support_ui.cpp support_settings.cpp @@ -309,9 +308,9 @@ Application Icon-O-Matic : Includes [ FGristFiles SVGParser.cpp ] : [ BuildFeatureAttribute expat : headers ] ; -DoCatalogs Icon-O-Matic : +DoCatalogs Icon-O-Matic : x-vnd.haiku-icon_o_matic - : + : MainWindow.cpp IconEditorApp.cpp SetPropertiesCommand.cpp diff --git a/src/apps/mediaplayer/Jamfile b/src/apps/mediaplayer/Jamfile index 50f2377f73b..68d4c329bab 100644 --- a/src/apps/mediaplayer/Jamfile +++ b/src/apps/mediaplayer/Jamfile @@ -101,7 +101,6 @@ Application MediaPlayer : ListenerAdapter.cpp MessageEvent.cpp Notifier.cpp - RWLocker.cpp SettingsMessage.cpp StackBlurFilter.cpp @@ -114,14 +113,14 @@ Application MediaPlayer : MainWin.cpp VideoView.cpp - : be game media tracker translation textencoding [ TargetLibstdc++ ] + : be game media tracker translation textencoding [ TargetLibstdc++ ] localestub libshared.a : MediaPlayer.rdef ; -DoCatalogs MediaPlayer : +DoCatalogs MediaPlayer : x-vnd.Haiku-MediaPlayer - : + : CopyPLItemsCommand.cpp ImportPLItemsCommand.cpp InfoWin.cpp diff --git a/src/apps/mediaplayer/support/RWLocker.cpp b/src/apps/mediaplayer/support/RWLocker.cpp deleted file mode 100644 index 6fb06d24b5d..00000000000 --- a/src/apps/mediaplayer/support/RWLocker.cpp +++ /dev/null @@ -1,471 +0,0 @@ -/* - * Copyright 2006, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * IngoWeinhold - */ - -#include "RWLocker.h" - -#include - -// info about a read lock owner -struct RWLocker::ReadLockInfo { - thread_id reader; - int32 count; -}; - - -// constructor -RWLocker::RWLocker() - : fLock(), - fMutex(), - fQueue(), - fReaderCount(0), - fWriterCount(0), - fReadLockInfos(8), - fWriter(B_ERROR), - fWriterWriterCount(0), - fWriterReaderCount(0) -{ - _Init(NULL); -} - -// constructor -RWLocker::RWLocker(const char* name) - : fLock(name), - fMutex(), - fQueue(), - fReaderCount(0), - fWriterCount(0), - fReadLockInfos(8), - fWriter(B_ERROR), - fWriterWriterCount(0), - fWriterReaderCount(0) -{ - _Init(name); -} - -// destructor -RWLocker::~RWLocker() -{ - fLock.Lock(); - delete_sem(fMutex.semaphore); - delete_sem(fQueue.semaphore); - for (int32 i = 0; ReadLockInfo* info = _ReadLockInfoAt(i); i++) - delete info; -} - -// ReadLock -bool -RWLocker::ReadLock() -{ - status_t error = _ReadLock(B_INFINITE_TIMEOUT); - return (error == B_OK); -} - -// ReadLockWithTimeout -status_t -RWLocker::ReadLockWithTimeout(bigtime_t timeout) -{ - bigtime_t absoluteTimeout = system_time() + timeout; - // take care of overflow - if (timeout > 0 && absoluteTimeout < 0) - absoluteTimeout = B_INFINITE_TIMEOUT; - return _ReadLock(absoluteTimeout); -} - -// ReadUnlock -void -RWLocker::ReadUnlock() -{ - if (fLock.Lock()) { - thread_id thread = find_thread(NULL); - if (thread == fWriter) { - // We (also) have a write lock. - if (fWriterReaderCount > 0) - fWriterReaderCount--; - // else: error: unmatched ReadUnlock() - } else { - int32 index = _IndexOf(thread); - if (ReadLockInfo* info = _ReadLockInfoAt(index)) { - fReaderCount--; - if (--info->count == 0) { - // The outer read lock bracket for the thread has been - // reached. Dispose the info. - _DeleteReadLockInfo(index); - } - if (fReaderCount == 0) { - // The last reader needs to unlock the mutex. - _ReleaseBenaphore(fMutex); - } - } // else: error: caller has no read lock - } - fLock.Unlock(); - } // else: we are probably going to be destroyed -} - -// IsReadLocked -// -// Returns whether or not the calling thread owns a read lock or even a -// write lock. -bool -RWLocker::IsReadLocked() const -{ - bool result = false; - if (fLock.Lock()) { - thread_id thread = find_thread(NULL); - result = (thread == fWriter || _IndexOf(thread) >= 0); - fLock.Unlock(); - } - return result; -} - -// WriteLock -bool -RWLocker::WriteLock() -{ - status_t error = _WriteLock(B_INFINITE_TIMEOUT); - return (error == B_OK); -} - -// WriteLockWithTimeout -status_t -RWLocker::WriteLockWithTimeout(bigtime_t timeout) -{ - bigtime_t absoluteTimeout = system_time() + timeout; - // take care of overflow - if (timeout > 0 && absoluteTimeout < 0) - absoluteTimeout = B_INFINITE_TIMEOUT; - return _WriteLock(absoluteTimeout); -} - -// WriteUnlock -void -RWLocker::WriteUnlock() -{ - if (fLock.Lock()) { - thread_id thread = find_thread(NULL); - if (thread == fWriter) { - fWriterCount--; - if (--fWriterWriterCount == 0) { - // The outer write lock bracket for the thread has been - // reached. - fWriter = B_ERROR; - if (fWriterReaderCount > 0) { - // We still own read locks. - _NewReadLockInfo(thread, fWriterReaderCount); - // A reader that expects to be the first reader may wait - // at the mutex semaphore. We need to wake it up. - if (fReaderCount > 0) - _ReleaseBenaphore(fMutex); - fReaderCount += fWriterReaderCount; - fWriterReaderCount = 0; - } else { - // We don't own any read locks. So we have to release the - // mutex benaphore. - _ReleaseBenaphore(fMutex); - } - } - } // else: error: unmatched WriteUnlock() - fLock.Unlock(); - } // else: We're probably going to die. -} - -// IsWriteLocked -// -// Returns whether or not the calling thread owns a write lock. -bool -RWLocker::IsWriteLocked() const -{ - return (fWriter == find_thread(NULL)); -} - -// _Init -void -RWLocker::_Init(const char* name) -{ - // init the mutex benaphore - BString mutexName(name); - mutexName += "_RWLocker_mutex"; - fMutex.semaphore = create_sem(0, mutexName.String()); - fMutex.counter = 0; - // init the queueing benaphore - BString queueName(name); - queueName += "_RWLocker_queue"; - fQueue.semaphore = create_sem(0, queueName.String()); - fQueue.counter = 0; -} - -// _ReadLock -// -// /timeout/ -- absolute timeout -status_t -RWLocker::_ReadLock(bigtime_t timeout) -{ - status_t error = B_OK; - thread_id thread = find_thread(NULL); - bool locked = false; - if (fLock.Lock()) { - // Check, if we already own a read (or write) lock. In this case we - // can skip the usual locking procedure. - if (thread == fWriter) { - // We already own a write lock. - fWriterReaderCount++; - locked = true; - } else if (ReadLockInfo* info = _ReadLockInfoAt(_IndexOf(thread))) { - // We already own a read lock. - info->count++; - fReaderCount++; - locked = true; - } - fLock.Unlock(); - } else // failed to lock the data - error = B_ERROR; - // Usual locking, i.e. we do not already own a read or write lock. - if (error == B_OK && !locked) { - error = _AcquireBenaphore(fQueue, timeout); - if (error == B_OK) { - if (fLock.Lock()) { - bool firstReader = false; - if (++fReaderCount == 1) { - // We are the first reader. - _NewReadLockInfo(thread); - firstReader = true; - } else - _NewReadLockInfo(thread); - fLock.Unlock(); - // The first reader needs to lock the mutex. - if (firstReader) { - error = _AcquireBenaphore(fMutex, timeout); - switch (error) { - case B_OK: - // fine - break; - case B_TIMED_OUT: { - // clean up - if (fLock.Lock()) { - _DeleteReadLockInfo(_IndexOf(thread)); - fReaderCount--; - fLock.Unlock(); - } - break; - } - default: - // Probably we are going to be destroyed. - break; - } - } - // Let the next candidate enter the game. - _ReleaseBenaphore(fQueue); - } else { - // We couldn't lock the data, which can only happen, if - // we're going to be destroyed. - error = B_ERROR; - } - } - } - return error; -} - -// _WriteLock -// -// /timeout/ -- absolute timeout -status_t -RWLocker::_WriteLock(bigtime_t timeout) -{ - status_t error = B_ERROR; - if (fLock.Lock()) { - bool infiniteTimeout = (timeout == B_INFINITE_TIMEOUT); - bool locked = false; - int32 readerCount = 0; - thread_id thread = find_thread(NULL); - int32 index = _IndexOf(thread); - if (ReadLockInfo* info = _ReadLockInfoAt(index)) { - // We already own a read lock. - if (fWriterCount > 0) { - // There are writers before us. - if (infiniteTimeout) { - // Timeout is infinite and there are writers before us. - // Unregister the read locks and lock as usual. - readerCount = info->count; - fWriterCount++; - fReaderCount -= readerCount; - _DeleteReadLockInfo(index); - error = B_OK; - } else { - // The timeout is finite and there are readers before us: - // let the write lock request fail. - error = B_WOULD_BLOCK; - } - } else if (info->count == fReaderCount) { - // No writers before us. - // We are the only read lock owners. Just move the read lock - // info data to the special writer fields and then we are done. - // Note: At this point we may overtake readers that already - // have acquired the queueing benaphore, but have not yet - // locked the data. But that doesn't harm. - fWriter = thread; - fWriterCount++; - fWriterWriterCount = 1; - fWriterReaderCount = info->count; - fReaderCount -= fWriterReaderCount; - _DeleteReadLockInfo(index); - locked = true; - error = B_OK; - } else { - // No writers before us, but other readers. - // Note, we're quite restrictive here. If there are only - // readers before us, we could reinstall our readers, if - // our request times out. Unfortunately it is not easy - // to ensure, that no writer overtakes us between unlocking - // the data and acquiring the queuing benaphore. - if (infiniteTimeout) { - // Unregister the readers and lock as usual. - readerCount = info->count; - fWriterCount++; - fReaderCount -= readerCount; - _DeleteReadLockInfo(index); - error = B_OK; - } else - error = B_WOULD_BLOCK; - } - } else { - // We don't own a read lock. - if (fWriter == thread) { - // ... but a write lock. - fWriterCount++; - fWriterWriterCount++; - locked = true; - error = B_OK; - } else { - // We own neither read nor write locks. - // Lock as usual. - fWriterCount++; - error = B_OK; - } - } - fLock.Unlock(); - // Usual locking... - // First step: acquire the queueing benaphore. - if (!locked && error == B_OK) { - error = _AcquireBenaphore(fQueue, timeout); - switch (error) { - case B_OK: - break; - case B_TIMED_OUT: { - // clean up - if (fLock.Lock()) { - fWriterCount--; - fLock.Unlock(); - } // else: failed to lock the data: we're probably going - // to die. - break; - } - default: - // Probably we're going to die. - break; - } - } - // Second step: acquire the mutex benaphore. - if (!locked && error == B_OK) { - error = _AcquireBenaphore(fMutex, timeout); - switch (error) { - case B_OK: { - // Yeah, we made it. Set the special writer fields. - fWriter = thread; - fWriterWriterCount = 1; - fWriterReaderCount = readerCount; - break; - } - case B_TIMED_OUT: { - // clean up - if (fLock.Lock()) { - fWriterCount--; - fLock.Unlock(); - } // else: failed to lock the data: we're probably going - // to die. - break; - } - default: - // Probably we're going to die. - break; - } - // Whatever happened, we have to release the queueing benaphore. - _ReleaseBenaphore(fQueue); - } - } else // failed to lock the data - error = B_ERROR; - return error; -} - -// _AddReadLockInfo -int32 -RWLocker::_AddReadLockInfo(ReadLockInfo* info) -{ - int32 index = fReadLockInfos.CountItems(); - fReadLockInfos.AddItem(info, index); - return index; -} - -// _NewReadLockInfo -// -// Create a new read lock info for the supplied thread and add it to the -// list. Returns the index of the info. -int32 -RWLocker::_NewReadLockInfo(thread_id thread, int32 count) -{ - ReadLockInfo* info = new ReadLockInfo; - info->reader = thread; - info->count = count; - return _AddReadLockInfo(info); -} - -// _DeleteReadLockInfo -void -RWLocker::_DeleteReadLockInfo(int32 index) -{ - if (ReadLockInfo* info = (ReadLockInfo*)fReadLockInfos.RemoveItem(index)) - delete info; -} - -// _ReadLockInfoAt -RWLocker::ReadLockInfo* -RWLocker::_ReadLockInfoAt(int32 index) const -{ - return (ReadLockInfo*)fReadLockInfos.ItemAt(index); -} - -// _IndexOf -int32 -RWLocker::_IndexOf(thread_id thread) const -{ - int32 count = fReadLockInfos.CountItems(); - for (int32 i = 0; i < count; i++) { - if (_ReadLockInfoAt(i)->reader == thread) - return i; - } - return -1; -} - -// _AcquireBenaphore -status_t -RWLocker::_AcquireBenaphore(Benaphore& benaphore, bigtime_t timeout) -{ - status_t error = B_OK; - if (atomic_add(&benaphore.counter, 1) > 0) { - error = acquire_sem_etc(benaphore.semaphore, 1, B_ABSOLUTE_TIMEOUT, - timeout); - } - return error; -} - -// _ReleaseBenaphore -void -RWLocker::_ReleaseBenaphore(Benaphore& benaphore) -{ - if (atomic_add(&benaphore.counter, -1) > 1) - release_sem(benaphore.semaphore); -} - diff --git a/src/apps/mediaplayer/support/RWLocker.h b/src/apps/mediaplayer/support/RWLocker.h deleted file mode 100644 index e94cff31473..00000000000 --- a/src/apps/mediaplayer/support/RWLocker.h +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright 2006, Haiku. - * Distributed under the terms of the MIT License. - * - * Authors: - * IngoWeinhold - */ - -// This class provides a reader/writer locking mechanism: -// * A writer needs an exclusive lock. -// * For a reader a non-exclusive lock to be shared with other readers is -// sufficient. -// * The ownership of a lock is bound to the thread that requested the lock; -// the same thread has to call Unlock() later. -// * Nested locking is supported: a number of XXXLock() calls needs to be -// bracketed by the same number of XXXUnlock() calls. -// * The lock acquiration strategy is fair: a lock applicant needs to wait -// only for those threads that already own a lock or requested one before -// the current thread. No one can overtake. E.g. if a thread owns a read -// lock, another one is waiting for a write lock, then a third one -// requesting a read lock has to wait until the write locker is done. -// This does not hold for threads that already own a lock (nested locking). -// A read lock owner is immediately granted another read lock and a write -// lock owner another write or a read lock. -// * A write lock owner is allowed to request a read lock and a read lock -// owner a write lock. While the first case is not problematic, the -// second one needs some further explanation: A read lock owner requesting -// a write lock temporarily looses its read lock(s) until the write lock -// is granted. Otherwise two read lock owning threads trying to get -// write locks at the same time would dead lock each other. The only -// problem with this solution is, that the write lock acquiration must -// not fail, because in that case the thread could not be given back -// its read lock(s), since another thread may have been given a write lock -// in the mean time. Fortunately locking can fail only either, if the -// locker has been deleted, or, if a timeout occured. Therefore -// WriteLockWithTimeout() immediatlely returns with a B_WOULD_BLOCK error -// code, if the caller already owns a read lock (but no write lock) and -// another thread already owns or has requested a read or write lock. -// * Calls to read and write locking methods may interleave arbitrarily, -// e.g.: ReadLock(); WriteLock(); ReadUnlock(); WriteUnlock(); -// -// Important note: Read/WriteLock() can fail only, if the locker has been -// deleted. However, it is NOT save to invoke any method on a deleted -// locker object. -// -// Implementation details: -// A locker needs three semaphores (a BLocker and two semaphores): one -// to protect the lockers data, one as a reader/writer mutex (to be -// acquired by each writer and the first reader) and one for queueing -// waiting readers and writers. The simplified locking/unlocking -// algorithm is the following: -// -// writer reader -// queue.acquire() queue.acquire() -// mutex.acquire() if (first reader) mutex.acquire() -// queue.release() queue.release() -// ... ... -// mutex.release() if (last reader) mutex.release() -// -// One thread at maximum waits at the mutex, the others at the queueing -// semaphore. Unfortunately features as nested locking and timeouts make -// things more difficult. Therefore readers as well as writers need to check -// whether they already own a lock before acquiring the queueing semaphore. -// The data for the readers are stored in a list of ReadLockInfo structures; -// the writer data are stored in some special fields. /fReaderCount/ and -// /fWriterCount/ contain the total count of unbalanced Read/WriteLock() -// calls, /fWriterReaderCount/ and /fWriterWriterCount/ only from those of -// the current write lock owner (/fWriter/). To be a bit more precise: -// /fWriterReaderCount/ is not contained in /fReaderCount/, but -// /fWriterWriterCount/ is contained in /fWriterCount/. Therefore -// /fReaderCount/ can be considered to be the count of true reader's read -// locks. - -#ifndef RW_LOCKER_H -#define RW_LOCKER_H - -#include -#include - -#include "AutoLocker.h" - -class RWLocker { - public: - RWLocker(); - RWLocker(const char* name); - virtual ~RWLocker(); - - bool ReadLock(); - status_t ReadLockWithTimeout(bigtime_t timeout); - void ReadUnlock(); - bool IsReadLocked() const; - - bool WriteLock(); - status_t WriteLockWithTimeout(bigtime_t timeout); - void WriteUnlock(); - bool IsWriteLocked() const; - - private: - struct ReadLockInfo; - struct Benaphore { - sem_id semaphore; - int32 counter; - }; - - private: - void _Init(const char* name); - status_t _ReadLock(bigtime_t timeout); - status_t _WriteLock(bigtime_t timeout); - - int32 _AddReadLockInfo(ReadLockInfo* info); - int32 _NewReadLockInfo(thread_id thread, - int32 count = 1); - void _DeleteReadLockInfo(int32 index); - ReadLockInfo* _ReadLockInfoAt(int32 index) const; - int32 _IndexOf(thread_id thread) const; - - static status_t _AcquireBenaphore(Benaphore& benaphore, - bigtime_t timeout); - static void _ReleaseBenaphore(Benaphore& benaphore); - - private: - mutable BLocker fLock; // data lock - Benaphore fMutex; // critical code mutex - Benaphore fQueue; // queueing semaphore - int32 fReaderCount; // total count... - int32 fWriterCount; // total count... - BList fReadLockInfos; - thread_id fWriter; // current write lock owner - int32 fWriterWriterCount; // write lock owner count - int32 fWriterReaderCount; // writer read lock owner - // count -}; - -typedef AutoLocker > AutoReadLocker; -typedef AutoLocker > AutoWriteLocker; - -#endif // RW_LOCKER_H diff --git a/src/kits/shared/Jamfile b/src/kits/shared/Jamfile index 69eb9015a53..fed99a5342a 100644 --- a/src/kits/shared/Jamfile +++ b/src/kits/shared/Jamfile @@ -46,6 +46,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { PromptWindow.cpp QueryFile.cpp RegExp.cpp + RWLocker.cpp RWLockManager.cpp SHA256.cpp ShakeTrackingFilter.cpp diff --git a/src/apps/icon-o-matic/generic/support/RWLocker.cpp b/src/kits/shared/RWLocker.cpp similarity index 100% rename from src/apps/icon-o-matic/generic/support/RWLocker.cpp rename to src/kits/shared/RWLocker.cpp