Completed
Push — master ( 496db6...15a9d5 )
by Hu
27:36 queued 24:40
created

Semaphore::acquire()   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 25
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 12
CRAP Score 6.1051

Importance

Changes 3
Bugs 0 Features 1
Metric Value
c 3
b 0
f 1
dl 0
loc 25
ccs 12
cts 14
cp 0.8571
rs 8.439
cc 6
eloc 14
nc 6
nop 1
crap 6.1051
1
<?php
2
/**
3
 * Created by PhpStorm.
4
 * User: Jenner
5
 * Date: 2015/8/12
6
 * Time: 20:52
7
 */
8
9
namespace Jenner\SimpleFork\Lock;
1 ignored issue
show
Coding Style introduced by
There must be one blank line after the namespace declaration
Loading history...
10
11
12
class Semaphore implements LockInterface
13
{
14
    /**
15
     * create a lock instance
16
     *
17
     * @param $key
18
     * @return Semaphore
19
     */
20 10
    public static function create($key)
21
    {
22 10
        return new Semaphore($key);
23
    }
24
25
    /**
26
     * @var
27
     */
28
    private $lock_id;
29
30
    /**
31
     * @var bool
32
     */
33
    private $locked = false;
34
35
    /**
36
     * init a lock
37
     *
38
     * @param $key
39
     * @throws \RuntimeException
40
     */
41 10
    private function __construct($key)
42
    {
43 10
        if (($this->lock_id = sem_get($this->_stringToSemKey($key))) === false) {
44
            throw new \RuntimeException('Cannot create semaphore for key: ' . $key);
45
        }
46 10
    }
47
48
    /**
49
     * release lock
50
     *
51
     * @throws \RuntimeException
52
     */
53 10
    public function __destruct()
54
    {
55 10
        if ($this->isLocked()) {
56 3
            $this->release();
57 3
        }
58 10
    }
59
60
61
    /**
62
     * get a lock
63
     *
64
     * @param bool $blocking
65
     * @return bool
66
     */
67 7
    public function acquire($blocking = true)
68
    {
69 7
        if ($this->locked) {
70 3
            throw new \RuntimeException("already lock by yourself");
71
        }
72
73 7
        if ($blocking === false) {
74 1
            if (version_compare(PHP_VERSION, '5.6.0') < 0) {
75
                throw new \RuntimeException("php version is at least 5.6.0 for param blocking");
76
            }
77 1
            if (!sem_acquire($this->lock_id, true)) {
78 1
                return false;
79
            }
80 1
            $this->locked = true;
81
82 1
            return true;
83
        }
84
85 6
        if (!sem_acquire($this->lock_id)) {
86
            return false;
87
        }
88 6
        $this->locked = true;
89
90 6
        return true;
91
    }
92
93
    /**
94
     * release lock
95
     *
96
     * @return bool
97
     * @throws \RuntimeException
98
     */
99 10
    public function release()
100
    {
101 10
        if (!$this->locked) {
102 3
            throw new \RuntimeException("release a non lock");
103
        }
104
105 7
        if (!sem_release($this->lock_id)) {
106
            return false;
107
        }
108 7
        $this->locked = false;
109
110 7
        return true;
111
    }
112
113
    /**
114
     * is locked
115
     *
116
     * @return bool
117
     */
118 10
    public function isLocked()
119
    {
120 10
        return $this->locked === true ? true : false;
121
    }
122
123
    /**
124
     * Semaphore requires a numeric value as the key
125
     *
126
     * @param $identifier
127
     * @return int
128
     */
129 10
    protected function _stringToSemKey($identifier)
1 ignored issue
show
Coding Style introduced by
Method name "_stringToSemKey" should not be prefixed with an underscore to indicate visibility
Loading history...
130
    {
131 10
        $md5 = md5($identifier);
132 10
        $key = 0;
133 10
        for ($i = 0; $i < 32; $i++) {
134 10
            $key += ord($md5{$i}) * $i;
135 10
        }
136 10
        return $key;
137
    }
138
}