ResourceMutex
Wrapper for locking API that uses two locks to not exhaust locking resources and still block properly.
The schematics here is:
- First acquire an access lock. This is using the type of the requested lock as key. Since the number of types is rather limited we can use the type as key as it will only eat up a limited number of lock resources on the system (files, semaphores)
- Second, we acquire the actual lock. We can be sure we are the only process at this very moment, hence we either get the lock for the given key or we get an error as we request a non-blocking mode.
Interleaving two locks is important, because the actual lock uses a hash value as key (see callers). If we would simply employ a normal blocking lock, we would get a potentially unlimited number of different locks. Depending on the available locking methods on the system we might run out of available resources: For instance maximum limit of semaphores is a system setting and applies to the whole system.
We therefore must make sure that page locks are destroyed again if they are not used anymore, such that we never use more locking resources than parallel requests.
In order to ensure this, we need to guarantee that no other process is waiting on a lock when the process currently having the lock on the lock is about to release the lock again.
This can only be achieved by using a non-blocking mode, such that a process is never put into wait state by the kernel, but only checks the availability of the lock. The access lock is our guard to be sure that no two processes are at the same time releasing/destroying a lock, whilst the other one tries to get a lock for this page lock.
The only drawback of this implementation is that we basically have to poll the availability of the page lock.
Note that the access lock resources are NEVER deleted/destroyed, otherwise the whole thing would be broken.
Table of Contents
Methods
- __construct() : mixed
- acquireLock() : bool
- Acquire a specific lock for the given scope.
- releaseLock() : void
- Release a worker specific lock.
Methods
__construct()
public
__construct(LockFactory $lockFactory) : mixed
Parameters
- $lockFactory : LockFactory
acquireLock()
Acquire a specific lock for the given scope.
public
acquireLock(string $scope, string $key) : bool
Parameters
- $scope : string
- $key : string
Tags
Return values
bool —True if we did not get the lock immediately and had to wait. This can be useful to know in the consumer since another process may have created something that we can re-use immediately.
releaseLock()
Release a worker specific lock.
public
releaseLock(string $scope) : void
Parameters
- $scope : string