app/django/utils/synch.py
author Sverre Rabbelier <srabbelier@gmail.com>
Tue, 02 Dec 2008 20:10:23 +0000
changeset 649 95a41542e693
parent 54 03e267d67478
permissions -rw-r--r--
Finish Program Added some fields, and made TinyMCE the editor for the description field. Also updated the public page to show these new fields. We really need generic public views... Patch by: Sverre Rabbelier

"""
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()