Completed
Push — pr32 ( 620873...63c524 )
by Kamil
03:52 queued 35s
created

LockAbstract   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 111
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Test Coverage

Coverage 85.29%

Importance

Changes 0
Metric Value
wmc 16
c 0
b 0
f 0
lcom 2
cbo 3
dl 0
loc 111
ccs 29
cts 34
cp 0.8529
rs 10

8 Methods

Rating   Name   Duplication   Size   Complexity  
A __clone() 0 4 1
A __destruct() 0 12 3
B acquireLock() 0 18 7
A __construct() 0 4 2
getLock() 0 1 ?
A getLockInformation() 0 4 1
A getLockInformationProvider() 0 4 1
A setLockInformationProvider() 0 4 1
1
<?php
2
/**
3
 * This file is part of ninja-mutex.
4
 *
5
 * (C) Kamil Dziedzic <[email protected]>
6
 *
7
 * For the full copyright and license information, please view the LICENSE
8
 * file that was distributed with this source code.
9
 */
10
namespace NinjaMutex\Lock;
11
12
use NinjaMutex\UnrecoverableMutexException;
13
14
/**
15
 * Abstract lock implementor
16
 *
17
 * @author Kamil Dziedzic <[email protected]>
18
 */
19
abstract class LockAbstract implements LockInterface
20
{
21
    const USLEEP_TIME = 100;
22
23
    /**
24
     * Provides information which allows to track down process which acquired lock
25
     *
26
     * @var LockInformationProviderInterface
27
     */
28
    protected $lockInformationProvider;
29
30
    /**
31
     * @var array
32
     */
33
    protected $locks = array();
34
35 2
    public function __construct(LockInformationProviderInterface $informationProvider = null)
36
    {
37 2
        $this->lockInformationProvider = $informationProvider ? : new BasicLockInformationProvider();
38 2
    }
39
40 65
    public function __clone()
41
    {
42 65
        $this->locks = array();
43 65
    }
44
45
    /**
46
     * Try to release any obtained locks when object is destroyed
47
     *
48
     * This is a safe guard for cases when your php script dies unexpectedly.
49
     * It's not guaranteed it will work either.
50
     *
51
     * You should not depend on __destruct() to release your locks,
52
     * instead release them with `$released = $this->releaseLock()`A
53
     * and check `$released` if lock was properly released
54
     */
55 61
    public function __destruct()
56
    {
57 61
        foreach ($this->locks as $name => $v) {
58 15
            $released = $this->releaseLock($name);
59 15
            if (!$released) {
60 4
                throw new UnrecoverableMutexException(sprintf(
61 4
                    'Cannot release lock in __destruct(): %s',
62
                    $name
63 4
                ));
64
            }
65 57
        }
66 57
    }
67
68
    /**
69
     * Acquire lock
70
     *
71
     * @param  string   $name    name of lock
72
     * @param  null|int $timeout 1. null if you want blocking lock
73
     *                           2. 0 if you want just lock and go
74
     *                           3. $timeout > 0 if you want to wait for lock some time (in milliseconds)
75
     * @return bool
76
     */
77 214
    public function acquireLock($name, $timeout = null)
78
    {
79 214
        $blocking = $timeout === null;
80 214
        $start = microtime(true);
81 214
        $end = $start + $timeout / 1000;
82 214
        $locked = false;
83 214
        while (!(empty($this->locks[$name]) && $locked = $this->getLock($name, $blocking)) && ($blocking || ($timeout > 0 && microtime(true) < $end))) {
84 13
            usleep(static::USLEEP_TIME);
85 13
        }
86
87 214
        if ($locked) {
88 214
            $this->locks[$name] = true;
89
90 214
            return true;
91
        }
92
93 91
        return false;
94
    }
95
96
    /**
97
     * @param  string $name
98
     * @param  bool   $blocking If lock provider supports blocking then you can pass this param through,
99
     *                          otherwise, ignore this variable, default blocking method will be used.
100
     * @return bool
101
     */
102
    abstract protected function getLock($name, $blocking);
103
104
    /**
105
     * Information returned by this method allow to track down process which acquired lock
106
     * .
107
     * @return array
108
     */
109 134
    protected function getLockInformation()
110
    {
111 134
        return $this->lockInformationProvider->getLockInformation();
112
    }
113
114
    /**
115
     * @return LockInformationProviderInterface
116
     */
117
    public function getLockInformationProvider()
118
    {
119
        return $this->lockInformationProvider;
120
    }
121
122
    /**
123
     * @param LockInformationProviderInterface $lockInformationProvider
124
     */
125
    public function setLockInformationProvider($lockInformationProvider)
126
    {
127
        $this->lockInformationProvider = $lockInformationProvider;
128
    }
129
}
130