+ // The second parameter for "sem_acquire" doesn't exist before 5.6.1
+ if (function_exists('sem_get') && version_compare(PHP_VERSION, '5.6.1', '>=')) {
+ self::$semaphore[$fn_name] = sem_get(self::semaphoreKey($fn_name));
+ if (self::$semaphore[$fn_name]) {
+ return sem_acquire(self::$semaphore[$fn_name], ($timeout == 0));
+ }
+ }
+
+ $memcache = self::connectMemcache();
+ if (is_object($memcache)) {
+ $cachekey = get_app()->get_hostname().";lock:".$fn_name;
+
+ do {
+ // We only lock to be sure that nothing happens at exactly the same time
+ dba::lock('locks');
+ $lock = $memcache->get($cachekey);
+
+ if (!is_bool($lock)) {
+ $pid = (int)$lock;
+
+ // When the process id isn't used anymore, we can safely claim the lock for us.
+ // Or we do want to lock something that was already locked by us.
+ if (!posix_kill($pid, 0) || ($pid == getmypid())) {
+ $lock = false;
+ }
+ }
+ if (is_bool($lock)) {
+ $memcache->set($cachekey, getmypid(), MEMCACHE_COMPRESSED, 300);
+ $got_lock = true;
+ }
+
+ dba::unlock();
+
+ if (!$got_lock && ($timeout > 0)) {
+ usleep(rand(10000, 200000));
+ }
+ } while (!$got_lock && ((time() - $start) < $timeout));
+
+ return $got_lock;
+ }
+