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 / mutex / CASMutex.php

CASMutex.php in DecaLog 4.4.0, at includes/libraries/lock/mutex/CASMutex.php

86 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\mutex;
6
7 use malkusch\lock\exception\TimeoutException;
8 use malkusch\lock\util\Loop;
9
10 /**
11 * CAS based mutex implementation.
12 *
13 * This mutex doesn't lock at all. It implements the compare-and-swap
14 * approach. I.e. it will repeat executing the code block until it wasn't
15 * modified in between. Use this only when you know that concurrency is
16 * a rare event.
17 *
18 * @author Markus Malkusch <[email protected]>
19 * @link bitcoin:1P5FAZ4QhXCuwYPnLZdk3PJsqePbu1UDDA Donations
20 * @license WTFPL
21 */
22 class CASMutex extends Mutex
23 {
24 /**
25 * @var Loop The loop.
26 */
27 private $loop;
28
29 /**
30 * Sets the timeout.
31 *
32 * The default is 3 seconds.
33 *
34 * @param int $timeout The timeout in seconds.
35 * @throws \LengthException The timeout must be greater than 0.
36 */
37 public function __construct(int $timeout = 3)
38 {
39 $this->loop = new Loop($timeout);
40 }
41
42 /**
43 * Notifies the Mutex about a successful CAS operation.
44 */
45 public function notify(): void
46 {
47 $this->loop->end();
48 }
49
50 /**
51 * Repeats executing a code until a compare-and-swap operation was successful.
52 *
53 * The code has to be designed in a way that it can be repeated without any
54 * side effects. When the CAS operation was successful it should notify
55 * this mutex by calling {@link CASMutex::notify()}. I.e. the only side effects
56 * of the code may happen after a successful CAS operation. The CAS
57 * operation itself is a valid side effect as well.
58 *
59 * If the code throws an exception it will stop repeating the execution.
60 *
61 * Example:
62 * <code>
63 * $mutex = new CASMutex();
64 * $mutex->synchronized(function () use ($memcached, $mutex, $amount) {
65 * $balance = $memcached->get("balance", null, $casToken);
66 * $balance -= $amount;
67 * if (!$memcached->cas($casToken, "balance", $balance)) {
68 * return;
69 *
70 * }
71 * $mutex->notify();
72 * });
73 * </code>
74 *
75 * @param callable $code The synchronized execution block.
76 * @throws \Exception The execution block threw an exception.
77 * @throws TimeoutException The timeout was reached.
78 * @return mixed The return value of the execution block.
79 *
80 */
81 public function synchronized(callable $code)
82 {
83 return $this->loop->execute($code);
84 }
85 }
86