‪TYPO3CMS  ‪main
ResourceMutex.php
Go to the documentation of this file.
1 <?php
2 
3 /*
4  * This file is part of the TYPO3 CMS project.
5  *
6  * It is free software; you can redistribute it and/or modify it under
7  * the terms of the GNU General Public License, either version 2
8  * of the License, or any later version.
9  *
10  * For the full copyright and license information, please read the
11  * LICENSE.txt file that was distributed with this source code.
12  *
13  * The TYPO3 project - inspiring people to share!
14  */
15 
17 
18 use Symfony\Component\DependencyInjection\Attribute\Autoconfigure;
22 
54 #[Autoconfigure(public: true)]
56 {
60  private array ‪$accessLocks = [];
61 
65  private array ‪$workerLocks = [];
66 
67  public function ‪__construct(private readonly ‪LockFactory $lockFactory) {}
68 
78  public function ‪acquireLock(string $scope, string $key): bool
79  {
80  $this->accessLocks[$scope] = $this->lockFactory->createLocker($scope);
81  $this->workerLocks[$scope] = $this->lockFactory->createLocker(
82  $key,
84  );
85  $hadToWaitForLock = false;
86  do {
87  if (!$this->accessLocks[$scope]->acquire()) {
88  throw new \RuntimeException('Could not acquire access lock for "' . $scope . '".', 1601923209);
89  }
90  try {
91  $locked = $this->workerLocks[$scope]->acquire(
93  );
95  // Somebody else has the lock, we keep waiting.
96  // First release the access lock, it will be acquired in next iteration again.
97  $this->accessLocks[$scope]->release();
98  // Mark "We had to wait".
99  $hadToWaitForLock = true;
100  // Now lets make a short break (20ms) until we try again, since
101  // the page generation by the lock owner will take a while.
102  usleep(20000);
103  continue;
104  }
105  $this->accessLocks[$scope]->release();
106  if ($locked) {
107  break;
108  }
109  throw new \RuntimeException('Could not acquire process lock for "' . $scope . '" with key "' . $key . '".', 1601923215);
110  } while (true);
111  return $hadToWaitForLock;
112  }
113 
120  public function ‪releaseLock(string $scope): void
121  {
122  if ($this->accessLocks[$scope] ?? null) {
123  if (!$this->accessLocks[$scope]->acquire()) {
124  throw new \RuntimeException('Could not acquire access lock for "' . $scope . '".', 1601923319);
125  }
126  $this->workerLocks[$scope]->release();
127  $this->workerLocks[$scope]->destroy();
128  $this->workerLocks[$scope] = null;
129  $this->accessLocks[$scope]->release();
130  $this->accessLocks[$scope] = null;
131  }
132  }
133 }
‪TYPO3\CMS\Core\Locking\ResourceMutex
Definition: ResourceMutex.php:56
‪TYPO3\CMS\Core\Locking\LockingStrategyInterface\LOCK_CAPABILITY_NOBLOCK
‪const LOCK_CAPABILITY_NOBLOCK
Definition: LockingStrategyInterface.php:40
‪TYPO3\CMS\Core\Locking
‪TYPO3\CMS\Core\Locking\LockingStrategyInterface\LOCK_CAPABILITY_EXCLUSIVE
‪const LOCK_CAPABILITY_EXCLUSIVE
Definition: LockingStrategyInterface.php:30
‪TYPO3\CMS\Core\Locking\Exception\LockAcquireWouldBlockException
Definition: LockAcquireWouldBlockException.php:21
‪TYPO3\CMS\Core\Locking\ResourceMutex\$workerLocks
‪array $workerLocks
Definition: ResourceMutex.php:65
‪TYPO3\CMS\Core\Locking\Exception\LockAcquireException
Definition: LockAcquireException.php:23
‪TYPO3\CMS\Core\Locking\Exception\LockCreateException
Definition: LockCreateException.php:23
‪TYPO3\CMS\Core\Locking\ResourceMutex\acquireLock
‪bool acquireLock(string $scope, string $key)
Definition: ResourceMutex.php:78
‪TYPO3\CMS\Core\Locking\ResourceMutex\releaseLock
‪releaseLock(string $scope)
Definition: ResourceMutex.php:120
‪TYPO3\CMS\Core\Locking\ResourceMutex\$accessLocks
‪array $accessLocks
Definition: ResourceMutex.php:60
‪TYPO3\CMS\Core\Locking\LockFactory
Definition: LockFactory.php:27
‪TYPO3\CMS\Core\Locking\ResourceMutex\__construct
‪__construct(private readonly LockFactory $lockFactory)
Definition: ResourceMutex.php:67