summaryrefslogtreecommitdiffstats
path: root/webapp/django/utils/synch.py
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/django/utils/synch.py')
-rw-r--r--webapp/django/utils/synch.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/webapp/django/utils/synch.py b/webapp/django/utils/synch.py
new file mode 100644
index 0000000000..2e808c1e01
--- /dev/null
+++ b/webapp/django/utils/synch.py
@@ -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()