Completed
Push — master ( d688a6...950060 )
by Hu
02:29
created

Semaphore::isLocked()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 2

Importance

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