Completed
Push — pr33 ( 0a4bbb )
by Kamil
02:37
created

LockAbstract::generateLockInformation()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 14
Code Lines 9

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 1

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 14
ccs 9
cts 9
cp 1
rs 9.4285
cc 1
eloc 9
nc 1
nop 0
crap 1

1 Method

Rating   Name   Duplication   Size   Complexity  
A LockAbstract::getLockInformationProvider() 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 70
    public function __clone()
41
    {
42 70
        $this->locks = array();
43 70
    }
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 66
    public function __destruct()
56
    {
57 66
        foreach ($this->locks as $name => $v) {
58 16
            $released = $this->releaseLock($name);
59 16
            if (!$released) {
60 4
                throw new UnrecoverableMutexException(sprintf(
61 4
                    'Cannot release lock in __destruct(): %s',
62
                    $name
63 4
                ));
64
            }
65 62
        }
66 62
    }
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 230
    public function acquireLock($name, $timeout = null)
78
    {
79 230
        $blocking = $timeout === null;
80 230
        $start = microtime(true);
81 230
        $end = $start + $timeout / 1000;
82 230
        $locked = false;
83 230
        while (!(empty($this->locks[$name]) && $locked = $this->getLock($name, $blocking)) && ($blocking || ($timeout > 0 && microtime(true) < $end))) {
84 14
            usleep(static::USLEEP_TIME);
85 14
        }
86
87 230
        if ($locked) {
88 230
            $this->locks[$name] = true;
89
90 230
            return true;
91
        }
92
93 96
        return false;
94
    }
95
96
    /**
97
     * @param  string $name
98
     * @param  bool   $blocking
99
     * @return bool
100
     */
101
    abstract protected function getLock($name, $blocking);
102
103
    /**
104
     * Information returned by this method allow to track down process which acquired lock
105
     * .
106
     * @return array
107
     */
108 134
    protected function getLockInformation()
109
    {
110 134
        return $this->lockInformationProvider->getLockInformation();
111
    }
112
113
    /**
114
     * @return LockInformationProviderInterface
115
     */
116
    public function getLockInformationProvider()
117
    {
118
        return $this->lockInformationProvider;
119
    }
120
121
    /**
122
     * @param LockInformationProviderInterface $lockInformationProvider
123
     */
124
    public function setLockInformationProvider($lockInformationProvider)
125
    {
126
        $this->lockInformationProvider = $lockInformationProvider;
127
    }
128
}
129