with the new design, there is always only one redraw message in the WindowLayers message queue, therefor, ReadLockWithTimeout() is no longer needed, removed RWLocker again as MultiLocker suits our needs.
git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15232 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
c63a78aafa
commit
312345bcb1
@ -491,18 +491,21 @@ Desktop::SendToBack(WindowLayer* window)
|
||||
void
|
||||
Desktop::SetFocusWindow(WindowLayer* window)
|
||||
{
|
||||
// TODO: find bug, this invalidates too many regions
|
||||
|
||||
if (fFocusWindow == window)
|
||||
return;
|
||||
|
||||
if (fFocusWindow)
|
||||
fFocusWindow->SetFocus(false);
|
||||
if (LockClipping()) {
|
||||
|
||||
fFocusWindow = window;
|
||||
if (fFocusWindow)
|
||||
fFocusWindow->SetFocus(false);
|
||||
|
||||
fFocusWindow = window;
|
||||
|
||||
if (fFocusWindow)
|
||||
fFocusWindow->SetFocus(true);
|
||||
|
||||
if (fFocusWindow)
|
||||
fFocusWindow->SetFocus(true);
|
||||
UnlockClipping();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -12,13 +12,10 @@
|
||||
#define SHOW_GLOBAL_DIRTY_REGION 0
|
||||
#define SHOW_WINDOW_CONTENT_DIRTY_REGION 0
|
||||
|
||||
#define MULTI_LOCKER 0
|
||||
#define RW_LOCKER 0
|
||||
#define MULTI_LOCKER 1
|
||||
|
||||
#if MULTI_LOCKER
|
||||
# include "MultiLocker.h"
|
||||
#elif RW_LOCKER
|
||||
# include "RWLocker.h"
|
||||
#else
|
||||
# include <Locker.h>
|
||||
#endif
|
||||
@ -68,23 +65,14 @@ class Desktop : public BLooper {
|
||||
|
||||
void SetFocusWindow(WindowLayer* window);
|
||||
|
||||
#if RW_LOCKER
|
||||
#if MULTI_LOCKER
|
||||
bool ReadLockClipping() { return fClippingLock.ReadLock(); }
|
||||
bool ReadLockClippingWithTimeout() { return fClippingLock.ReadLockWithTimeout(10000) >= B_OK; }
|
||||
void ReadUnlockClipping() { fClippingLock.ReadUnlock(); }
|
||||
|
||||
bool LockClipping() { return fClippingLock.WriteLock(); }
|
||||
void UnlockClipping() { fClippingLock.WriteUnlock(); }
|
||||
#elif MULTI_LOCKER
|
||||
bool ReadLockClipping() { return fClippingLock.ReadLock(); }
|
||||
bool ReadLockClippingWithTimeout() { return fClippingLock.ReadLock(); }
|
||||
void ReadUnlockClipping() { fClippingLock.ReadUnlock(); }
|
||||
|
||||
bool LockClipping() { return fClippingLock.WriteLock(); }
|
||||
void UnlockClipping() { fClippingLock.WriteUnlock(); }
|
||||
#else // BLocker
|
||||
bool ReadLockClipping() { return fClippingLock.Lock(); }
|
||||
bool ReadLockClippingWithTimeout() { return fClippingLock.LockWithTimeout(10000) >= B_OK; }
|
||||
void ReadUnlockClipping() { fClippingLock.Unlock(); }
|
||||
|
||||
bool LockClipping() { return fClippingLock.Lock(); }
|
||||
|
@ -1,465 +0,0 @@
|
||||
// RWLocker.cpp
|
||||
|
||||
#include <String.h>
|
||||
|
||||
#include "RWLocker.h"
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
@ -1,126 +0,0 @@
|
||||
// RWLocker.h
|
||||
//
|
||||
// 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 <List.h>
|
||||
#include <Locker.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
|
||||
};
|
||||
|
||||
#endif // RW_LOCKER_H
|
@ -83,14 +83,9 @@ WindowLayer::MessageReceived(BMessage* message)
|
||||
{
|
||||
switch (message->what) {
|
||||
case MSG_REDRAW: {
|
||||
if (!MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
||||
while (!fDesktop->ReadLockClippingWithTimeout()) {
|
||||
//printf("%s MSG_REDRAW -> timeout\n", Name());
|
||||
if (MessageQueue()->FindMessage(MSG_REDRAW, 0)) {
|
||||
//printf("%s MSG_REDRAW -> timeout - leaving because there are pending redraws\n", Name());
|
||||
return;
|
||||
}
|
||||
}
|
||||
// there is only one MSG_REDRAW in the queue at anytime
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
|
||||
_DrawBorder();
|
||||
_TriggerContentRedraw();
|
||||
|
||||
@ -208,19 +203,15 @@ void
|
||||
WindowLayer::SetFocus(bool focus)
|
||||
{
|
||||
// executed from Desktop thread
|
||||
// it holds the clipping write lock,
|
||||
// so the window thread cannot be
|
||||
// accessing fFocus
|
||||
|
||||
// since we don't mark parts dirty that
|
||||
// don't intersect with our own visible
|
||||
// region, readlocking is fine
|
||||
if (fDesktop->ReadLockClipping()) {
|
||||
BRegion dirty(fBorderRegion);
|
||||
dirty.IntersectWith(&fVisibleRegion);
|
||||
fDesktop->MarkDirty(&dirty);
|
||||
BRegion dirty(fBorderRegion);
|
||||
dirty.IntersectWith(&fVisibleRegion);
|
||||
fDesktop->MarkDirty(&dirty);
|
||||
|
||||
fFocus = focus;
|
||||
|
||||
fDesktop->ReadUnlockClipping();
|
||||
}
|
||||
fFocus = focus;
|
||||
}
|
||||
|
||||
// MoveBy
|
||||
|
@ -35,7 +35,6 @@ SRCS= ClientLooper.cpp \
|
||||
DrawingEngine.cpp \
|
||||
main.cpp \
|
||||
MultiLocker.cpp \
|
||||
RWLocker.cpp \
|
||||
ViewLayer.cpp \
|
||||
WindowLayer.cpp
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user