PluginProbe
DecaLog / 4.4.0
DecaLog v4.4.0
3.0.2 3.1.0 3.10.0 3.2.0 3.3.0 3.4.0 3.4.1 3.5.0 3.5.1 3.6.0 3.6.1 3.6.2 3.6.3 3.7.0 3.7.1 3.8.0 3.9.0 3.9.1 4.0.0 4.1.0 4.2.0 4.3.0 4.3.1 4.4.0 4.5.0 All 75 releases
decalog / includes / libraries / lock / util / DoubleCheckedLocking.php

DoubleCheckedLocking.php in DecaLog 4.4.0, at includes/libraries/lock/util/DoubleCheckedLocking.php

82 lines 2.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 declare(strict_types=1);
4
5 namespace malkusch\lock\util;
6
7 use malkusch\lock\mutex\Mutex;
8
9 /**
10 * The double-checked locking pattern.
11 *
12 * You should not instantiate this class directly. Use
13 * {@link \malkusch\lock\mutex\Mutex::check()}.
14 *
15 * @author Markus Malkusch <markus@malkusch.de>
16 * @link bitcoin:1P5FAZ4QhXCuwYPnLZdk3PJsqePbu1UDDA Donations
17 * @license WTFPL
18 */
19 class DoubleCheckedLocking
20 {
21 /**
22 * @var \malkusch\lock\mutex\Mutex The mutex.
23 */
24 private $mutex;
25
26 /**
27 * @var callable The check.
28 */
29 private $check;
30
31 /**
32 * Constructs a new instance of the DoubleCheckedLocking pattern.
33 *
34 * @param \malkusch\lock\mutex\Mutex $mutex Provides methods for exclusive
35 * code execution.
36 * @param callable $check Callback that decides if the lock should be
37 * acquired and if the critical code callback should be executed after
38 * acquiring the lock.
39 */
40 public function __construct(Mutex $mutex, callable $check)
41 {
42 $this->mutex = $mutex;
43 $this->check = $check;
44 }
45
46 /**
47 * Executes a synchronized callback only after the check callback passes
48 * before and after acquiring the lock.
49 *
50 * If then returns boolean boolean false, the check did not pass before or
51 * after acquiring the lock. A boolean false can also be returned from the
52 * critical code callback to indicate that processing did not occure or has
53 * failed. It is up to the user to decide the last point.
54 *
55 * @param callable $code The critical code callback.
56 * @throws \Exception The execution callback or the check threw an
57 * exception.
58 * @throws \malkusch\lock\exception\LockAcquireException The mutex could not
59 * be acquired.
60 * @throws \malkusch\lock\exception\LockReleaseException The mutex could not
61 * be released.
62 * @throws \malkusch\lock\exception\ExecutionOutsideLockException Some code
63 * has been executed outside of the lock.
64 * @return mixed Boolean false if check did not pass or mixed for what ever
65 * the critical code callback returns.
66 */
67 public function then(callable $code)
68 {
69 if (!\call_user_func($this->check)) {
70 return false;
71 }
72
73 return $this->mutex->synchronized(function () use ($code) {
74 if (!\call_user_func($this->check)) {
75 return false;
76 }
77
78 return $code();
79 });
80 }
81 }
82