fiberManager = new FiberManager($clock, $timer); $this->mutex = new AsyncMutex('test-mutex'); }); it('acquires and releases lock', function () { expect($this->mutex->isLocked())->toBeFalse(); // Run in fiber context $this->fiberManager->async(function () { $this->mutex->acquire(); expect($this->mutex->isLocked())->toBeTrue(); $this->mutex->release(); expect($this->mutex->isLocked())->toBeFalse(); }); }); it('tries to acquire lock non-blocking', function () { $this->fiberManager->async(function () { $acquired = $this->mutex->tryAcquire(); expect($acquired)->toBeTrue(); expect($this->mutex->isLocked())->toBeTrue(); // Try again while locked $acquiredAgain = $this->mutex->tryAcquire(); expect($acquiredAgain)->toBeFalse(); $this->mutex->release(); }); }); it('executes synchronized operation', function () { $result = $this->fiberManager->async(function () { return $this->mutex->synchronized(function () { return 'synchronized-result'; }); }); expect($result->getReturn())->toBe('synchronized-result'); expect($this->mutex->isLocked())->toBeFalse(); // Should be released after }); it('releases lock even if exception occurs', function () { $this->fiberManager->async(function () { try { $this->mutex->synchronized(function () { throw new \RuntimeException('error in synchronized block'); }); } catch (\RuntimeException $e) { // Expected } expect($this->mutex->isLocked())->toBeFalse(); // Should still be released }); }); it('provides mutex statistics', function () { $stats = $this->mutex->getStats(); expect($stats)->toHaveKey('name'); expect($stats)->toHaveKey('locked'); expect($stats)->toHaveKey('owner'); expect($stats)->toHaveKey('waiting_fibers'); expect($stats['name'])->toBe('test-mutex'); expect($stats['locked'])->toBeFalse(); }); it('prevents multiple acquisitions', function () { $this->fiberManager->async(function () { $this->mutex->acquire(); $stats = $this->mutex->getStats(); expect($stats['locked'])->toBeTrue(); expect($stats['owner'])->not->toBeNull(); $this->mutex->release(); }); }); it('tracks waiting fibers', function () { $this->fiberManager->async(function () { $this->mutex->acquire(); $stats = $this->mutex->getStats(); expect($stats['waiting_fibers'])->toBe(0); // None waiting yet $this->mutex->release(); }); }); });