Пример #1
0
 final void writeValue(long allocIndex, Object value) {
   U.putObject(this, allocOffset(allocIndex) + ARRAY_OBJECT_INDEX_SCALE, value);
 }
Пример #2
0
  /**
   * See above for explanation.
   *
   * @param interruptible true if should check interrupts and if so return INTERRUPTED
   * @param deadline if nonzero, the System.nanoTime value to timeout at (and return zero)
   * @return next state, or INTERRUPTED
   */
  private long acquireRead(boolean interruptible, long deadline) {
    WNode node = null, p;
    boolean interrupted = false;
    for (int spins = -1; ; ) {
      WNode h;
      if ((h = whead) == (p = wtail)) {
        for (long m, s, ns; ; ) {
          if ((m = (s = state) & ABITS) < RFULL
              ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT)
              : (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
            if (interrupted) Thread.currentThread().interrupt();
            return ns;
          } else if (m >= WBIT) {
            if (spins > 0) {
              if (LockSupport.nextSecondarySeed() >= 0) --spins;
            } else {
              if (spins == 0) {
                WNode nh = whead, np = wtail;
                if ((nh == h && np == p) || (h = nh) != (p = np)) break;
              }
              spins = SPINS;
            }
          }
        }
      }
      if (p == null) { // initialize queue
        WNode hd = new WNode(WMODE, null);
        if (U.compareAndSwapObject(this, WHEAD, null, hd)) wtail = hd;
      } else if (node == null) node = new WNode(RMODE, p);
      else if (h == p || p.mode != RMODE) {
        if (node.prev != p) node.prev = p;
        else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
          p.next = node;
          break;
        }
      } else if (!U.compareAndSwapObject(p, WCOWAIT, node.cowait = p.cowait, node))
        node.cowait = null;
      else {
        for (; ; ) {
          WNode pp, c;
          Thread w;
          if ((h = whead) != null
              && (c = h.cowait) != null
              && U.compareAndSwapObject(h, WCOWAIT, c, c.cowait)
              && (w = c.thread) != null) // help release
          U.unpark(w);
          if (h == (pp = p.prev) || h == p || pp == null) {
            long m, s, ns;
            do {
              if ((m = (s = state) & ABITS) < RFULL
                  ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT)
                  : (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
                if (interrupted) Thread.currentThread().interrupt();
                return ns;
              }
            } while (m < WBIT);
          }
          if (whead == h && p.prev == pp) {
            long time;
            if (pp == null || h == p || p.status > 0) {
              node = null; // throw away
              break;
            }
            if (deadline == 0L) time = 0L;
            else if ((time = deadline - System.nanoTime()) <= 0L)
              return cancelWaiter(node, p, false);
            Thread wt = Thread.currentThread();
            U.putObject(wt, PARKBLOCKER, this);
            node.thread = wt;
            if ((h != pp || (state & ABITS) == WBIT) && whead == h && p.prev == pp)
              U.park(false, time);
            node.thread = null;
            U.putObject(wt, PARKBLOCKER, null);
            //                        if (interruptible && Thread.interrupted())
            //                            return cancelWaiter(node, p, true);
            if (Thread.interrupted()) {
              if (interruptible) return cancelWaiter(node, p, true);
              else interrupted = true;
            }
          }
        }
      }
    }

    for (int spins = -1; ; ) {
      WNode h, np, pp;
      int ps;
      if ((h = whead) == p) {
        if (spins < 0) spins = HEAD_SPINS;
        else if (spins < MAX_HEAD_SPINS) spins <<= 1;
        for (int k = spins; ; ) { // spin at head
          long m, s, ns;
          if ((m = (s = state) & ABITS) < RFULL
              ? U.compareAndSwapLong(this, STATE, s, ns = s + RUNIT)
              : (m < WBIT && (ns = tryIncReaderOverflow(s)) != 0L)) {
            WNode c;
            Thread w;
            whead = node;
            node.prev = null;
            while ((c = node.cowait) != null) {
              if (U.compareAndSwapObject(node, WCOWAIT, c, c.cowait) && (w = c.thread) != null)
                U.unpark(w);
            }
            if (interrupted) Thread.currentThread().interrupt();
            return ns;
          } else if (m >= WBIT && LockSupport.nextSecondarySeed() >= 0 && --k <= 0) break;
        }
      } else if (h != null) {
        WNode c;
        Thread w;
        while ((c = h.cowait) != null) {
          if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) && (w = c.thread) != null)
            U.unpark(w);
        }
      }
      if (whead == h) {
        if ((np = node.prev) != p) {
          if (np != null) (p = np).next = node; // stale
        } else if ((ps = p.status) == 0) U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
        else if (ps == CANCELLED) {
          if ((pp = p.prev) != null) {
            node.prev = pp;
            pp.next = node;
          }
        } else {
          long time;
          if (deadline == 0L) time = 0L;
          else if ((time = deadline - System.nanoTime()) <= 0L)
            return cancelWaiter(node, node, false);
          Thread wt = Thread.currentThread();
          U.putObject(wt, PARKBLOCKER, this);
          node.thread = wt;
          if (p.status < 0 && (p != h || (state & ABITS) == WBIT) && whead == h && node.prev == p)
            U.park(false, time);
          node.thread = null;
          U.putObject(wt, PARKBLOCKER, null);
          //                    if (interruptible && Thread.interrupted())
          //                        return cancelWaiter(node, node, true);
          if (Thread.interrupted()) {
            if (interruptible) return cancelWaiter(node, p, true);
            else interrupted = true;
          }
        }
      }
    }
  }
Пример #3
0
 final void writeKey(long allocIndex, Object key) {
   U.putObject(this, allocOffset(allocIndex), key);
 }
Пример #4
0
  /**
   * See above for explanation.
   *
   * @param interruptible true if should check interrupts and if so return INTERRUPTED
   * @param deadline if nonzero, the System.nanoTime value to timeout at (and return zero)
   * @return next state, or INTERRUPTED
   */
  private long acquireWrite(boolean interruptible, long deadline) {
    WNode node = null, p;
    boolean interrupted = false;
    for (int spins = -1; ; ) { // spin while enqueuing
      long m, s, ns;
      if ((m = (s = state) & ABITS) == 0L) {
        if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) {
          if (interrupted) Thread.currentThread().interrupt();
          return ns;
        }
      } else if (spins < 0) spins = (m == WBIT && wtail == whead) ? SPINS : 0;
      else if (spins > 0) {
        if (LockSupport.nextSecondarySeed() >= 0) --spins;
      } else if ((p = wtail) == null) { // initialize queue
        WNode hd = new WNode(WMODE, null);
        if (U.compareAndSwapObject(this, WHEAD, null, hd)) wtail = hd;
      } else if (node == null) node = new WNode(WMODE, p);
      else if (node.prev != p) node.prev = p;
      else if (U.compareAndSwapObject(this, WTAIL, p, node)) {
        p.next = node;
        break;
      }
    }

    for (int spins = -1; ; ) {
      WNode h, np, pp;
      int ps;
      if ((h = whead) == p) {
        if (spins < 0) spins = HEAD_SPINS;
        else if (spins < MAX_HEAD_SPINS) spins <<= 1;
        for (int k = spins; ; ) { // spin at head
          long s, ns;
          if (((s = state) & ABITS) == 0L) {
            if (U.compareAndSwapLong(this, STATE, s, ns = s + WBIT)) {
              whead = node;
              node.prev = null;
              if (interrupted) Thread.currentThread().interrupt();
              return ns;
            }
          } else if (LockSupport.nextSecondarySeed() >= 0 && --k <= 0) break;
        }
      } else if (h != null) { // help release stale waiters
        WNode c;
        Thread w;
        while ((c = h.cowait) != null) {
          if (U.compareAndSwapObject(h, WCOWAIT, c, c.cowait) && (w = c.thread) != null)
            U.unpark(w);
        }
      }
      if (whead == h) {
        if ((np = node.prev) != p) {
          if (np != null) (p = np).next = node; // stale
        } else if ((ps = p.status) == 0) U.compareAndSwapInt(p, WSTATUS, 0, WAITING);
        else if (ps == CANCELLED) {
          if ((pp = p.prev) != null) {
            node.prev = pp;
            pp.next = node;
          }
        } else {
          long time; // 0 argument to park means no timeout
          if (deadline == 0L) time = 0L;
          else if ((time = deadline - System.nanoTime()) <= 0L)
            return cancelWaiter(node, node, false);
          Thread wt = Thread.currentThread();
          U.putObject(wt, PARKBLOCKER, this);
          node.thread = wt;
          if (p.status < 0 && (p != h || (state & ABITS) != 0L) && whead == h && node.prev == p)
            U.park(false, time); // emulate LockSupport.park
          node.thread = null;
          U.putObject(wt, PARKBLOCKER, null);
          //                    if (interruptible && Thread.interrupted())
          //                        return cancelWaiter(node, node, true);
          if (Thread.interrupted()) {
            if (interruptible) return cancelWaiter(node, node, true);
            else interrupted = true;
          }
        }
      }
    }
  }