Source code for rwlock.imp_1.imp

"""
Module **rwlock.imp_1.imp** has class ``Imp`` that implements
the read-write-lock service.
To instantiate and drive ``Imp`` from **rwlock/user.py**, in the parent
directory run "``python user.py <num_threads> <num_ops> imp_1.imp <mri>``".
Or instantiate ``Imp`` in your own program and drive it from there.
"""

from threading import Lock, Condition
import argparse, sys

[docs]class Imp: """ An implementation of the read-write-lock service. Ensures writers do not starve by limiting a "read interval" to at most *mri* reads, where *mri* is an initialization argument. (A "read" interval starts when ``nr`` becomes non-zero and ends when ``nr`` becomes zero.) Imp has functions ``acqw()``, ``relr()``, ``acqw()`` and ``relw()``. It maintains the following variables: - ``mri`` (constant int): max number of reads in a "read" interval; set to ``__init__`` parameter ``mri``. - ``nr`` (int): number of threads holding a read lock; initially 0. - ``nw`` (int): number of threads holding a write lock; initially 0. - ``nx`` (int): number of reads started in current interval; initially 0. - ``lck`` (lock): protects ``nr`` and ``nw``. - ``cvr`` (condition): to wait for ``nw == 0`` and ``nx < max_nx`` - ``cvw`` (condition): to wait for ``nr`` and ``nw`` equal to 0. When a thread executes ``acqw()``, it waits on ``cvw`` until ``nr`` and ``nw`` are both 0, then increments ``nw`` and returns. At this point, no thread can acquire a write lock or a read lock. When a thread executes ``relw()``, it decrements ``nw`` and returns. When a thread executes ``acqr()``, it waits on ``cvr`` until ``nw == 0`` and ``nx < mri`` hold, then increments ``nr`` and ``nx``, and returns. At this point a thread cannot get a write lock, and can get a read lock only if ``nx < mri`` holds. When a thread executes ``relr()``, it decrements ``nr`` and, if ``nr`` has become zero, zeros ``nx``. """ def __init__(self, argv): p = argparse.ArgumentParser() p.add_argument('mri', type=int, help='max number of reads in a read interval') args = p.parse_args(argv[1:]) self.mri = args.mri self.nr = 0 self.nw = 0 self.nx = 0 self.lck = Lock() self.cvr = Condition(self.lck) self.cvw = Condition(self.lck) def acqr(self): with self.cvr: while self.nw > 0 or self.nx == self.mri: self.cvr.wait() self.nr += 1 self.nx += 1 def relr(self): with self.lck: self.nr -= 1 if self.nr == 0: self.nx = 0 self.cvw.notify() self.cvr.notify_all() def acqw(self): with self.cvw: while self.nr + self.nw > 0: self.cvw.wait() self.nw += 1 def relw(self): with self.lck: self.nw -= 1 self.cvr.notify_all() self.cvw.notify()
##### end class Imp ############################# if __name__ == '__main__': imp = Imp(sys.argv)