From c084edfddf14bfeee0e3a1f13ca41e0805a14059 Mon Sep 17 00:00:00 2001 From: kocoten1992 Date: Sat, 12 Aug 2023 07:40:28 +0700 Subject: [PATCH] feat: add mutex helper (OS level) --- src/Mutex.php | 45 +++++++++++++++++++++++++++++++++++++++++++++ tests/MutexTest.php | 23 +++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 src/Mutex.php create mode 100644 tests/MutexTest.php diff --git a/src/Mutex.php b/src/Mutex.php new file mode 100644 index 0000000..7c6a4f2 --- /dev/null +++ b/src/Mutex.php @@ -0,0 +1,45 @@ +lock_name = $lock_name; + } + + public function lock( + float $timeout = INF /* microseconds */ + ): bool { + $timepass = 0; + + while ($timepass <= $timeout) { + $mkdir = @mkdir("/dev/shm/{$this->lock_name}"); + + if ($mkdir) { + return true; + } + + $timepass += 100000; + + usleep(100000); // check every 0.1s + } + + // throw exception here because lock was expected to success + // client api should not have to check and handle this + throw new \Exception('PU2991: unable to get lock'); + } + + public function unlock(): void + { + $rmdir = rmdir("/dev/shm/{$this->lock_name}"); + + if (! $rmdir) { + throw new \Exception('PU2992: unable unlock'); + } + } +} diff --git a/tests/MutexTest.php b/tests/MutexTest.php new file mode 100644 index 0000000..837c2d5 --- /dev/null +++ b/tests/MutexTest.php @@ -0,0 +1,23 @@ +assertFalse(file_exists('/dev/shm/'.$lock_name)); + + $mutex = new Mutex($lock_name); + $mutex->lock(0); + + $this->assertTrue(file_exists('/dev/shm/'.$lock_name)); + + $mutex->unlock(); + + $this->assertFalse(file_exists('/dev/shm/'.$lock_name)); + } +}