Skip to content

Commit

Permalink
feat: add mutex helper (OS level)
Browse files Browse the repository at this point in the history
  • Loading branch information
kocoten1992 committed Aug 12, 2023
1 parent 850da66 commit c084edf
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 0 deletions.
45 changes: 45 additions & 0 deletions src/Mutex.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace Talmp\Phputils;

# This is an mutex implementation at OS level
class Mutex
{
public readonly string $lock_name;

public function __construct(string $lock_name)
{
$this->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');
}
}
}
23 changes: 23 additions & 0 deletions tests/MutexTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<?php

use PHPUnit\Framework\TestCase;
use Talmp\Phputils\Mutex;

class MutexTest extends TestCase
{
public function test_lock_unlock(): void
{
$lock_name = bin2hex(random_bytes(16));

$this->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));
}
}

0 comments on commit c084edf

Please sign in to comment.