haiku/src/servers/app/MultiLocker.h
Stephan Aßmus 39c9925fcf * implemented a BRegion pool per WindowLayer which is supposed
to cut down on BRegion related allocations, cannot really tell
  if it speeds things up
* used the new BRegion pool in WindowLayer and ViewLayer whereever
  a BRegion was used on the stack
* fixed the debugging stuff in MultiLocker - it will get you into
  the debugger if you
    - try to nest read locks
    - try to write lock when your are a reader already
    - don't match up nested locks when your a writer
    -> but only if you #define DEBUG 1 in the .cpp, is off by default now
* went over WindowLayer, ServerWindow, Desktop and a few other places
  and fixed the locking for use with the MultiLocker, the "a reader can
  not become a writer" is especially tricky, feel free to review the
  changes
* activated the MultiLocker, I tested this quite a bit, if there are
  problems simply turn on DEBUG and you should drop into the debugger
  right where the problem is... hope all is good


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17046 a95241bf-73f2-0310-859d-f6bbb57e9c96
2006-04-07 19:14:25 +00:00

136 lines
3.0 KiB
C++

/* MultiLocker.h */
/*
Copyright 2005-2006, Haiku.
Distributed under the terms of the MIT license.
Copyright 1999, Be Incorporated. All Rights Reserved.
This file may be used under the terms of the Be Sample Code License.
*/
/** multiple-reader single-writer locking class */
// IMPORTANT:
// * nested read locks are not supported
// * a reader becomming the write is not supported
// * nested write locks are supported
// * a writer can do read locks, even nested ones
// * in case of problems, #define DEBUG 1 in the .cpp
#ifndef MULTI_LOCKER_H
#define MULTI_LOCKER_H
//#define TIMING 1
#include <OS.h>
const int32 LARGE_NUMBER = 100000;
class MultiLocker {
public:
MultiLocker(const char* semaphoreBaseName);
virtual ~MultiLocker();
status_t InitCheck();
//locking for reading or writing
bool ReadLock();
bool WriteLock();
//unlocking after reading or writing
bool ReadUnlock();
bool WriteUnlock();
//does the current thread hold a write lock ?
bool IsWriteLocked(uint32 *stack_base = NULL,
thread_id *thread = NULL);
//in DEBUG mode returns whether the lock is held
//in non-debug mode returns true
bool IsReadLocked();
private:
//functions for managing the DEBUG reader array
void register_thread();
void unregister_thread();
status_t fInit;
//readers adjust count and block on fReadSem when a writer
//hold the lock
int32 fReadCount;
sem_id fReadSem;
//writers adjust the count and block on fWriteSem
//when readers hold the lock
int32 fWriteCount;
sem_id fWriteSem;
//writers must acquire fWriterLock when acquiring a write lock
int32 fLockCount;
sem_id fWriterLock;
int32 fWriterNest;
thread_id fWriterThread;
uint32 fWriterStackBase;
int32 * fDebugArray;
int32 fMaxThreads;
#if TIMING
uint32 rl_count;
bigtime_t rl_time;
uint32 ru_count;
bigtime_t ru_time;
uint32 wl_count;
bigtime_t wl_time;
uint32 wu_count;
bigtime_t wu_time;
uint32 islock_count;
bigtime_t islock_time;
uint32 reg_count;
bigtime_t reg_time;
uint32 unreg_count;
bigtime_t unreg_time;
#endif
};
class AutoWriteLocker {
public:
AutoWriteLocker(MultiLocker* lock)
: fLock(*lock)
{
fLock.WriteLock();
}
AutoWriteLocker(MultiLocker& lock)
: fLock(lock)
{
fLock.WriteLock();
}
~AutoWriteLocker()
{
fLock.WriteUnlock();
}
private:
MultiLocker& fLock;
};
class AutoReadLocker {
public:
AutoReadLocker(MultiLocker* lock)
: fLock(*lock)
{
fLock.ReadLock();
}
AutoReadLocker(MultiLocker& lock)
: fLock(lock)
{
fLock.ReadLock();
}
~AutoReadLocker()
{
fLock.ReadUnlock();
}
private:
MultiLocker& fLock;
};
#endif