Skip to content

[Lock] Scoped Lock #22115

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 14 additions & 1 deletion src/Symfony/Component/Lock/Factory.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public function __construct(StoreInterface $store)
* Creates a lock for the given resource.
*
* @param string $resource The resource to lock
* @param float $ttl maximum expected lock duration
* @param float $ttl Maximum expected lock duration in seconds
*
* @return Lock
*/
Expand All @@ -48,4 +48,17 @@ public function createLock($resource, $ttl = 300.0)

return $lock;
}

/**
* Create a scoped lock for the given resource.
*
* @param string $resource The resource to lock
* @param float $ttl Maximum expected lock duration in seconds
*
* @return ScopedLock
*/
public function createScopedLock($resource, $ttl = 300.0)
{
return new ScopedLock($this->createLock($resource, $ttl));
}
}
6 changes: 3 additions & 3 deletions src/Symfony/Component/Lock/Lock.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ final class Lock implements LockInterface, LoggerAwareInterface
private $ttl;

/**
* @param Key $key
* @param StoreInterface $store
* @param float|null $ttl
* @param Key $key Resource to lock
* @param StoreInterface $store Store used to handle lock persistence
* @param float|null $ttl Maximum expected lock duration in seconds
*/
public function __construct(Key $key, StoreInterface $store, $ttl = null)
{
Expand Down
75 changes: 75 additions & 0 deletions src/Symfony/Component/Lock/ScopedLock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Lock;

/**
* ScopedLock encapsulates a LockInterface which is automatically released when destructed.
*
* @author Fabien Bourigault <bourigaultfabien@gmail.com>
*/
final class ScopedLock implements LockInterface
{
/**
* @var LockInterface
*/
private $lock;

/**
* @param LockInterface $lock
*/
public function __construct(LockInterface $lock)
{
$this->lock = $lock;
}

/**
* Automatically release the underlying lock when the object is destructed.
*/
public function __destruct()
{
if ($this->isAcquired()) {
$this->release();
}
}

/**
* {@inheritdoc}
*/
public function acquire($blocking = false)
{
return $this->lock->acquire($blocking);
}

/**
* {@inheritdoc}
*/
public function refresh()
{
$this->lock->refresh();
}

/**
* {@inheritdoc}
*/
public function isAcquired()
{
return $this->lock->isAcquired();
}

/**
* {@inheritdoc}
*/
public function release()
{
$this->lock->release();
}
}
13 changes: 13 additions & 0 deletions src/Symfony/Component/Lock/Tests/FactoryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Psr\Log\LoggerInterface;
use Symfony\Component\Lock\Factory;
use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\ScopedLock;
use Symfony\Component\Lock\StoreInterface;

/**
Expand All @@ -33,4 +34,16 @@ public function testCreateLock()

$this->assertInstanceOf(LockInterface::class, $lock);
}

public function testCreateScopedLock()
{
$store = $this->getMockBuilder(StoreInterface::class)->getMock();
$logger = $this->getMockBuilder(LoggerInterface::class)->getMock();
$factory = new Factory($store);
$factory->setLogger($logger);

$lock = $factory->createScopedLock('foo');

$this->assertInstanceOf(ScopedLock::class, $lock);
}
}
38 changes: 38 additions & 0 deletions src/Symfony/Component/Lock/Tests/ScopedLockTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\Lock\Tests;

use PHPUnit\Framework\TestCase;
use Symfony\Component\Lock\LockInterface;
use Symfony\Component\Lock\ScopedLock;

/**
* @author Fabien Bourigault <bourigaultfabien@gmail.com>
*/
class ScopedLockTest extends TestCase
{
public function testReleaseWhenLeavingScope()
{
$lock = $this->getMockBuilder(LockInterface::class)->getMock();

$lock
->method('isAcquired')
->willReturn(true)
;
$lock
->expects($this->once())
->method('release')
;

new ScopedLock($lock);
}
}