From 425db0d5647a4a9a96b38ea8b6930c2cc8e07a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Ma=C5=9Blanka?= <piotr.maslanka@henrietta.com.pl> Date: Mon, 30 Dec 2019 21:19:52 +0100 Subject: [PATCH] fixed the docs for Monitor --- docs/coding/concurrent.rst | 48 ++++++++++++++++++++++++++++ docs/coding/monitor.md | 42 ------------------------ docs/index.rst | 1 - satella/coding/concurrent/monitor.py | 47 +++++++++++++-------------- 4 files changed, 71 insertions(+), 67 deletions(-) delete mode 100644 docs/coding/monitor.md diff --git a/docs/coding/concurrent.rst b/docs/coding/concurrent.rst index d6d67905..0a39ef1f 100644 --- a/docs/coding/concurrent.rst +++ b/docs/coding/concurrent.rst @@ -25,3 +25,51 @@ It means that if it's hanging on I/O, for example, it won't be affected. .. autoclass:: satella.coding.concurrent.TerminableThread :members: + +Monitor +======= + +A monitor is a Java-like synchronization idea. Inheriting from Monitor outfits the class with a Lock +(or a reentrant lock, if *RMonitor* is used), that can be used to coordinate access to some shared resource. + +Take care to invoke Monitor's constructor when inheriting, or this won't work. + +You can decorate your methods with *Monitor.synchronized* to have them execute with the lock acquired. +If you have such a method, you can also temporarily release the lock using context manager _Monitor.release_ +(it will be reacquired) when context manager is exited. + +You can also use manual synchronization with context manager *Monitor.acquire*. + +:: + + from satella.coding import Monitor + + + class MyProtectedClass(Monitor): + def __init__(self, *args): + super(Monitor, self).__init__() + + @Monitor.synchronized + def synchronized(self): + pass # everything here is executed with class lock acquired + + @Monitor.synchronized + def temporary_release(self): + pass # lock is acquired here + with Monitor.release(self): + pass # lock is NOT ACQUIRED here + pass # and here it's reacquired again + + def manual_sync(self): + pass # not synchronized + with Monitor.acquire(self): + pass # synchronized + + +You can also use *Monitor.release* and *Monitor.acquire* with other objects than self, but exercise +caution and think over the consequences. + +.. autoclass:: satella.coding.concurrent.Monitor + :members: + +.. autoclass:: satella.coding.concurrent.RMonitor diff --git a/docs/coding/monitor.md b/docs/coding/monitor.md deleted file mode 100644 index 491bcba1..00000000 --- a/docs/coding/monitor.md +++ /dev/null @@ -1,42 +0,0 @@ -# Monitor - -A monitor is a Java-like synchronization idea. Inheriting from _Monitor_ outfits the class with a Lock -(or a reentrant lock, if _RMonitor_ is used), that can be used to coordinate access to some shared resource. - -Take care to invoke _Monitor's_ constructor when inheriting, or this won't work. - -You can decorate your methods with _Monitor.synchronized_ to have them execute with the lock acquired. -If you have such a method, you can also temporarily release the lock using context manager _Monitor.release_ -(it will be reacquired) when context manager is exited. - -You can also use manual synchronization with context manager _Monitor.acquire_. - -```python -from satella.coding import Monitor - - -class MyProtectedClass(Monitor): - def __init__(self, *args): - super(Monitor, self).__init__() - - @Monitor.synchronized - def synchronized(self): - pass # everything here is executed with class lock acquired - - @Monitor.synchronized - def temporary_release(self): - pass # lock is acquired here - with Monitor.release(self): - pass # lock is NOT ACQUIRED here - pass # and here it's reacquired again - - def manual_sync(self): - pass # not synchronized - with Monitor.acquire(self): - pass # synchronized - -``` - -You can also use _Monitor.release_ and _Monitor.acquire_ with other objects than self, but exercise -caution and think over the consequences. - diff --git a/docs/index.rst b/docs/index.rst index 8a69a3f3..416955c7 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -8,7 +8,6 @@ Welcome to satella's documentation! configuration/index configuration/schema configuration/sources - coding/monitor coding/functions coding/structures coding/concurrent diff --git a/satella/coding/concurrent/monitor.py b/satella/coding/concurrent/monitor.py index 2927304b..ecfa67d0 100644 --- a/satella/coding/concurrent/monitor.py +++ b/satella/coding/concurrent/monitor.py @@ -14,19 +14,19 @@ class Monitor: Use it like that: - class MyProtectedObject(Monitor): - def __init__(self, *args, **kwargs): - Monitor.__init__(self) - ... do your job .. - - @Monitor.synchronized - def function_that_needs_mutual_exclusion(self): - .. do your threadsafe jobs .. - - def function_that_partially_needs_protection(self): - .. do your jobs .. - with Monitor.acquire(self): - .. do your threadsafe jobs .. + >>> class MyProtectedObject(Monitor): + >>> def __init__(self, *args, **kwargs): + >>> Monitor.__init__(self) + >>> ... do your job .. + + >>> @Monitor.synchronized + >>> def function_that_needs_mutual_exclusion(self): + >>> .. do your threadsafe jobs .. + + >>> def function_that_partially_needs_protection(self): + >>> .. do your jobs .. + >>> with Monitor.acquire(self): + >>> .. do your threadsafe jobs .. """ def __init__(self, obj=None): @@ -60,16 +60,15 @@ class Monitor: but you feel that you can release it for a while as it would improve parallelism. You can use it as such: - @Monitor.synchronized - def protected_function(self): - .. do some stuff that needs mutual exclusion .. - with Monitor.release(self): - .. do some I/O that doesn't need mutual exclusion .. - .. back to protected stuff .. - + >>> @Monitor.synchronized + >>> def protected_function(self): + >>> .. do some stuff that needs mutual exclusion .. + >>> with Monitor.release(self): + >>> .. do some I/O that doesn't need mutual exclusion .. + >>> .. back to protected stuff .. """ - def __init__(self, foo): + def __init__(self, foo: 'Monitor'): self.foo = foo def __enter__(self): @@ -89,11 +88,11 @@ class Monitor: Consider foo, which is a monitor. If you needed to lock it from outside, you would do: - with Monitor.acquire(foo): - .. do operations on foo that need mutual exclusion .. + >>> with Monitor.acquire(foo): + >>> .. do operations on foo that need mutual exclusion .. """ - def __init__(self, foo): + def __init__(self, foo: 'Monitor'): self.foo = foo def __enter__(self): -- GitLab