protected internal override OwnerQueueElement <Thread> Acquire(LockedEntity key) { OwnerQueueElement <Thread> suggestion = new OwnerQueueElement <Thread>(currentThread()); for ( ; ;) { OwnerQueueElement <Thread> owner = _locks.putIfAbsent(key, suggestion); if (owner == null) { // Our suggestion was accepted, we got the lock return(suggestion); } Thread other = owner.Owner; if (other == currentThread()) { // the lock has been handed to us (or we are re-entering), claim it! owner.Count++; return(owner); } // Make sure that we only add to the queue once, and if that addition fails (because the queue is dead // - i.e. has been removed from the map), retry form the top of the loop immediately. if (suggestion.Head == suggestion) // true if enqueue() has not been invoked (i.e. first time around) { // otherwise it has already been enqueued, and we are in a spurious (or timed) wake up if (!owner.Enqueue(suggestion)) { continue; // the lock has already been released, the queue is dead, retry! } } parkNanos(key, _maxParkNanos); } }
//JAVA TO C# CONVERTER TODO TASK: Most Java annotations will not have direct .NET equivalent attributes: //ORIGINAL LINE: @Override @SuppressWarnings("SynchronizationOnLocalVariableOrMethodParameter") protected void release(LockedEntity key, OwnerQueueElement<Thread> ownerQueueElement) protected internal override void Release(LockedEntity key, OwnerQueueElement <Thread> ownerQueueElement) { if (0 == --ownerQueueElement.Count) { Thread nextThread; lock ( ownerQueueElement ) { nextThread = ownerQueueElement.Dequeue(); if (nextThread == currentThread()) { // no more threads in the queue, remove this list _locks.remove(key, ownerQueueElement); // done under synchronization to honour definition of 'dead' nextThread = null; // to make unpark() a no-op. } } unpark(nextThread); } }
/// <summary> /// Return true if the item was enqueued, or false if this LockOwner is dead. /// A dead LockOwner is no longer reachable from the map, and so no longer participates in the lock. /// </summary> internal bool Enqueue(OwnerQueueElement <OWNER> last) { lock (this) { if (Owner == default(OWNER)) { return(false); // don't enqueue into a dead queue } last.Head = this; last.Tail = this; Tail.tail = last; this.Tail = last; if (Head == this) { Head = last; } return(true); } }
internal OWNER Dequeue() { lock (this) { OwnerQueueElement <OWNER> first = this.Head; (this.Head = first.Tail).head = this; first.Tail = this; if (this.Head == this) { this.Tail = this; // don't leave junk references around! } try { return(this.Owner = first.Owner); } finally { first.Owner = default(OWNER); // mark 'first' as dead. } } }