Test Failed
Push — main ( c76fcf...a2096a )
by Bingo
14:02
created

ArrayBlockingQueue::__construct()   B

Complexity

Conditions 7
Paths 37

Size

Total Lines 26
Code Lines 19

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 19
c 0
b 0
f 0
dl 0
loc 26
rs 8.8333
cc 7
nc 37
nop 3
1
<?php
2
3
namespace Jabe\Engine\Impl\Util\Concurrent;
4
5
class ArrayBlockingQueue extends AbstractQueue implements BlockingQueueInterface
6
{
7
    /** The queued items */
8
    public $items = [];
9
10
    /** items index for next take, poll, peek or remove */
11
    public $takeIndex = 0;
12
13
    /** items index for next put, offer, or add */
14
    public $putIndex = 0;
15
16
    /** Number of elements in the queue */
17
    public $count = 0;
18
19
    public $lock;
20
21
    /**
22
     * Circularly increment i.
23
     */
24
    public function inc(int $i): int
25
    {
26
        $i += 1;
27
        return ($i === count($this->items)) ? 0 : $i;
28
    }
29
30
    /**
31
     * Circularly decrement i.
32
     */
33
    public function dec(int $i): int
34
    {
35
        return (($i === 0) ? count($this->items) : $i) - 1;
36
    }
37
38
    /**
39
     * Returns item at index i.
40
     */
41
    public function itemAt(int $i = null)
42
    {
43
        if ($i !== null && $i >= 0 && $i < count($this->items)) {
44
            return $this->items[$i];
45
        }
46
        return null;
47
    }
48
49
    /**
50
     * Throws NullPointerException if argument is null.
51
     *
52
     * @param v the element
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Util\Concurrent\the 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...
53
     */
54
    private static function checkNotNull($v = null): void
55
    {
56
        if ($v === null) {
57
            throw new \Exception("Object is null");
58
        }
59
    }
60
61
    /**
62
     * Inserts element at current put position, advances
63
     */
64
    private function insert($x, InterruptibleProcess $process = null): void
65
    {
66
        $this->items[$this->putIndex] = $x;
67
        $this->putIndex = $this->inc($this->putIndex);
68
        $this->count += 1;
69
        if ($process !== null) {
70
            $process->push(serialize($x));
71
        }
72
    }
73
74
    public function __construct(int $capacity, bool $fair = false, $c = null)
0 ignored issues
show
Unused Code introduced by
The parameter $fair is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

74
    public function __construct(int $capacity, /** @scrutinizer ignore-unused */ bool $fair = false, $c = null)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
75
    {
76
        $this->lock = new \Swoole\Lock(SWOOLE_MUTEX);
0 ignored issues
show
Bug introduced by
The type Swoole\Lock 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...
Bug introduced by
The constant Jabe\Engine\Impl\Util\Concurrent\SWOOLE_MUTEX was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
77
        if ($capacity < 0) {
78
            throw new \Exception("Illegal capacity");
79
        }
80
        for ($i = 0; $i < $capacity; $i += 1) {
81
            $this->items[] = null;
82
        }
83
        $i = 0;
84
        $this->lock->trylock();
85
        try {
86
            if (is_array($c)) {
87
                foreach ($c as $e) {
88
                    self::checkNotNull($e);
89
                    $i += 1;
90
                    $this->items[$i] = $e;
91
                }
92
            }
93
        } catch (\Exception $ex) {
94
            throw $ex;
95
        } finally {
96
            $this->lock->unlock();
97
        }
98
        $this->count = $i;
99
        $this->putIndex = ($i === $capacity) ? 0 : $i;
100
    }
101
102
    public function offer($e, InterruptibleProcess $process = null): bool
103
    {
104
        self::checkNotNull($e);
105
        $this->lock->trylock();
106
        try {
107
            if ($this->count === count($this->items)) {
108
                return false;
109
            } else {
110
                $this->insert($e, $process);
111
                return true;
112
            }
113
        } finally {
114
            $this->lock->unlock();
115
        }
116
    }
117
118
    public function poll(int $timeout, string $unit, InterruptibleProcess $process)
119
    {
120
        $nanos = TimeUnit::toNanos($timeout, $unit);
121
        $this->lock->trylock();
122
        try {
123
            time_nanosleep(0, $nanos);
124
            return $process->pop();
125
        } finally {
126
            $this->lock->unlock();
127
        }
128
    }
129
130
    public function take(InterruptibleProcess $process)
131
    {
132
        $this->lock->trylock();
133
        try {
134
            return $process->pop();
135
        } finally {
136
            $this->lock->unlock();
137
        }
138
    }
139
140
    public function peek()
141
    {
142
        $this->lock->trylock();
143
        try {
144
            return ($this->count === 0) ? null : $this->itemAt($this->takeIndex);
145
        } finally {
146
            $this->lock->unlock();
147
        }
148
    }
149
150
    /**
151
     * Returns the number of elements in this queue.
152
     *
153
     * @return the number of elements in this queue
154
     */
155
    public function size(): int
156
    {
157
        $this->lock->trylock();
158
        try {
159
            return $this->count;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->count returns the type integer which is incompatible with the documented return type Jabe\Engine\Impl\Util\Concurrent\the.
Loading history...
160
        } finally {
161
            $this->lock->unlock();
0 ignored issues
show
Bug Best Practice introduced by
The expression ImplicitReturnNode returns the type integer which is incompatible with the documented return type Jabe\Engine\Impl\Util\Concurrent\the.
Loading history...
162
        }
163
    }
164
165
    /**
166
     * Removes a single instance of the specified element from this queue,
167
     * if it is present.
168
     *
169
     * @param o element to be removed from this queue, if present
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Util\Concurrent\element 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...
170
     * @return {@code true} if this queue changed as a result of the call
0 ignored issues
show
Documentation Bug introduced by
The doc comment {@code at position 0 could not be parsed: Unknown type name '{' at position 0 in {@code.
Loading history...
171
     */
172
    public function remove($o = null)
173
    {
174
        $this->lock->trylock();
175
        try {
176
            if ($o === null) {
177
                return false;
178
            }
179
            for ($i = $this->takeIndex, $k = $this->count; $k > 0; $i = $this->inc($i), $k -= 1) {
180
                if ($o === $this->items[$i]) {
181
                    $this->removeAt($i);
182
                    return true;
183
                }
184
            }
185
            return false;
186
        } catch (\Exception $e) {
187
            throw $e;
188
        } finally {
189
            $this->lock->unlock();
190
        }
191
    }
192
193
    private function removeAt(int $i): void
194
    {
195
        if ($i == $this->takeIndex) {
196
            $this->items[$this->takeIndex] = null;
197
            $this->takeIndex = $this->inc($this->takeIndex);
198
        } else {
199
            // slide over all others up through putIndex.
200
            for (;;) {
201
                $nexti = $this->inc($i);
202
                if ($nexti != $this->putIndex) {
203
                    $this->items[$i] = $this->items[$nexti];
204
                    $i = $nexti;
205
                } else {
206
                    $this->items[$i] = null;
207
                    $this->putIndex = $i;
208
                    break;
209
                }
210
            }
211
        }
212
        $this->count -= 1;
213
    }
214
215
    /**
216
     * Returns {@code true} if this queue contains the specified element.
217
     *
218
     * @param o object to be checked for containment in this queue
219
     * @return {@code true} if this queue contains the specified element
0 ignored issues
show
Documentation Bug introduced by
The doc comment {@code at position 0 could not be parsed: Unknown type name '{' at position 0 in {@code.
Loading history...
220
     */
221
    public function contains($o): bool
222
    {
223
        $this->lock->trylock();
224
        try {
225
            if ($o === null) {
226
                return false;
227
            }
228
            for ($i = $this->takeIndex, $k = $this->count; $k > 0; $i = $this->inc($i), $k -= 1) {
229
                if ($o === $this->items[$i]) {
230
                    return true;
231
                }
232
            }
233
            return false;
234
        } finally {
235
            $this->lock->unlock();
236
        }
237
    }
238
239
    /**
240
     * Returns an array containing all of the elements in this queue, in
241
     * proper sequence.
242
     *
243
     * @return an array containing all of the elements in this queue
0 ignored issues
show
Bug introduced by
The type Jabe\Engine\Impl\Util\Concurrent\an 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...
244
     */
245
    public function toArray(array &$c = null): array
246
    {
247
        $this->lock->trylock();
248
        try {
249
            if ($c == null) {
250
                $a = [];
251
                for ($i = $this->takeIndex, $k = 0; $k < $this->count; $i = $this->inc($i), $k += 1) {
252
                    $a[$k] = $this->items[$i];
253
                }
254
                return $a;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $a returns the type array which is incompatible with the documented return type Jabe\Engine\Impl\Util\Concurrent\an.
Loading history...
255
            } elseif (is_array($c)) {
0 ignored issues
show
introduced by
The condition is_array($c) is always true.
Loading history...
256
                for ($i = $this->takeIndex, $k = 0; $k < $this->count; $i = $this->inc($i), $k += 1) {
257
                    $c[$k] = $this->items[$i];
258
                }
259
                return $c;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $c returns the type array which is incompatible with the documented return type Jabe\Engine\Impl\Util\Concurrent\an.
Loading history...
260
            }
261
        } finally {
262
            $this->lock->unlock();
0 ignored issues
show
Bug Best Practice introduced by
In this branch, the function will implicitly return null which is incompatible with the type-hinted return array. Consider adding a return statement or allowing null as return value.

For hinted functions/methods where all return statements with the correct type are only reachable via conditions, ?null? gets implicitly returned which may be incompatible with the hinted type. Let?s take a look at an example:

interface ReturnsInt {
    public function returnsIntHinted(): int;
}

class MyClass implements ReturnsInt {
    public function returnsIntHinted(): int
    {
        if (foo()) {
            return 123;
        }
        // here: null is implicitly returned
    }
}
Loading history...
263
        }
264
    }
265
266
    /**
267
     * Atomically removes all of the elements from this queue.
268
     * The queue will be empty after this call returns.
269
     */
270
    public function clear(): void
271
    {
272
        $this->lock->trylock();
273
        try {
274
            for ($i = $this->takeIndex, $k = $this->count; $k > 0; $i = $this->inc($i), $k -= 1) {
275
                $this->items[$i] = null;
276
            }
277
            $this->count = 0;
278
            $this->putIndex = 0;
279
            $this->takeIndex = 0;
280
        } finally {
281
            $this->lock->unlock();
282
        }
283
    }
284
285
    public function drainTo(&$c, int $maxElements = null): int
286
    {
287
        self::checkNotNull($c);
288
        if ($c === $this) {
289
            throw new \Exception("Argument must be non-null");
290
        }
291
        $this->lock->trylock();
292
        try {
293
            $i = $this->takeIndex;
294
            $n = 0;
295
            $max = $maxElements ?? $this->count;
296
            while ($n < $max) {
297
                $c[] = $this->items[$i];
298
                $this->items[$i] = null;
299
                $i = $this->inc($i);
300
                $n += 1;
301
            }
302
            if ($n > 0 && $maxElements === null) {
303
                $this->count = 0;
304
                $this->putIndex = 0;
305
                $this->takeIndex = 0;
306
            } elseif ($n > 0) {
307
                $this->count -= $n;
308
                $this->takeIndex = $i;
309
            }
310
            return $n;
311
        } finally {
312
            $this->lock->unlock();
313
        }
314
    }
315
316
    public function iterator()
317
    {
318
        return new Itr($this);
319
    }
320
}
321