27
27
final class LockRegistry
28
28
{
29
29
private static $ openedFiles = [];
30
- private static $ lockedFiles ;
30
+ private static $ lockedKeys ;
31
31
32
32
/**
33
33
* The number of items in this list controls the max number of concurrent processes.
@@ -75,32 +75,40 @@ public static function setFiles(array $files): array
75
75
fclose ($ file );
76
76
}
77
77
}
78
- self ::$ openedFiles = self ::$ lockedFiles = [];
78
+ self ::$ openedFiles = self ::$ lockedKeys = [];
79
79
80
80
return $ previousFiles ;
81
81
}
82
82
83
83
public static function compute (callable $ callback , ItemInterface $ item , bool &$ save , CacheInterface $ pool , \Closure $ setMetadata = null , LoggerInterface $ logger = null )
84
84
{
85
- if ('\\' === \DIRECTORY_SEPARATOR && null === self ::$ lockedFiles ) {
85
+ if ('\\' === \DIRECTORY_SEPARATOR && null === self ::$ lockedKeys ) {
86
86
// disable locking on Windows by default
87
- self ::$ files = self ::$ lockedFiles = [];
87
+ self ::$ files = self ::$ lockedKeys = [];
88
88
}
89
89
90
- $ key = self :: $ files ? abs ( crc32 ( $ item ->getKey ())) % \count ( self :: $ files ) : - 1 ;
90
+ $ key = unpack ( ' i ' , md5 ( $ item ->getKey (), true ))[ 1 ] ;
91
91
92
- if ($ key < 0 || (self ::$ lockedFiles [$ key ] ?? false ) || !$ lock = self ::open ($ key )) {
92
+ if (!\function_exists ('sem_get ' )) {
93
+ $ key = self ::$ files ? abs ($ key ) % \count (self ::$ files ) : null ;
94
+ }
95
+
96
+ if (null === $ key || (self ::$ lockedKeys [$ key ] ?? false ) || !$ lock = self ::open ($ key )) {
93
97
return $ callback ($ item , $ save );
94
98
}
95
99
96
100
while (true ) {
97
101
try {
98
102
// race to get the lock in non-blocking mode
99
- $ locked = flock ($ lock , \LOCK_EX | \LOCK_NB , $ wouldBlock );
103
+ if ($ wouldBlock = \function_exists ('sem_get ' )) {
104
+ $ locked = @sem_acquire ($ lock , true );
105
+ } else {
106
+ $ locked = flock ($ lock , \LOCK_EX | \LOCK_NB , $ wouldBlock );
107
+ }
100
108
101
109
if ($ locked || !$ wouldBlock ) {
102
110
$ logger && $ logger ->info (sprintf ('Lock %s, now computing item "{key}" ' , $ locked ? 'acquired ' : 'not supported ' ), ['key ' => $ item ->getKey ()]);
103
- self ::$ lockedFiles [$ key ] = true ;
111
+ self ::$ lockedKeys [$ key ] = true ;
104
112
105
113
$ value = $ callback ($ item , $ save );
106
114
@@ -115,12 +123,23 @@ public static function compute(callable $callback, ItemInterface $item, bool &$s
115
123
116
124
return $ value ;
117
125
}
126
+
118
127
// if we failed the race, retry locking in blocking mode to wait for the winner
119
128
$ logger && $ logger ->info ('Item "{key}" is locked, waiting for it to be released ' , ['key ' => $ item ->getKey ()]);
120
- flock ($ lock , \LOCK_SH );
129
+
130
+ if (\function_exists ('sem_get ' )) {
131
+ $ lock = sem_get ($ key );
132
+ @sem_acquire ($ lock );
133
+ } else {
134
+ flock ($ lock , \LOCK_SH );
135
+ }
121
136
} finally {
122
- flock ($ lock , \LOCK_UN );
123
- unset(self ::$ lockedFiles [$ key ]);
137
+ if (\function_exists ('sem_get ' )) {
138
+ sem_remove ($ lock );
139
+ } else {
140
+ flock ($ lock , \LOCK_UN );
141
+ }
142
+ unset(self ::$ lockedKeys [$ key ]);
124
143
}
125
144
static $ signalingException , $ signalingCallback ;
126
145
$ signalingException = $ signalingException ?? unserialize ("O:9: \"Exception \":1:{s:16: \"\0Exception \0trace \";a:0:{}} " );
@@ -145,6 +164,10 @@ public static function compute(callable $callback, ItemInterface $item, bool &$s
145
164
146
165
private static function open (int $ key )
147
166
{
167
+ if (\function_exists ('sem_get ' )) {
168
+ return sem_get ($ key );
169
+ }
170
+
148
171
if (null !== $ h = self ::$ openedFiles [$ key ] ?? null ) {
149
172
return $ h ;
150
173
}
0 commit comments