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'