Door¶
The main feature of the Door library is its synchronization proxy implementation.
Typically, when locks are used, there is a risk that, due to programmer error, a race condition is introduced by improperly accessing data.
Doors support the following scenarios:
Multithreading;
Multiprocessing;
Asynchronous programming.
As long as the primitive implements door.primitives.Acquirable, they
are compatible with acquirable doors.
Supports:
Lock;
RLock;
Condition;
Semaphore;
BoundedSemaphore;
et cetera.
Implementations:
As long as the primitive implements door.primitives.Waitable, they
are compatible with waitable doors.
Supports:
Condition;
et cetera.
Implementations:
As long as the primitive implements door.primitives.SAcquirable, they
are compatible with shared acquirable doors.
RSLock (Read-preferring shared lock);
WSLock (Write-preferring shared lock);
RSCondition (Read-preferring shared condition variables);
WSCondition (Write-preferring shared condition variables);
et cetera.
Implementations:
As long as the primitive implements door.primitives.SWaitable, they
are compatible with shared waitable doors.
RSCondition (Read-preferring shared condition variables);
WSCondition (Write-preferring shared condition variables);
et cetera.
Implementations:
Below shows sample usages of doors.
First, initialize a resource.
>>> from dataclasses import dataclass
>>> @dataclass
... class Resource:
... key: str = 'value'
...
>>> resource = Resource()
>>> resource
Resource(key='value')
>>> resource.key
'value'
Now, let’s use acquirable door.
>>> from door.threading2 import AcquirableDoor
>>> door = AcquirableDoor(resource)
>>> with door() as proxy:
... proxy.key
... proxy.key = 'VALUE'
... proxy.key
...
'value'
'VALUE'
Outside, the proxy is closed.
>>> proxy.key
Traceback (most recent call last):
...
ValueError: no read permission
>>> proxy.key = 'value'
Traceback (most recent call last):
...
ValueError: no write permission
Check the value of resource.
>>> resource
Resource(key='VALUE')
>>> resource.key
'VALUE'
Reset the resource.
>>> resource = Resource()
>>> resource
Resource(key='value')
>>> resource.key
'value'
We can also use shared acquirable doors. Acquirable doors allow client to specify the type of operation they want.
>>> from door.threading2 import SAcquirableDoor
>>> door = SAcquirableDoor(resource)
>>> with door.read() as proxy:
... proxy.key
...
'value'
>>> with door.read() as proxy:
... proxy.key = 'VALUE'
...
Traceback (most recent call last):
...
ValueError: no write permission
>>> with door.write() as proxy:
... proxy.key
... proxy.key = 'VALUE'
... proxy.key
...
'value'
'VALUE'
>>> proxy.key
Traceback (most recent call last):
...
ValueError: no read permission
>>> proxy.key = 'value'
Traceback (most recent call last):
...
ValueError: no write permission
>>> resource
Resource(key='VALUE')
>>> resource.key
'VALUE'