00001
00002
00003
00004
00005
00006 #ifndef __EVG_W32_RW_LOCK_H_Included__
00007 #define __EVG_W32_RW_LOCK_H_Included__
00008
00009 #include <Windows.h>
00010 #include "atomic_util.h"
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 class EvgW32RWLock
00027 {
00028 volatile long rwdata;
00029 volatile long waiting_readers;
00030 volatile long waiting_writers;
00031 HANDLE readers_iocport;
00032 HANDLE writers_iocport;
00033
00034
00035
00036
00037 inline void yield()
00038 {
00039 Sleep(0);
00040 }
00041
00042 inline void reader_wait(long milliseconds)
00043 {
00044 DWORD ln;
00045 ULONG_PTR key;
00046 LPOVERLAPPED ovlp;
00047 GetQueuedCompletionStatus(
00048 readers_iocport,
00049 &ln,
00050 &key,
00051 &ovlp,
00052 milliseconds);
00053 }
00054 inline void signal_readers(void)
00055 {
00056 long i, w=waiting_readers;
00057 for(i=0; i<w; i++)
00058 {
00059 PostQueuedCompletionStatus(
00060 readers_iocport,
00061 0,
00062 NULL,
00063 NULL);
00064 }
00065 }
00066 inline void writer_wait(long milliseconds)
00067 {
00068 DWORD ln;
00069 ULONG_PTR key;
00070 LPOVERLAPPED ovlp;
00071 GetQueuedCompletionStatus(
00072 writers_iocport,
00073 &ln,
00074 &key,
00075 &ovlp,
00076 milliseconds);
00077 }
00078 inline void signal_writers(void)
00079 {
00080 long i, w=waiting_writers;
00081
00082 for(i=0; i<w; w++)
00083 {
00084 PostQueuedCompletionStatus(
00085 writers_iocport,
00086 0,
00087 NULL,
00088 NULL);
00089 }
00090 }
00091 public:
00092 static const char *name() { return "Evgeniy's W32 RW Lock"; }
00093
00094 EvgW32RWLock() : rwdata(0L), waiting_readers(0), waiting_writers(0)
00095 {
00096 readers_iocport = CreateIoCompletionPort(
00097 INVALID_HANDLE_VALUE,
00098 NULL,
00099 NULL,
00100 0);
00101 writers_iocport = CreateIoCompletionPort(
00102 INVALID_HANDLE_VALUE,
00103 NULL,
00104 NULL,
00105 0);
00106 }
00107
00108 virtual ~EvgW32RWLock()
00109 {
00110 CloseHandle(readers_iocport);
00111 CloseHandle(writers_iocport);
00112 }
00113
00114
00115
00116 inline void enter_read(void)
00117 {
00118
00119
00120 if((atomic_inc(rwdata) & 0x80000000) == 0) break;
00121 if(atomic_dec(rwdata) & 0x80000000)
00122 {
00123 take_writer_lock();
00124 atomic_inc(rwdata);
00125 release_writer_lock();
00126 }
00127
00128 }
00129
00130
00131
00132 inline void leave_read(void)
00133 {
00134 atomic_dec(rwdata);
00135 }
00136
00137
00138
00139 inline void enter_write(void)
00140 {
00141 for(;;)
00142 {
00143 if(InterlockedCompareExchange(&rwdata, 0x80000000, 0) == 0) break;
00144 writer_wait(100);
00145 }
00146 atomic_dec(waiting_writers);
00147 }
00148
00149
00150
00151
00152 inline void leave_write(void)
00153 {
00154 InterlockedExchangeAdd(&rwdata, 0x80000000);
00155 signal_readers();
00156 }
00157 };
00158
00159 #endif // __EVG_W2_RW_LOCK_H_Included__
00160
00161
00162