root/src/tests/servers/app/newerClipping/MultiLocker.h
/* MultiLocker.h */
/*
        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 */

#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()
                                                                {
                                                                        fLock->WriteUnlock();
                                                                }
 private:
                MultiLocker*                    fLock;
};

class AutoReadLocker {
 public:
                                                                AutoReadLocker(MultiLocker* lock)
                                                                        : fLock(lock)
                                                                {
                                                                        fLock->ReadLock();
                                                                }
                                                                ~AutoReadLocker()
                                                                {
                                                                        fLock->ReadUnlock();
                                                                }
 private:
                MultiLocker*                    fLock;
};



#endif