diff --git a/src/Symfony/Component/Lock/Factory.php b/src/Symfony/Component/Lock/Factory.php index c050145f90978..e92f04759508b 100644 --- a/src/Symfony/Component/Lock/Factory.php +++ b/src/Symfony/Component/Lock/Factory.php @@ -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 */ @@ -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)); + } } diff --git a/src/Symfony/Component/Lock/Lock.php b/src/Symfony/Component/Lock/Lock.php index 06ceec44e29c8..ec7bf743179ad 100644 --- a/src/Symfony/Component/Lock/Lock.php +++ b/src/Symfony/Component/Lock/Lock.php @@ -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) { diff --git a/src/Symfony/Component/Lock/ScopedLock.php b/src/Symfony/Component/Lock/ScopedLock.php new file mode 100644 index 0000000000000..8c90105f0368e --- /dev/null +++ b/src/Symfony/Component/Lock/ScopedLock.php @@ -0,0 +1,75 @@ + + * + * 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 + */ +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(); + } +} diff --git a/src/Symfony/Component/Lock/Tests/FactoryTest.php b/src/Symfony/Component/Lock/Tests/FactoryTest.php index d67949098c7a4..cd345edf8e62f 100644 --- a/src/Symfony/Component/Lock/Tests/FactoryTest.php +++ b/src/Symfony/Component/Lock/Tests/FactoryTest.php @@ -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; /** @@ -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); + } } diff --git a/src/Symfony/Component/Lock/Tests/ScopedLockTest.php b/src/Symfony/Component/Lock/Tests/ScopedLockTest.php new file mode 100644 index 0000000000000..3b4ecc3c0c5c2 --- /dev/null +++ b/src/Symfony/Component/Lock/Tests/ScopedLockTest.php @@ -0,0 +1,38 @@ + + * + * 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 + */ +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); + } +} pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy