Skip to content

Commit

Permalink
Merge pull request #10 from petrknap/critical-section-args
Browse files Browse the repository at this point in the history
Added support for critical sections with arguments
  • Loading branch information
petrknap authored Jun 22, 2024
2 parents 99e1f11 + a8160a1 commit a3db429
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 9 deletions.
9 changes: 5 additions & 4 deletions src/CriticalSectionInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@
use Throwable;

/**
* @template T
* @template T of mixed
*/
interface CriticalSectionInterface
{
/**
* @param callable(): T $criticalSection
* @param (callable(mixed...): T)|callable $criticalSection
* @param mixed ...$args will be forwarded to {@link $criticalSection}
*
* @return ?T returned by {@link $criticalSection} or null when it is occupied (non-blocking mode only)
* @return T|null returned by {@link $criticalSection} or null when it is occupied (non-blocking mode only)
*
* @throws CouldNotEnterCriticalSection
* @throws CouldNotLeaveCriticalSection
* @throws Throwable from {@link $criticalSection}
*/
public function __invoke(callable $criticalSection);
public function __invoke(callable $criticalSection, mixed ...$args);
}
7 changes: 3 additions & 4 deletions src/WrappingCriticalSection.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,16 @@ protected function __construct(
) {
}

/** @inheritDoc */
public function __invoke(callable $criticalSection)
public function __invoke(callable $criticalSection, mixed ...$args)
{
if ($this->enter() === false) {
return null;
}
try {
if ($this->wrappedCriticalSection) {
return ($this->wrappedCriticalSection)(static fn () => $criticalSection());
return ($this->wrappedCriticalSection)(static fn () => $criticalSection(...$args));
}
return $criticalSection();
return $criticalSection(...$args);
} finally {
$this->leave();
}
Expand Down
19 changes: 18 additions & 1 deletion tests/WrappingCriticalSectionTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,28 @@ final class WrappingCriticalSectionTest extends TestCase
{
private const FOO = 'bar';

public function testForwardsArgumentsIntoCriticalSection(): void
{
$expectedArgs = ['string', 1, null];
$receivedArgs = [];
(new NonCriticalSection(canEnter: true))(
function (string $s, int $i, mixed $n) use (&$receivedArgs): void {
$receivedArgs = func_get_args();
},
...$expectedArgs,
);

self::assertEquals(
$expectedArgs,
$receivedArgs,
);
}

public function testReturnsValueReturnedByExecutedCriticalSection(): void
{
self::assertSame(
self::FOO,
(new NonCriticalSection(canEnter: true))(fn () => self::FOO)
(new NonCriticalSection(canEnter: true))(fn () => self::FOO),
);
}

Expand Down

0 comments on commit a3db429

Please sign in to comment.