Synchronizations#

Instantiating and operating features in multirunnable is classified to 2 modules. Modules in subpackage multirunnable.adapter be a factories which has responsibility of generating target instance of running strategy. And for multirunnable.api, its responsibility for operating.

Factory Modules#

module multirunnable.factory

It focuses on generating instance but doesn’t care about how to operating it. It’s an factory to generate the target instance, so it would returns different instance with different RunningMode. Below are the mapping table about which instance it generates with different RunningMode:

Factory

Running Mode

Truly Instance

Lock

Parallel

multiprocessing.Lock

Concurrent

threading.Lock

Coroutine (Green Thread)

gevent.threading.Lock

Coroutine (Asynchronous)

asyncio.locks.Lock

RLock

Parallel

multiprocessing.RLock

Concurrent

threading.RLock

Coroutine (Green Thread)

gevent.lock.RLock

Coroutine (Asynchronous)

asyncio.locks.RLock

Semaphore

Parallel

multiprocessing.Semaphore

Concurrent

threading.Semaphore

Coroutine (Green Thread)

gevent.lock.Semaphore

Coroutine (Asynchronous)

asyncio.locks.Semaphore

Bounded Semaphore

Parallel

multiprocessing.BoundedSemaphore

Concurrent

threading.BoundedSemaphore

Coroutine (Green Thread)

gevent.lock.BoundedSemaphore

Coroutine (Asynchronous)

asyncio.locks.BoundedSemaphore

Event

Parallel

multiprocessing.Event

Concurrent

threading.Event

Coroutine (Green Thread)

gevent.event.Event

Coroutine (Asynchronous)

asyncio.Event

Condition

Parallel

multiprocessing.Condition

Concurrent

threading.Condition

Coroutine (Green Thread)

(Not Support)

Coroutine (Asynchronous)

asyncio.Condition

Lock Modules#

module multirunnable.factory.lock

The module doesn’t only response of Lock. All synchronization features which could limit the performance but DOES NOT communicate with each others like Lock, Semaphore, etc.

It was named as LockAdapter before version 0.17.0. Same as classes in it (Lock, Semaphore, etc).

LockFactory#

class multirunnable.factory.lock.LockFactory

The implement about generating Lock instance.

get_instance(**kwargs)

Instantiate the Lock instance by FeatureMode which be assigned by RunningMode.

It could pass arguments if its instantiating needs.

Parameters:
  • kwargs (Dict) : A argument of the Lock object.

Return:

An instance of Lock.

globalize_instance(obj: MRLock)

Assign the object as a global variable.

Parameters:
  • obj (multirunnsble.types.MRLock) : An instance of Lock.

Return:

None.

RLockFactory#

class multirunnable.factory.lock.RLockFactoryFactory

It’s same as multirunnable.factory.lock.LockFactory but for RLock.

SemaphoreFactory#

class multirunnable.factory.lock.SemaphoreFactoryFactory

It’s same as multirunnable.factory.lock.LockFactory but for Semaphore.

BoundedSemaphoreFactory#

class multirunnable.factory.lock.BoundedSemaphoreFactory

It’s same as multirunnable.factory.lock.LockFactory but for BoundedSemaphore.

Communication Modules#

module multirunnable.factory.communication

All synchronization features which could limit the performance AND could communicate with each others like Event, Condition.

It will be modified to naming as CommunicationFactory in version 0.17.0. Same as classes in it (Event, Condition).

EventFactory#

class multirunnable.factory.communication.EventFactory

It’s same as multirunnable.factory.lock.LockFactory but for Event.

ConditionFactory#

class multirunnable.factory.communication.ConditionFactory

It’s same as multirunnable.factory.lock.LockFactory but for Condition.

API Modules#

module multirunnable.api

All operators of MultiRunnable is the responsibility of this subpackage. Including synchronizations like Lock, Semaphore or something like this and retry mechanism. For synchronization features, multirunnable.factory focus on generating instance, multirunnable.api focus on operating something with the instance.

Operator Modules#

module multirunnable.api.operator

This module responses of some operators of synchronization-features.

LockOperator#

class multirunnable.api.operator.LockOperator()

Operators of feature Lock. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_get_feature_instance()

Return a Lock instance which be get from global variable be saved in module multirunnable.api.manage. Therefore, this return value would be the same as multirunnable.api.manage.Running_Lock.

Return:

An instance of Lock.

acquire()

Acquire a lock to limit performance so that it’s force to run ONLY ONE runnable object at the same time.

Return:

None.

release()

Release the lock to let other runnable objects could acquire it.

Return:

None.

RLockOperator#

class multirunnable.api.operator.RLockOperator()

Operators of feature RLock. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_get_feature_instance()

Same as LockOperator._get_feature_instance. It returns value would be the same as multirunnable.api.manage.Running_RLock.

Return:

An instance of RLock.

acquire(blocking=True, timeout=None)

Acquire a lock to limit performance so that it’s force to run ONLY ONE runnable object at the same time. Different is it could acquire lock again and again in runtime. But remember, how many it acquires, how many it needs to release.

Parameters:
  • blocking (bool) : It would block until RLock resource has been released if blocking is True, or it doesn’t.

  • timeout (int) : The most number of seconds it would block.

Return:

None.

release()

Same as Lock.acquire. Difference is program would keep run util last one release be called.

Return:

None.

SemaphoreOperator#

class multirunnable.api.operator.SemaphoreOperator()

Operators of feature Semaphore. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_get_feature_instance()

Same as LockOperator._get_feature_instance. It returns value would be the same as multirunnable.api.manage.Running_Semaphore.

Return:

An instance of Semaphore.

acquire(blocking: bool = True, timeout: int = None)

It’s mostly same as Lock. It force to only one runnable object could run at the same time with Lock. For Semaphore, it permits multiple runnable objects to run simultaneously and the permitted amount is the value of option value of multirunnable.factory.lock.Semaphore.

Parameters:
  • blocking (bool) : It would block until Semaphore resource has been released if blocking is True, or it doesn’t.

  • timeout (int) : The most number of seconds it would block.

Return:

None.

release(n: int = 1)

The logic is same as Lock.release but be used for Semaphore.

Parameters:
  • n (int) : How many semaphore it should release.

Return:

None.

BoundedSemaphoreOperator#

class multirunnable.api.operator.BoundedSemaphoreOperator()

Operators of feature Bounded Semaphore. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_get_feature_instance()

Same as LockOperator._get_feature_instance. It returns value would be the same as multirunnable.api.manage.Running_Bounded_Semaphore.

Return:

An instance of BoundedSemaphore.

acquire(blocking: bool = True, timeout: int = None)

This implement is same as SemaphoreOperator.acquire.

Parameters:
  • blocking (bool) : It would block until BoundedSemaphore resource has been released if blocking is True, or it doesn’t.

  • timeout (int) : The most number of seconds it would block.

Return:

None.

release(n: int = 1)

It’s also same as SemaphoreOperator.acquire but the only one different is it has limitation (the argument n) in every time it releases.

Parameters:
  • n (int) : How many semaphore it should release.

Return:

None.

EventOperator#

class multirunnable.api.operator.EventOperator()

Operators of feature Event. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_event_instance()

Return the Event instance.

Return:

An instance of Event.

_get_feature_instance()

Same as LockOperator._get_feature_instance. It returns value would be the same as multirunnable.api.manage.Running_Event.

Return:

An instance of Event.

set()

Set a flag to tell other runnable objects could run.

Return:

None.

is_set()

Return bool type value. It’s True if flag be set or it’s False.

Return:

A boolean value.

wait(timeout: int = None)

Let runnable object waits util flag be set by the method set.

Parameters:
  • timeout (int) : The most number of seconds it would block.

Return:

A boolean value.

clear()

Clear all flags.

Return:

None.

ConditionOperator#

class multirunnable.api.operator.ConditionOperator()

Operators of feature Condition. This feature do the same thing as the truly instance we call. Please refer to below to get more details:

_get_feature_instance()

Same as LockOperator._get_feature_instance. It returns value would be the same as multirunnable.api.manage.Running_Condition.

Return:

An instance of Condition.

acquire(blocking: bool = True, timeout: int = None)

Acquire a lock to limit performance. It’s same as LockOperator.acquire.

Parameters:
  • blocking (bool) : It would block until Condition resource has been released if blocking is True, or it doesn’t.

  • timeout (int) : The most number of seconds it would block.

Return:

A boolean value.

release()

Same as LockOperator.release.

Return:

None.

wait(timeout: int = None)

Wait util notified or util a timeout occurs.

Parameters:
  • timeout (int) : The most number of seconds it would block.

Return:

None.

wait_for(predicate, timeout: int = None)

Wait until a condition evaluates to true.

Parameters:
  • predicate (Callable) : This should be a function which return value is boolean type. It would keep running if it satisfy predicate.

  • timeout (int) : The most number of seconds it would block.

Return:

A boolean value.

notify(n: int = 1)

By default, wait up one runnable object on this condition.

Parameters:
  • n (int) : How many runnable objects it should wake up to run on the condition.

Return:

None.

notify_all()

Wait up all runnable objects on this condition.

Return:

None.

Adapter Modules#

module multirunnable.adapter

Subpackage Adapter for clear and convenient in usage. It combines the features of both 2 subpackages Factory and API.

About synchronization usage in multirunnable, it divides to 2 sections: Factory and API. The former generates instance with RunningMode; the latter provides all operators of the instance. However, it doesn’t be clear or be convenient to use sometimes. It also needs to care 2 different objects when you’re using.

Let’s demonstrate some different usage between Adapter and Factory with API:

Usage with Adapter:

from multirunnable import RunningMode, SimpleExecutor, sleep
from multirunnable.adapter import Lock

_lock = Lock(mode=RunningMode.Parallel, init=True)    # Use Lock feature with Adapter object

def lock_function():
    _lock.acquire()
    print("This is ExampleTargetFunction.target_function.")
    sleep(3)
    _lock.release()

executor = SimpleExecutor(mode=RunningMode.Parallel, executors=5)
executor.run(function=lock_function)

Usage with Factory and API:

from multirunnable import RunningMode, SimpleExecutor, sleep
from multirunnable.api import LockOperator
from multirunnable.factory import LockFactory

def lock_function():
    _lock_opt = LockOperator()    # Use Lock feature with Operator object
    _lock_opt.acquire()
    print("This is ExampleTargetFunction.target_function.")
    sleep(3)
    _lock_opt.release()

executor = SimpleExecutor(mode=RunningMode.Parallel, executors=5)
lock = LockFactory()    # Use Lock feature with Factory object
executor.run(function=lock_function, features=lock)

About second one of above demonstrations, it generates instance by object LockFactory and operates the Lock feature with object LockOperator. It must to care about what thing to do and when to call it. But it doesn’t if it uses with object Lock.

Objects in it has all the attributes of Factory and API. And the attribute’s name also the same between them. So what attributes Factory or API they have, what attributes Adapter it has.

This is new in version 0.17.0.

The modules of subpackage Adapter: