app/django/utils/synch.py
changeset 54 03e267d67478
equal deleted inserted replaced
53:57b4279d8c4e 54:03e267d67478
       
     1 """
       
     2 Synchronization primitives:
       
     3 
       
     4     - reader-writer lock (preference to writers)
       
     5 
       
     6 (Contributed to Django by eugene@lazutkin.com)
       
     7 """
       
     8 
       
     9 try:
       
    10     import threading
       
    11 except ImportError:
       
    12     import dummy_threading as threading
       
    13 
       
    14 class RWLock:
       
    15     """
       
    16     Classic implementation of reader-writer lock with preference to writers.
       
    17 
       
    18     Readers can access a resource simultaneously.
       
    19     Writers get an exclusive access.
       
    20 
       
    21     API is self-descriptive:
       
    22         reader_enters()
       
    23         reader_leaves()
       
    24         writer_enters()
       
    25         writer_leaves()
       
    26     """
       
    27     def __init__(self):
       
    28         self.mutex     = threading.RLock()
       
    29         self.can_read  = threading.Semaphore(0)
       
    30         self.can_write = threading.Semaphore(0)
       
    31         self.active_readers  = 0
       
    32         self.active_writers  = 0
       
    33         self.waiting_readers = 0
       
    34         self.waiting_writers = 0
       
    35 
       
    36     def reader_enters(self):
       
    37         self.mutex.acquire()
       
    38         try:
       
    39             if self.active_writers == 0 and self.waiting_writers == 0:
       
    40                 self.active_readers += 1
       
    41                 self.can_read.release()
       
    42             else:
       
    43                 self.waiting_readers += 1
       
    44         finally:
       
    45             self.mutex.release()
       
    46         self.can_read.acquire()
       
    47 
       
    48     def reader_leaves(self):
       
    49         self.mutex.acquire()
       
    50         try:
       
    51             self.active_readers -= 1
       
    52             if self.active_readers == 0 and self.waiting_writers != 0:
       
    53                 self.active_writers  += 1
       
    54                 self.waiting_writers -= 1
       
    55                 self.can_write.release()
       
    56         finally:
       
    57             self.mutex.release()
       
    58 
       
    59     def writer_enters(self):
       
    60         self.mutex.acquire()
       
    61         try:
       
    62             if self.active_writers == 0 and self.waiting_writers == 0 and self.active_readers == 0:
       
    63                 self.active_writers += 1
       
    64                 self.can_write.release()
       
    65             else:
       
    66                 self.waiting_writers += 1
       
    67         finally:
       
    68             self.mutex.release()
       
    69         self.can_write.acquire()
       
    70 
       
    71     def writer_leaves(self):
       
    72         self.mutex.acquire()
       
    73         try:
       
    74             self.active_writers -= 1
       
    75             if self.waiting_writers != 0:
       
    76                 self.active_writers  += 1
       
    77                 self.waiting_writers -= 1
       
    78                 self.can_write.release()
       
    79             elif self.waiting_readers != 0:
       
    80                 t = self.waiting_readers
       
    81                 self.waiting_readers = 0
       
    82                 self.active_readers += t
       
    83                 while t > 0:
       
    84                     self.can_read.release()
       
    85                     t -= 1
       
    86         finally:
       
    87             self.mutex.release()