00001 /* **************************************************************************** 00002 * Owner: Evgeniy Makeev 00003 * Created by: Evgeniy Makeev 00004 * **************************************************************************** 00005 */ 00006 #ifndef __EVG_RW_LOCK_H_Included__ 00007 #define __EVG_RW_LOCK_H_Included__ 00008 00009 #include "atomic_util.h" 00010 #include "system_abstraction.h" 00011 00012 /*---------------------------------*/ 00013 /* Written by Evgeniy Makeev, 2000 */ 00014 /*---------------------------------*/ 00015 // 00016 // Multiple readers - one writer interface class. 00017 // Implements multiple readers one writer mechanism. 00018 // Optimizes readers speed, provides fast readers 00019 // synchronization when no writers are waiting. 00020 // Useful when data is needed to be written/changed 00021 // only occasionally but it is read often by multiple 00022 // threads. 00023 // 00024 00025 class SharedCounterRWLock 00026 { 00027 volatile int rwdata; 00028 // 00029 // Can be overwritten with a system specific yield thread 00030 // or sleep implementation 00031 // 00032 inline void yield() 00033 { 00034 thread_yield(); 00035 } 00036 00037 public: 00038 static const char *name() { return "Shared_Counter_Lock"; } 00039 00040 SharedCounterRWLock() : rwdata(0L) {} 00041 // 00042 // Must be called at the beginning of any read/data access. 00043 // 00044 inline void enter_read(void) 00045 { 00046 if(atomic_inc_return(&rwdata) & 0x80000000) 00047 for(;;) 00048 { 00049 if(atomic_dec_return(&rwdata) & 0x80000000) yield(); 00050 if((atomic_inc_return(&rwdata) & 0x80000000)==0) break; 00051 } 00052 } 00053 00054 // 00055 // Must be called at the end of any read/data access. 00056 // 00057 inline void leave_read(void) 00058 { 00059 atomic_dec(&rwdata); 00060 } 00061 00062 // 00063 // Must be called at the beginning of a write operation 00064 // 00065 inline void enter_write(void) 00066 { 00067 for(;;) 00068 { 00069 if(atomic_cmpexch_return(&rwdata, 0x80000000, 0) == 0) break; 00070 if(rwdata) yield(); 00071 } 00072 } 00073 00074 // 00075 // Must be called at the end of a write operation 00076 // 00077 inline void leave_write(void) 00078 { 00079 atomic_and(&rwdata, ~0x80000000); 00080 // atomic_add(&rwdata, 0x80000000); 00081 } 00082 }; 00083 00084 #endif // __EVG_RW_LOCK_H_Included__ 00085 00086 00087
1.5.5