| 129 | } |
| 130 | |
| 131 | func (p *_LockStoreImp) tryLock( |
| 132 | key string, |
| 133 | timeout time.Duration, |
| 134 | lockingMethod _LockingMethod, |
| 135 | unlockingMethod _UnlockingMethod) bool { |
| 136 | done := make(chan struct{}) |
| 137 | |
| 138 | // We need both variables, checks, and unlock attempts to make the code thread-safe. |
| 139 | locked := false |
| 140 | timedOut := false |
| 141 | syncLock := sync.Mutex{} |
| 142 | go func() { |
| 143 | defer close(done) |
| 144 | p.lock(key, lockingMethod) |
| 145 | syncLock.Lock() |
| 146 | locked = true |
| 147 | if timedOut { |
| 148 | // we timed-out. |
| 149 | p.unlock(key, unlockingMethod) |
| 150 | } |
| 151 | syncLock.Unlock() |
| 152 | p.testTryLockCallback() |
| 153 | }() |
| 154 | |
| 155 | select { |
| 156 | case <-done: |
| 157 | return true |
| 158 | case <-time.After(timeout): |
| 159 | // We timed-out. We need to release the lock internally |
| 160 | syncLock.Lock() |
| 161 | timedOut = true |
| 162 | if locked { |
| 163 | // we timed-out. |
| 164 | p.unlock(key, unlockingMethod) |
| 165 | } |
| 166 | syncLock.Unlock() |
| 167 | } |
| 168 | |
| 169 | return false |
| 170 | } |
| 171 | |
| 172 | func (p *_LockStoreImp) lock(key string, method _LockingMethod) { |
| 173 | if p.granularity == PerKeyGranularity { |