PriorityQueue::insert()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 6
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 2
1
<?php
2
3
/**
4
 * Phoole (PHP7.2+)
5
 *
6
 * @category  Library
7
 * @package   Phoole\Base
8
 * @copyright Copyright (c) 2019 Hong Zhang
9
 */
10
declare(strict_types=1);
11
12
namespace Phoole\Base\Queue;
13
14
/**
15
 * PriorityQueue
16
 *
17
 * @package Phoole\Base
18
 */
19
class PriorityQueue implements \IteratorAggregate, \Countable
20
{
21
    /**
22
     * data storage
23
     *
24
     * @var  array
25
     */
26
    protected $queue = [];
27
28
    /**
29
     * marker for sorted or not
30
     *
31
     * @var  bool
32
     */
33
    protected $sorted = TRUE;
34
35
    /**
36
     * counter for priority
37
     *
38
     * @var  int
39
     */
40
    protected $counter = 20000000;
41
42
    /**
43
     * Insert data into the queue with priority
44
     *
45
     * @param  mixed $data
46
     * @param  int   $priority  priority, higher number retrieved first(-1000 - 1000)
47
     * @return void
48
     * @throws \RuntimeException if priority out of range
49
     */
50
    public function insert($data, int $priority = 0): void
51
    {
52
        $i = $this->getIndex($priority);
53
        $this->queue[$i] = ['data' => $data, 'priority' => $priority];
54
        $this->sorted = FALSE;
55
    }
56
57
    /**
58
     * Combine with queue and return a combined new queue
59
     *
60
     * @param  PriorityQueueInterface $queue
61
     * @return PriorityQueueInterface
62
     */
63
    public function combine(PriorityQueue $queue): PriorityQueue
64
    {
65
        $nqueue = clone $this;
66
        foreach ($queue->queue as $data) {
67
            $nqueue->insert($data['data'], $data['priority']);
68
        }
69
        return $nqueue;
70
    }
71
72
    /**
73
     * {@inheritDoc}
74
     */
75
    public function count()
76
    {
77
        return count($this->queue);
78
    }
79
80
    /**
81
     * {@inheritDoc}
82
     */
83
    public function getIterator()
84
    {
85
        $this->sortQueue();
86
        return new \ArrayIterator(array_column($this->queue, 'data'));
87
    }
88
89
    /**
90
     * Generate an integer key
91
     *
92
     * @param  int $priority
93
     * @return int
94
     * @throws \RuntimeException  priority out of range
95
     */
96
    protected function getIndex(int $priority): int
97
    {
98
        if (abs($priority) > 1000) {
99
            throw new \RuntimeException("Priority $priority out of range.");
100
        }
101
        return --$this->counter + $priority * 10000;
102
    }
103
104
    /**
105
     * Sort the queue from higher to lower int $key
106
     *
107
     * @return $this
108
     */
109
    protected function sortQueue()
110
    {
111
        if (!$this->sorted) {
112
            krsort($this->queue);
113
            $this->sorted = TRUE;
114
        }
115
        return $this;
116
    }
117
}