13
13
*/
14
14
class Loop
15
15
{
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
-
22
16
/** True while code execution is repeating */
23
17
private bool $ looping = false ;
24
18
@@ -65,8 +59,11 @@ public function execute(callable $code, float $timeout)
65
59
// At this time, the lock will timeout.
66
60
$ deadlineTs = microtime (true ) + $ timeout ;
67
61
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
+
68
65
$ result = null ;
69
- for ($ i = 0 ; $ this -> looping && microtime ( true ) < $ deadlineTs ; ++$ i ) { // @phpstan-ignore booleanAnd.leftAlwaysTrue
66
+ for ($ i = 0 ;; ++$ i ) {
70
67
$ result = $ code ();
71
68
if (!$ this ->looping ) { // @phpstan-ignore booleanNot.alwaysFalse
72
69
// The $code callback has called $this->end() and the lock has been acquired.
@@ -75,24 +72,28 @@ public function execute(callable $code, float $timeout)
75
72
}
76
73
77
74
// 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 ) {
82
77
break ;
83
78
}
84
79
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 ))
88
88
);
89
- $ max = min ($ min * 2 , self ::MAXIMUM_WAIT_US );
90
89
91
- $ usecToSleep = min ($ usecRemaining , random_int ((int ) $ min , (int ) $ max ));
90
+ usleep ($ sleepMicros );
91
+ }
92
92
93
- usleep ($ usecToSleep );
93
+ if (microtime (true ) >= $ deadlineTs ) {
94
+ throw LockAcquireTimeoutException::create ($ timeout );
94
95
}
95
96
96
- throw LockAcquireTimeoutException:: create ( $ timeout ) ;
97
+ return $ result ;
97
98
}
98
99
}
0 commit comments