Passed
Push — dev ( 1ff3e9...219c54 )
by Janko
07:35
created

SemaphoreUtil::isSemaphoreAlreadyAcquired()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Stu\Module\Control;
4
5
use Override;
0 ignored issues
show
Bug introduced by
The type Override was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Stu\Component\Game\SemaphoreConstants;
0 ignored issues
show
Bug introduced by
The type Stu\Component\Game\SemaphoreConstants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Stu\Exception\SemaphoreException;
8
use Stu\Module\Config\StuConfigInterface;
9
use Stu\Module\Logging\LogLevelEnum;
10
use Stu\Module\Logging\LoggerUtilFactoryInterface;
11
use Stu\Module\Logging\LoggerUtilInterface;
12
use SysvSemaphore;
13
14
final class SemaphoreUtil implements SemaphoreUtilInterface
15
{
16
    /** @var array<int, SysvSemaphore> */
17
    public static array $semaphores = [];
18
19
    private LoggerUtilInterface $loggerUtil;
20
21 1
    public function __construct(
22
        private readonly StuConfigInterface $stuConfig,
23
        LoggerUtilFactoryInterface $loggerUtilFactory
24
    ) {
25 1
        $this->loggerUtil = $loggerUtilFactory->getLoggerUtil();
26
    }
27
28 38
    #[Override]
29
    public function isSemaphoreAlreadyAcquired(int $key): bool
30
    {
31 38
        return array_key_exists($key, self::$semaphores);
32
    }
33
34 39
    #[Override]
35
    public function acquireSemaphore(int $key): null|int|SysvSemaphore
36
    {
37 39
        if (!$this->isSemaphoreUsageActive()) {
38 39
            return null;
39
        }
40
41
        $semaphore = $this->getSemaphore($key);
42
43
        if ($this->isSemaphoreAlreadyAcquired($key)) {
44
            return null;
45
        }
46
47
        $this->acquire($semaphore);
48
        self::$semaphores[$key] = $semaphore;
49
50
        return $semaphore;
51
    }
52
53
    private function getSemaphore(int $key): SysvSemaphore
54
    {
55
        $semaphore = sem_get(
56
            $key,
57
            1,
58
            0o666,
59
            SemaphoreConstants::AUTO_RELEASE_SEMAPHORES
60
        );
61
62
        if ($semaphore === false) {
63
            throw new SemaphoreException('Error getting semaphore');
64
        }
65
66
        return $semaphore;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $semaphore could return the type resource which is incompatible with the type-hinted return SysvSemaphore. Consider adding an additional type-check to rule them out.
Loading history...
67
    }
68
69
    private function acquire(SysvSemaphore $semaphore): void
70
    {
71
        if (!sem_acquire($semaphore)) {
72
            throw new SemaphoreException("Error acquiring Semaphore!");
73
        }
74
    }
75
76 39
    #[Override]
77
    public function releaseSemaphore(null|int|SysvSemaphore $semaphore, bool $doRemove = false): void
78
    {
79 39
        if (!$this->isSemaphoreUsageActive() || !$semaphore instanceof SysvSemaphore) {
80 39
            return;
81
        }
82
83
        $this->release($semaphore, $doRemove);
84
    }
85
86
    private function release(SysvSemaphore $semaphore, bool $doRemove): void
87
    {
88
        if (!sem_release($semaphore)) {
89
            $this->loggerUtil->init('semaphores', LogLevelEnum::ERROR);
90
            $this->loggerUtil->log("Error releasing Semaphore!");
91
            return;
92
            //throw new SemaphoreException("Error releasing Semaphore!");
93
        }
94
95
        if ($doRemove && !sem_remove($semaphore)) {
96
            $this->loggerUtil->init('semaphores', LogLevelEnum::ERROR);
97
            $this->loggerUtil->log("Error removing Semaphore!");
98
            //throw new SemaphoreException("Error removing Semaphore!");
99
        }
100
    }
101
102 39
    private function isSemaphoreUsageActive(): bool
103
    {
104 39
        return $this->stuConfig->getGameSettings()->useSemaphores();
105
    }
106
107 7
    public static function reset(): void
108
    {
109 7
        self::$semaphores = [];
110
    }
111
}
112