app/django/utils/synch.py
changeset 54 03e267d67478
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/app/django/utils/synch.py	Fri Jul 18 18:22:23 2008 +0000
@@ -0,0 +1,87 @@
+"""
+Synchronization primitives:
+
+    - reader-writer lock (preference to writers)
+
+(Contributed to Django by eugene@lazutkin.com)
+"""
+
+try:
+    import threading
+except ImportError:
+    import dummy_threading as threading
+
+class RWLock:
+    """
+    Classic implementation of reader-writer lock with preference to writers.
+
+    Readers can access a resource simultaneously.
+    Writers get an exclusive access.
+
+    API is self-descriptive:
+        reader_enters()
+        reader_leaves()
+        writer_enters()
+        writer_leaves()
+    """
+    def __init__(self):
+        self.mutex     = threading.RLock()
+        self.can_read  = threading.Semaphore(0)
+        self.can_write = threading.Semaphore(0)
+        self.active_readers  = 0
+        self.active_writers  = 0
+        self.waiting_readers = 0
+        self.waiting_writers = 0
+
+    def reader_enters(self):
+        self.mutex.acquire()
+        try:
+            if self.active_writers == 0 and self.waiting_writers == 0:
+                self.active_readers += 1
+                self.can_read.release()
+            else:
+                self.waiting_readers += 1
+        finally:
+            self.mutex.release()
+        self.can_read.acquire()
+
+    def reader_leaves(self):
+        self.mutex.acquire()
+        try:
+            self.active_readers -= 1
+            if self.active_readers == 0 and self.waiting_writers != 0:
+                self.active_writers  += 1
+                self.waiting_writers -= 1
+                self.can_write.release()
+        finally:
+            self.mutex.release()
+
+    def writer_enters(self):
+        self.mutex.acquire()
+        try:
+            if self.active_writers == 0 and self.waiting_writers == 0 and self.active_readers == 0:
+                self.active_writers += 1
+                self.can_write.release()
+            else:
+                self.waiting_writers += 1
+        finally:
+            self.mutex.release()
+        self.can_write.acquire()
+
+    def writer_leaves(self):
+        self.mutex.acquire()
+        try:
+            self.active_writers -= 1
+            if self.waiting_writers != 0:
+                self.active_writers  += 1
+                self.waiting_writers -= 1
+                self.can_write.release()
+            elif self.waiting_readers != 0:
+                t = self.waiting_readers
+                self.waiting_readers = 0
+                self.active_readers += t
+                while t > 0:
+                    self.can_read.release()
+                    t -= 1
+        finally:
+            self.mutex.release()