00001 #include "atomic_util.h"
00002
00003 #ifdef WIN32
00004
00005 #include <windows.h>
00006 #include <LIMITS.H>
00007
00008 class ClassicRWLock
00009 {
00010 public:
00011 ClassicRWLock() :
00012 activeReader(0), waitingReader(0), activeWriter(0), waitingWriter(0)
00013 {
00014 InitializeCriticalSection(&cs);
00015 blockedReader = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
00016 blockedWriter = CreateSemaphore(NULL, 0, LONG_MAX, NULL);
00017 }
00018 ~ClassicRWLock()
00019 {
00020 DeleteCriticalSection(&cs);
00021 }
00022 void enter_read(void);
00023 void leave_read(void);
00024 void enter_write(void);
00025 void leave_write(void);
00026
00027 static const char *name() { return "ClassicRWLock"; }
00028
00029 private:
00030
00031 long activeReader;
00032 long waitingReader;
00033 long activeWriter;
00034 long waitingWriter;
00035 CRITICAL_SECTION cs;
00036 HANDLE blockedReader;
00037 HANDLE blockedWriter;
00038 };
00039
00040
00041
00042
00043
00044
00045 inline void ClassicRWLock::enter_read(void)
00046 {
00047 EnterCriticalSection(&cs);
00048
00049 if (activeWriter > 0 || waitingWriter > 0)
00050 {
00051 waitingReader++;
00052 LeaveCriticalSection(&cs);
00053 WaitForSingleObject(blockedReader, INFINITE);
00054 }
00055 else
00056 {
00057 activeReader++;
00058 LeaveCriticalSection(&cs);
00059 }
00060 }
00061
00062
00063
00064
00065
00066
00067 inline void ClassicRWLock::leave_read(void)
00068 {
00069 EnterCriticalSection(&cs);
00070 activeReader--;
00071
00072 if (activeReader == 0 && waitingWriter > 0)
00073 {
00074 activeWriter = 1;
00075 waitingWriter--;
00076 ReleaseSemaphore(blockedWriter, 1, NULL);
00077 }
00078 LeaveCriticalSection(&cs);
00079 }
00080
00081
00082
00083
00084
00085
00086 inline void ClassicRWLock::enter_write(void)
00087 {
00088 EnterCriticalSection(&cs);
00089 if (activeReader == 0 && activeWriter == 0)
00090 {
00091
00092 activeWriter = 1;
00093 LeaveCriticalSection(&cs);
00094 }
00095 else
00096 {
00097
00098 waitingWriter++;
00099 LeaveCriticalSection(&cs);
00100 WaitForSingleObject(blockedWriter, INFINITE);
00101 }
00102 }
00103
00104
00105
00106
00107
00108
00109 inline void ClassicRWLock::leave_write(void)
00110 {
00111 EnterCriticalSection(&cs);
00112 activeWriter = 0;
00113 if (waitingReader > 0)
00114 {
00115
00116 while (waitingReader > 0)
00117 {
00118 waitingReader--;
00119 activeReader++;
00120 ReleaseSemaphore(blockedReader, 1, NULL);
00121 }
00122 }
00123 else if (waitingWriter > 0)
00124 {
00125
00126
00127 waitingWriter--;
00128 activeWriter = 1;
00129 ReleaseSemaphore(blockedWriter, 1, NULL);
00130 }
00131 LeaveCriticalSection(&cs);
00132 }
00133
00134 #else // #ifdef WIN32
00135
00136 #include <pthread.h>
00137
00138
00139 class ClassicRWLock
00140 {
00141 private:
00142 pthread_mutex_t lock;
00143 pthread_cond_t rcond;
00144 pthread_cond_t wcond;
00145 int lock_count;
00146
00147
00148 int waiting_writers;
00149 public:
00150 ClassicRWLock()
00151 {
00152 pthread_mutex_init(&lock, NULL);
00153 pthread_cond_init(&wcond, NULL);
00154 pthread_cond_init(&rcond, NULL);
00155 lock_count = 0;
00156 waiting_writers = 0;
00157 }
00158 ~ClassicRWLock()
00159 {
00160 pthread_mutex_destroy(&lock);
00161 pthread_cond_destroy(&wcond);
00162 pthread_cond_destroy(&rcond);
00163 }
00164
00165 void enter_write(void)
00166 {
00167 pthread_mutex_lock(&lock);
00168 waiting_writers++;
00169 while(lock_count)
00170 pthread_cond_wait(&wcond, &lock);
00171 waiting_writers--;
00172 lock_count = -1;
00173 pthread_mutex_unlock(&lock);
00174 }
00175 void leave_write(void)
00176 {
00177 pthread_mutex_lock(&lock);
00178 lock_count = 0;
00179 if(waiting_writers == 0)
00180 pthread_cond_broadcast(&rcond);
00181 else
00182 pthread_cond_signal(&wcond);
00183 pthread_mutex_unlock(&lock);
00184 }
00185
00186 void enter_read(void)
00187 {
00188 pthread_mutex_lock(&lock);
00189 while(lock_count < 0)
00190 pthread_cond_wait(&rcond, &lock);
00191 lock_count++;
00192 pthread_mutex_unlock(&lock);
00193 }
00194 void leave_read(void)
00195 {
00196 pthread_mutex_lock(&lock);
00197 lock_count--;
00198 if (!lock_count)
00199 pthread_cond_signal(&wcond);
00200 pthread_mutex_unlock(&lock);
00201 }
00202
00203 static const char *name() { return "ClassicRWLock"; }
00204 };
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 #endif // #ifdef WIN32
00231
00232