Changeset 576
- Timestamp:
- 08/29/05 12:38:00
- Files:
-
- trunk/cherrypy/lib/filter/sessionfilter/mrow.py (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/cherrypy/lib/filter/sessionfilter/mrow.py
r575 r576 1 2 import threading3 1 4 2 # write should lock out everyone 5 3 # read should only lock out writing 6 4 5 import threading 6 7 try: 8 from threading import local 9 except ImportError: 10 from cherrypy._cpthreadinglocal import local 11 12 7 13 class MROWLock(object): 14 8 15 def __init__(self): 9 self.local = threading.local() 10 self.writelock = threading.RLock() # this is required so that multiple writers won't mess up writing event 11 self.writing = threading.Event() # must wait() for this; it'll tell you when a write is over (like a lock that you dont acquire, you just wiat for) 12 self.writing.set() # we are not writing to it right now 13 self.readers = [] # list of all reader Events. when clear, they are reading. must wait() for all of these to be sure no one is reading 14 self.readerslock = threading.RLock() # lock for readers list so it is not changed while looping 16 self.local = local() 17 # this is required so that multiple writers won't mess up writing event 18 self.writelock = threading.RLock() 19 # must wait() for this; it'll tell you when a write is over 20 # (like a lock that you dont acquire, you just wait for) 21 self.writing = threading.Event() 22 # we are not writing to it right now 23 self.writing.set() 24 # list of all reader Events. when clear, they are reading. 25 # must wait() for all of these to be sure no one is reading 26 self.readers = [] 27 # lock for readers list so it is not changed while looping 28 self.readerslock = threading.RLock() 15 29 16 30 def lock_read(self): … … 18 32 self.local.reader = threading.Event() 19 33 self.local.reader.set() 20 self.readerslock.acquire() # lock the list so it won't mess up the loop in lock_write 34 # lock the list so it won't mess up the loop in lock_write 35 self.readerslock.acquire() 21 36 self.readers.append(self.local.reader) 22 37 self.readerslock.release() 23 38 24 # only wait if the writing thread is not the thread same which is requesting a read lock 39 # only wait if the writing thread is not the thread same 40 # which is requesting a read lock 25 41 if not hasattr(self.local, 'writing'): 26 self.writing.wait() # wait for any writes to finish 27 42 # wait for any writes to finish 43 self.writing.wait() 44 28 45 # tell everyone we are reading 29 46 self.local.reader.clear() … … 34 51 if not hasattr(self.local, 'writing'): 35 52 self.local.writing = True 36 self.writing.wait() # wait for any writes to finish (this is a bit redundant with the next line) 53 # wait for any writes to finish 54 # (this is a bit redundant with the next line) 55 self.writing.wait() 37 56 38 57 self.writelock.acquire() 39 self.writing.clear() # lock out everyone reading from this dict 58 # lock out everyone reading from this dict 59 self.writing.clear() 40 60 self.readerslock.acquire() 41 61 for reader in self.readers: … … 49 69 50 70 def unlock_write(self): 51 self.writing.set() # wake everyone else up. TODO: what if one thread has the lock, and another calls this method? 71 # wake everyone else up. 72 # TODO: what if one thread has the lock, and another calls this method? 73 self.writing.set() 52 74 self.writelock.release() 53 75 54 76 55 77 class MROWDict(dict): 78 56 79 def __init__(self, auto_lock = False, auto_lock_safe = True, *args, **kwargs): 57 80 dict.__init__(self, *args, **kwargs) 58 81 self._locks = {} 59 82 self._lockslock = threading.RLock() 60 self._auto_lock = auto_lock # automatically acquire locks for getitem setitem (BAD IDEA) 61 self._auto_lock_safe = auto_lock_safe # when autolocking, lock the whole dict (GOOD IDEA) 83 # automatically acquire locks for getitem setitem (BAD IDEA) 84 self._auto_lock = auto_lock 85 # when autolocking, lock the whole dict (GOOD IDEA) 86 self._auto_lock_safe = auto_lock_safe 62 87 63 88 def _init_lock(self, key): … … 128 153 dict.update(self, values) 129 154 130 ''' 155 131 156 # test code 132 157 import time, thread 133 158 134 deadthreads = 0 135 136 def writer_thread(d, l): 137 global deadthreads 138 for i in range(0, 100): 139 l.lock_write() 140 hits = d["hits"] 141 hits = hits + 1 142 time.sleep(.01) 143 d["hits"] = hits 144 l.unlock_write() 145 deadthreads += 1 146 147 def reader_thread(d, l): 148 while True: 149 l.lock_read() 150 try: 151 hits = d["hits"] 152 if deadthreads == 3: 153 if d["hits"] != 300: 154 print "omfg error",d["hits"] 159 class MROWTest(object): 160 161 def __init__(self): 162 self.deadthreads = 0 163 self.hitdict = {"hits": 0} 164 self.lock = MROWLock() 165 for i in xrange(0, 2): 166 thread.start_new_thread(self.reader_thread, ()) 167 for i in range(0, 3): 168 thread.start_new_thread(self.writer_thread, ()) 169 self.reader_thread() 170 171 def writer_thread(self): 172 for i in xrange(100): 173 self.lock.lock_write() 174 hits = self.hitdict["hits"] + 1 175 time.sleep(.01) 176 self.hitdict["hits"] = hits 177 self.lock.unlock_write() 178 self.deadthreads += 1 179 180 def reader_thread(self): 181 while True: 182 self.lock.lock_read() 183 try: 184 hits = self.hitdict["hits"] 185 if self.deadthreads == 3: 155 186 break 156 else: 157 print "its all ok" 158 break 159 finally: 160 l.unlock_read() 161 time.sleep(.01) 162 163 def main(): 164 global deadthreads 165 deadthreads = 0 166 d = {} 167 d["hits"] = 0 168 l = MROWLock() 169 for i in range(0, 2): 170 thread.start_new_thread(reader_thread, (d,l)) 171 for i in range(0, 3): 172 thread.start_new_thread(writer_thread, (d,l)) 173 reader_thread(d, l) 187 finally: 188 self.lock.unlock_read() 189 time.sleep(.01) 190 191 if hits != 300: 192 print "omfg error", hits 193 else: 194 print "its all ok" 195 174 196 175 197 if __name__ == "__main__": 176 198 while True: 177 main() 178 ''' 199 MROWTest() 200 201 del time, thread, MROWTest

