Skip to content

Commit

Permalink
refactor: CriticalSection divided into two objects
Browse files Browse the repository at this point in the history
  • Loading branch information
petrknap committed Nov 11, 2023
1 parent 44c8ce7 commit eaf34da
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 34 deletions.
35 changes: 2 additions & 33 deletions src/CriticalSection.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,43 +2,12 @@

namespace PetrKnap\CriticalSection;

use PetrKnap\CriticalSection\Exception\CouldNotEnterCriticalSection;
use PetrKnap\CriticalSection\Exception\CouldNotLeaveCriticalSection;
use Symfony\Component\Lock\Exception\LockAcquiringException;
use Symfony\Component\Lock\Exception\LockConflictedException;
use Symfony\Component\Lock\Exception\LockReleasingException;
use Symfony\Component\Lock\LockInterface;

final class CriticalSection implements CriticalSectionInterface
final class CriticalSection
{
protected function __construct(
private LockInterface $lock,
private bool $isLocking,
) {
}

public static function withLock(LockInterface $lock, bool $isBlocking = true): CriticalSectionInterface
{
return new self($lock, $isBlocking);
}

public function __invoke(callable $criticalSection)
{
try {
if($this->lock->acquire(blocking: $this->isLocking) === false) {
return null;
}
} catch (LockConflictedException | LockAcquiringException $acquiringException) {
throw new CouldNotEnterCriticalSection(previous: $acquiringException);
}
try {
return $criticalSection();
} finally {
try {
$this->lock->release();
} catch (LockReleasingException $releasingException) {
throw new CouldNotLeaveCriticalSection(previous: $releasingException);
}
}
return new PhpCriticalSection($lock, $isBlocking);
}
}
39 changes: 39 additions & 0 deletions src/PhpCriticalSection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php declare(strict_types=1);

namespace PetrKnap\CriticalSection;

use PetrKnap\CriticalSection\Exception\CouldNotEnterCriticalSection;
use PetrKnap\CriticalSection\Exception\CouldNotLeaveCriticalSection;
use Symfony\Component\Lock\Exception\LockAcquiringException;
use Symfony\Component\Lock\Exception\LockConflictedException;
use Symfony\Component\Lock\Exception\LockReleasingException;
use Symfony\Component\Lock\LockInterface;

final class PhpCriticalSection implements CriticalSectionInterface
{
public function __construct(
private LockInterface $lock,
private bool $isBlocking,
) {
}

public function __invoke(callable $criticalSection)
{
try {
if($this->lock->acquire(blocking: $this->isBlocking) === false) {
return null;
}
} catch (LockConflictedException | LockAcquiringException $acquiringException) {
throw new CouldNotEnterCriticalSection(previous: $acquiringException);
}
try {
return $criticalSection();
} finally {
try {
$this->lock->release();
} catch (LockReleasingException $releasingException) {
throw new CouldNotLeaveCriticalSection(previous: $releasingException);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\NoLock;

class CriticalSectionTest extends TestCase
class PhpCriticalSectionTest extends TestCase
{
public function testAcquiresLockBeforeCriticalSectionIsExecuted(): void
{
Expand Down

0 comments on commit eaf34da

Please sign in to comment.