Passed
Pull Request — master (#30)
by Alexander
08:49 queued 06:43
created

Mutex::release()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3

Importance

Changes 0
Metric Value
eloc 6
dl 0
loc 12
ccs 7
cts 7
cp 1
rs 10
c 0
b 0
f 0
cc 3
nc 3
nop 1
crap 3
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Mutex;
6
7
use RuntimeException;
8
9
use function in_array;
10
11
/**
12
 * The Mutex component allows mutual execution of concurrent processes in order to prevent "race conditions".
13
 * This is a base class, which should be extended in order to implement the actual lock mechanism.
14
 */
15
abstract class Mutex implements MutexInterface
16
{
17
    /**
18
     * @var string[] Names of the locks acquired by the current PHP process.
19
     */
20
    private array $locks = [];
21
22
    /**
23
     * Mutex constructor.
24
     *
25
     * @param bool $autoRelease Whether all locks acquired in this process (i.e. local locks) must be released
26
     * automatically before finishing script execution. Defaults to true. Setting this property
27
     * to true means that all locks acquired in this process must be released (regardless of
28
     * errors or exceptions).
29
     */
30 10
    public function __construct(bool $autoRelease = true)
31
    {
32 10
        if ($autoRelease) {
33
            $locks = &$this->locks;
34
            register_shutdown_function(function () use (&$locks) {
35
                /** @var string $lock */
36
                foreach ($locks as $lock) {
37
                    $this->release($lock);
38
                }
39
            });
40
        }
41 10
    }
42
43 7
    public function acquire(string $name, int $timeout = 0): MutexLockInterface
44
    {
45 7
        if (!in_array($name, $this->locks, true) && $this->acquireLock($name, $timeout)) {
46 7
            $this->locks[] = $name;
47
48 7
            return new MutexLock($this, $name);
49
        }
50
51 3
        throw new MutexLockedException();
52
    }
53
54
    /**
55
     * Releases acquired lock. This method will return false in case the lock was not found.
56
     *
57
     * @param string $name Name of the lock to be released. This lock must already exist.
58
     */
59 6
    public function release(string $name): void
60
    {
61 6
        if ($this->releaseLock($name)) {
62 3
            $index = array_search($name, $this->locks, true);
63 3
            if ($index !== false) {
64 3
                unset($this->locks[$index]);
65
            }
66
67 3
            return;
68
        }
69
70 3
        throw new RuntimeException();
71
    }
72
73
    /**
74
     * This method should be extended by a concrete Mutex implementations. Acquires lock by name.
75
     *
76
     * @param string $name Name of the lock to be acquired.
77
     * @param int $timeout Time (in seconds) to wait for the lock to be released.
78
     *
79
     * @return bool Acquiring result.
80
     */
81
    abstract protected function acquireLock(string $name, int $timeout = 0): bool;
82
83
    /**
84
     * This method should be extended by a concrete Mutex implementations. Releases lock by given name.
85
     *
86
     * @param string $name Name of the lock to be released.
87
     *
88
     * @return bool Release result.
89
     */
90
    abstract protected function releaseLock(string $name): bool;
91
}
92