1313 */
1414class Loop
1515{
16- /** Minimum time to wait between lock checks. In micro seconds. */
17- private const MINIMUM_WAIT_US = 10_000 ;
18-
19- /** Maximum time to wait between lock checks. In micro seconds. */
20- private const MAXIMUM_WAIT_US = 500_000 ;
21-
2216 /** True while code execution is repeating */
2317 private bool $ looping = false ;
2418
@@ -65,8 +59,11 @@ public function execute(callable $code, float $timeout)
6559 // At this time, the lock will timeout.
6660 $ deadlineTs = microtime (true ) + $ timeout ;
6761
62+ $ minWaitSecs = 0.1e-3 ; // 0.1 ms
63+ $ maxWaitSecs = max (0.05 , min (25 , $ timeout / 120 )); // 50 ms to 25 s, based on timeout
64+
6865 $ result = null ;
69- for ($ i = 0 ; $ this -> looping && microtime ( true ) < $ deadlineTs ; ++$ i ) { // @phpstan-ignore booleanAnd.leftAlwaysTrue
66+ for ($ i = 0 ;; ++$ i ) {
7067 $ result = $ code ();
7168 if (!$ this ->looping ) { // @phpstan-ignore booleanNot.alwaysFalse
7269 // The $code callback has called $this->end() and the lock has been acquired.
@@ -75,24 +72,28 @@ public function execute(callable $code, float $timeout)
7572 }
7673
7774 // Calculate max time remaining, don't sleep any longer than that.
78- $ usecRemaining = LockUtil::getInstance ()->castFloatToInt (($ deadlineTs - microtime (true )) * 1e6 );
79-
80- // We've ran out of time.
81- if ($ usecRemaining <= 0 ) {
75+ $ remainingSecs = $ deadlineTs - microtime (true );
76+ if ($ remainingSecs <= 0 ) {
8277 break ;
8378 }
8479
85- $ min = min (
86- self ::MINIMUM_WAIT_US * 1.25 ** $ i ,
87- self ::MAXIMUM_WAIT_US
80+ $ minSecs = min (
81+ $ minWaitSecs * 1.5 ** $ i ,
82+ max ($ minWaitSecs , $ maxWaitSecs / 2 )
83+ );
84+ $ maxSecs = min ($ minSecs * 2 , $ maxWaitSecs );
85+ $ sleepMicros = min (
86+ max (10 , LockUtil::getInstance ()->castFloatToInt ($ remainingSecs * 1e6 )),
87+ random_int (LockUtil::getInstance ()->castFloatToInt ($ minSecs * 1e6 ), LockUtil::getInstance ()->castFloatToInt ($ maxSecs * 1e6 ))
8888 );
89- $ max = min ($ min * 2 , self ::MAXIMUM_WAIT_US );
9089
91- $ usecToSleep = min ($ usecRemaining , random_int ((int ) $ min , (int ) $ max ));
90+ usleep ($ sleepMicros );
91+ }
9292
93- usleep ($ usecToSleep );
93+ if (microtime (true ) >= $ deadlineTs ) {
94+ throw LockAcquireTimeoutException::create ($ timeout );
9495 }
9596
96- throw LockAcquireTimeoutException:: create ( $ timeout ) ;
97+ return $ result ;
9798 }
9899}
0 commit comments