Package com.orientechnologies.common.concur.lock

Source Code of com.orientechnologies.common.concur.lock.OReadersWriterSpinLock$WNode

/*
  *
  *  *  Copyright 2014 Orient Technologies LTD (info(at)orientechnologies.com)
  *  *
  *  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  *  you may not use this file except in compliance with the License.
  *  *  You may obtain a copy of the License at
  *  *
  *  *       http://www.apache.org/licenses/LICENSE-2.0
  *  *
  *  *  Unless required by applicable law or agreed to in writing, software
  *  *  distributed under the License is distributed on an "AS IS" BASIS,
  *  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  *  *  See the License for the specific language governing permissions and
  *  *  limitations under the License.
  *  *
  *  * For more information: http://www.orientechnologies.com
  *
  */

package com.orientechnologies.common.concur.lock;

import com.orientechnologies.common.types.OModifiableInteger;

import java.util.HashSet;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.AbstractOwnableSynchronizer;
import java.util.concurrent.locks.LockSupport;

/**
* @author Andrey Lomakin <a href="mailto:lomakin.andrey@gmail.com">Andrey Lomakin</a>
* @since 8/18/14
*/
public class OReadersWriterSpinLock extends AbstractOwnableSynchronizer {
  private final OThreadCountersHashTable        threadCountersHashTable = new OThreadCountersHashTable();

  private final AtomicReference<WNode>          tail                    = new AtomicReference<WNode>();
  private final ThreadLocal<OModifiableInteger> lockHolds               = new ThreadLocal<OModifiableInteger>() {
                                                                          @Override
                                                                          protected OModifiableInteger initialValue() {
                                                                            return new OModifiableInteger();
                                                                          }
                                                                        };

  private final ThreadLocal<WNode>              myNode                  = new ThreadLocal<WNode>() {
                                                                          @Override
                                                                          protected WNode initialValue() {
                                                                            return new WNode();
                                                                          }
                                                                        };
  private final ThreadLocal<WNode>              predNode                = new ThreadLocal<WNode>();

  public OReadersWriterSpinLock() {
    final WNode wNode = new WNode();
    wNode.locked = false;

    tail.set(wNode);
  }

  public void acquireReadLock() {
    final OModifiableInteger lHolds = lockHolds.get();

    final int holds = lHolds.intValue();
    if (holds > 0) {
      // we have already acquire read lock
      lHolds.increment();
      return;
    } else if (holds < 0) {
      // write lock is acquired before, do nothing
      return;
    }

    threadCountersHashTable.increment();

    WNode wNode = tail.get();
    while (wNode.locked) {
      threadCountersHashTable.decrement();

      while (wNode.locked) {
        wNode.waitingReaders.add(Thread.currentThread());

        if (wNode == tail.get() && wNode.locked)
          LockSupport.park(this);

        wNode = tail.get();
      }

      threadCountersHashTable.increment();

      wNode = tail.get();
    }

    lHolds.increment();
    assert lHolds.intValue() == 1;
  }

  public void releaseReadLock() {
    final OModifiableInteger lHolds = lockHolds.get();
    final int holds = lHolds.intValue();
    if (holds > 1) {
      lockHolds.get().decrement();
      return;
    } else if (holds < 0) {
      // write lock was acquired before, do nothing
      return;
    }

    threadCountersHashTable.decrement();

    lHolds.decrement();
    assert lHolds.intValue() == 0;
  }

  public void acquireWriteLock() {
    final OModifiableInteger lHolds = lockHolds.get();

    if (lHolds.intValue() < 0) {
      lHolds.decrement();
      return;
    }

    final WNode node = myNode.get();
    node.locked = true;

    final WNode pNode = tail.getAndSet(myNode.get());
    predNode.set(pNode);

    while (pNode.locked) {
      pNode.waitingWriter = Thread.currentThread();

      if (pNode.locked)
        LockSupport.park(this);
    }

    pNode.waitingWriter = null;

    while (!threadCountersHashTable.isEmpty())
      ;

    setExclusiveOwnerThread(Thread.currentThread());

    lHolds.decrement();
    assert lHolds.intValue() == -1;
  }

  public void releaseWriteLock() {
    final OModifiableInteger lHolds = lockHolds.get();

    if (lHolds.intValue() < -1) {
      lHolds.increment();
      return;
    }

    setExclusiveOwnerThread(null);

    final WNode node = myNode.get();
    node.locked = false;

    final Thread waitingWriter = node.waitingWriter;
    if (waitingWriter != null)
      LockSupport.unpark(waitingWriter);

    final Set<Thread> waitingReaders = new HashSet<Thread>();

    for (Thread waitingReader : node.waitingReaders) {
      if (waitingReaders.add(waitingReader))
        LockSupport.unpark(waitingReader);
    }

    myNode.set(predNode.get());
    predNode.set(null);

    lHolds.increment();
    assert lHolds.intValue() == 0;
  }

  private final static class WNode {
    private final Queue<Thread> waitingReaders = new ConcurrentLinkedQueue<Thread>();

    private volatile boolean    locked         = true;
    private volatile Thread     waitingWriter;
  }
}
TOP

Related Classes of com.orientechnologies.common.concur.lock.OReadersWriterSpinLock$WNode

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.