Completed
Push — master ( e42de6...8350e2 )
by Hu
02:44
created

Semaphore   A

Complexity

Total Complexity 18

Size/Duplication

Total Lines 128
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 0

Test Coverage

Coverage 78.05%

Importance

Changes 2
Bugs 0 Features 2
Metric Value
wmc 18
c 2
b 0
f 2
lcom 1
cbo 0
dl 0
loc 128
ccs 32
cts 41
cp 0.7805
rs 10

7 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 6 2
A create() 0 4 1
A __destruct() 0 6 2
A release() 0 13 3
A isLocked() 0 4 2
A _stringToSemKey() 0 9 2
B acquire() 0 25 6
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;
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
     * @param $count
45
     * @throws \RuntimeException
46
     */
47 9
    private function __construct($key, $count = 1)
48
    {
49 9
        if (($this->lock_id = sem_get($this->_stringToSemKey($key), $count)) === false) {
50
            throw new \RuntimeException('Cannot create semaphore for key: ' . $key);
51
        }
52 9
    }
53
54
    /**
55
     * release lock
56
     *
57
     * @throws \RuntimeException
58
     */
59 9
    public function __destruct()
60
    {
61 9
        if ($this->isLocked()) {
62 3
            $this->release();
63 3
        }
64 9
    }
65
66
67
    /**
68
     * get a lock
69
     *
70
     * @param bool $blocking
71
     * @return bool
72
     */
73 6
    public function acquire($blocking = true)
74
    {
75 6
        if ($this->locked) {
76 3
            throw new \RuntimeException("already lock by yourself");
77
        }
78
79 6
        if ($blocking === false) {
80
            if (version_compare(PHP_VERSION, '5.6.0') < 0) {
81
                throw new \RuntimeException("php version is at least 5.6.0 for param blocking");
82
            }
83
            if (!sem_acquire($this->lock_id, true)) {
84
                return false;
85
            }
86
            $this->locked = true;
87
88
            return true;
89
        }
90
91 6
        if (!sem_acquire($this->lock_id)) {
92
            return false;
93
        }
94 6
        $this->locked = true;
95
96 6
        return true;
97
    }
98
99
    /**
100
     * release lock
101
     *
102
     * @return bool
103
     * @throws \RuntimeException
104
     */
105 9
    public function release()
106
    {
107 9
        if (!$this->locked) {
108 3
            throw new \RuntimeException("release a non lock");
109
        }
110
111 6
        if (!sem_release($this->lock_id)) {
112
            return false;
113
        }
114 6
        $this->locked = false;
115
116 6
        return true;
117
    }
118
119
    /**
120
     * is locked
121
     *
122
     * @return bool
123
     */
124 9
    public function isLocked()
125
    {
126 9
        return $this->locked === true ? true : false;
127
    }
128
129
    /**
130
     * Semaphore requires a numeric value as the key
131
     *
132
     * @param $identifier
133
     * @return int
134
     */
135 9
    protected function _stringToSemKey($identifier)
136
    {
137 9
        $md5 = md5($identifier);
138 9
        $key = 0;
139 9
        for ($i = 0; $i < 32; $i++) {
140 9
            $key += ord($md5{$i}) * $i;
141 9
        }
142 9
        return $key;
143
    }
144
}