| 233 | } |
| 234 | |
| 235 | func (p *_LockStoreImp) unlock(key string, method _UnlockingMethod) { |
| 236 | if p.granularity == PerKeyGranularity { |
| 237 | var lock *_LockImp |
| 238 | var ok bool |
| 239 | p.storeLock.RLock() |
| 240 | // let's check if we have an existing lock for the given key |
| 241 | if lock, ok = p.perKeyLocks[key]; ok { |
| 242 | p.storeLock.RUnlock() |
| 243 | |
| 244 | // let's call the real unlock |
| 245 | switch method { |
| 246 | case _Unlock: |
| 247 | lock.Unlock() |
| 248 | case _RUnlock: |
| 249 | lock.RUnlock() |
| 250 | } |
| 251 | |
| 252 | newRefCount := atomic.AddInt32(&lock.count, -1) |
| 253 | // if this is the last Unlock, let's clean up |
| 254 | if newRefCount == 0 { |
| 255 | // let's garbage collect it iff the lock is still |
| 256 | // in our dictionary. It might have been replaced |
| 257 | // if someone called Lock after the last unlock. We need to double-check |
| 258 | // ref-count again because we need to check for the ref-count for deletion |
| 259 | // while holding the storelock exclusively |
| 260 | p.storeLock.Lock() |
| 261 | if existingLock := p.perKeyLocks[key]; existingLock == lock && |
| 262 | atomic.LoadInt32(&lock.count) == 0 { |
| 263 | delete(p.perKeyLocks, key) |
| 264 | } |
| 265 | p.storeLock.Unlock() |
| 266 | } else if newRefCount < 0 { |
| 267 | panic("negative lock count for key " + key) |
| 268 | } |
| 269 | } else { |
| 270 | p.storeLock.RUnlock() |
| 271 | panic("unexpected unlock without a lock for key " + key) |
| 272 | } |
| 273 | } else if p.granularity == StoreGranularity { |
| 274 | switch method { |
| 275 | case _Unlock: |
| 276 | p.storeLock.Unlock() |
| 277 | case _RUnlock: |
| 278 | p.storeLock.RUnlock() |
| 279 | } |
| 280 | } else if p.granularity == ShardedGranularity { |
| 281 | // hash the key into a bucked and return that lock |
| 282 | shard, err := shardForKey(key, len(p.shardedLocks)) |
| 283 | if err != nil { |
| 284 | panic(err.Error()) |
| 285 | } |
| 286 | switch method { |
| 287 | case _Unlock: |
| 288 | p.shardedLocks[shard].Unlock() |
| 289 | case _RUnlock: |
| 290 | p.shardedLocks[shard].RUnlock() |
| 291 | } |
| 292 | } else { |