예제 #1
0
 /** Initializes a random variable */
 private void createRandom() {
   this.random =
       new Random(
           System.currentTimeMillis()
               + Thread.currentThread().getId()
               - Thread.currentThread().hashCode()
               + this.cname.hashCode());
 }
예제 #2
0
 /**
  * Retrieves and removes the head of this queue, waiting if necessary until an element with an
  * expired delay is available on this queue, or the specified wait time expires.
  *
  * @return the head of this queue, or <tt>null</tt> if the specified waiting time elapses before
  *     an element with an expired delay becomes available
  * @throws InterruptedException {@inheritDoc}
  */
 public E poll(long timeout, TimeUnit unit) throws InterruptedException {
   long nanos = unit.toNanos(timeout);
   final ReentrantLock lock = this.lock;
   lock.lockInterruptibly();
   try {
     for (; ; ) {
       E first = q.peek();
       if (first == null) {
         if (nanos <= 0) return null;
         else nanos = available.awaitNanos(nanos);
       } else {
         long delay = first.getDelay(TimeUnit.NANOSECONDS);
         if (delay <= 0) return q.poll();
         if (nanos <= 0) return null;
         if (nanos < delay || leader != null) nanos = available.awaitNanos(nanos);
         else {
           Thread thisThread = Thread.currentThread();
           leader = thisThread;
           try {
             long timeLeft = available.awaitNanos(delay);
             nanos -= delay - timeLeft;
           } finally {
             if (leader == thisThread) leader = null;
           }
         }
       }
     }
   } finally {
     if (leader == null && q.peek() != null) available.signal();
     lock.unlock();
   }
 }
예제 #3
0
 /**
  * Retrieves and removes the head of this queue, waiting if necessary until an element with an
  * expired delay is available on this queue.
  *
  * @return the head of this queue
  * @throws InterruptedException {@inheritDoc}
  */
 public E take() throws InterruptedException {
   final ReentrantLock lock = this.lock;
   lock.lockInterruptibly();
   try {
     for (; ; ) {
       E first = q.peek();
       if (first == null) available.await();
       else {
         long delay = first.getDelay(TimeUnit.NANOSECONDS);
         if (delay <= 0) return q.poll();
         else if (leader != null) available.await();
         else {
           Thread thisThread = Thread.currentThread();
           leader = thisThread;
           try {
             available.awaitNanos(delay);
           } finally {
             if (leader == thisThread) leader = null;
           }
         }
       }
     }
   } finally {
     if (leader == null && q.peek() != null) available.signal();
     lock.unlock();
   }
 }
  public HostConnectionPool(Host host, HostDistance hostDistance, Session.Manager manager)
      throws ConnectionException {
    assert hostDistance != HostDistance.IGNORED;
    this.host = host;
    this.hostDistance = hostDistance;
    this.manager = manager;

    this.newConnectionTask =
        new Runnable() {
          @Override
          public void run() {
            addConnectionIfUnderMaximum();
            scheduledForCreation.decrementAndGet();
          }
        };

    // Create initial core connections
    List<Connection> l =
        new ArrayList<Connection>(options().getCoreConnectionsPerHost(hostDistance));
    try {
      for (int i = 0; i < options().getCoreConnectionsPerHost(hostDistance); i++)
        l.add(manager.connectionFactory().open(host));
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      // If asked to interrupt, we can skip opening core connections, the pool will still work.
      // But we ignore otherwise cause I'm not sure we can do much better currently.
    }
    this.connections = new CopyOnWriteArrayList<Connection>(l);
    this.open = new AtomicInteger(connections.size());

    logger.trace("Created connection pool to host {}", host);
  }
 public void shutdown() {
   try {
     shutdown(0, TimeUnit.MILLISECONDS);
   } catch (InterruptedException e) {
     Thread.currentThread().interrupt();
   }
 }
예제 #6
0
 // Acquire the lock if state is zero
 public boolean tryAcquire(int acquires) {
   assert acquires == 1; // Otherwise unused
   if (compareAndSetState(0, 1)) {
     setExclusiveOwnerThread(Thread.currentThread());
     return true;
   }
   return false;
 }
예제 #7
0
        @Override
        public void run() {
          reentrantLock.lock();
          // if pool-1-thread-1 is the last, no thread will notify it;
          while (Thread.currentThread().getName().equals("pool-1-thread-1")) {
            try {
              condition.await();

            } catch (InterruptedException e) {
              e.printStackTrace();
            }
          }
          for (Integer integer : list) {
            System.out.println(integer);
            System.out.println(Thread.currentThread().getName());
          }
          condition.signalAll();
          reentrantLock.unlock();
        }
  /**
   * @param key Removed key.
   * @param ver Removed version.
   * @throws IgniteCheckedException If failed.
   */
  public void onDeferredDelete(KeyCacheObject key, GridCacheVersion ver)
      throws IgniteCheckedException {
    try {
      T2<KeyCacheObject, GridCacheVersion> evicted = rmvQueue.add(new T2<>(key, ver));

      if (evicted != null) cctx.dht().removeVersionedEntry(evicted.get1(), evicted.get2());
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();

      throw new IgniteInterruptedCheckedException(e);
    }
  }
  /** {@inheritDoc} */
  @Override
  public R get(long timeout, TimeUnit unit) throws IgniteCheckedException {
    A.ensure(timeout >= 0, "timeout cannot be negative: " + timeout);
    A.notNull(unit, "unit");

    try {
      return get0(unit.toNanos(timeout));
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();

      throw new IgniteInterruptedCheckedException(
          "Got interrupted while waiting for future to complete.", e);
    }
  }
예제 #10
0
 // 提供一个线程安全draw()方法来完成取钱操作
 public void draw(double drawAmount) {
   // 加锁
   lock.lock();
   try {
     // 账户余额大于取钱数目
     if (balance >= drawAmount) {
       // 吐出钞票
       System.out.println(Thread.currentThread().getName() + "取钱成功!吐出钞票:" + drawAmount);
       try {
         Thread.sleep(1);
       } catch (InterruptedException ex) {
         ex.printStackTrace();
       }
       // 修改余额
       balance -= drawAmount;
       System.out.println("\t余额为: " + balance);
     } else {
       System.out.println(Thread.currentThread().getName() + "取钱失败!余额不足!");
     }
   } finally {
     // 修改完成,释放锁
     lock.unlock();
   }
 }
예제 #11
0
 /**
  * Spins/blocks until node s is matched by a fulfill operation.
  *
  * @param s the waiting node
  * @param timed true if timed wait
  * @param nanos timeout value
  * @return matched node, or s if cancelled
  */
 SNode awaitFulfill(SNode s, boolean timed, long nanos) {
   /*
    * When a node/thread is about to block, it sets its waiter
    * field and then rechecks state at least one more time
    * before actually parking, thus covering race vs
    * fulfiller noticing that waiter is non-null so should be
    * woken.
    *
    * When invoked by nodes that appear at the point of call
    * to be at the head of the stack, calls to park are
    * preceded by spins to avoid blocking when producers and
    * consumers are arriving very close in time.  This can
    * happen enough to bother only on multiprocessors.
    *
    * The order of checks for returning out of main loop
    * reflects fact that interrupts have precedence over
    * normal returns, which have precedence over
    * timeouts. (So, on timeout, one last check for match is
    * done before giving up.) Except that calls from untimed
    * SynchronousQueue.{poll/offer} don't check interrupts
    * and don't wait at all, so are trapped in transfer
    * method rather than calling awaitFulfill.
    */
   long lastTime = timed ? System.nanoTime() : 0;
   Thread w = Thread.currentThread();
   SNode h = head;
   int spins = (shouldSpin(s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0);
   for (; ; ) {
     if (w.isInterrupted()) s.tryCancel();
     SNode m = s.match;
     if (m != null) return m;
     if (timed) {
       long now = System.nanoTime();
       nanos -= now - lastTime;
       lastTime = now;
       if (nanos <= 0) {
         s.tryCancel();
         continue;
       }
     }
     if (spins > 0) spins = shouldSpin(s) ? (spins - 1) : 0;
     else if (s.waiter == null) s.waiter = w; // establish waiter so can park next iter
     else if (!timed) LockSupport.park(this);
     else if (nanos > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanos);
   }
 }
  private boolean addConnectionIfUnderMaximum() {

    // First, make sure we don't cross the allowed limit of open connections
    for (; ; ) {
      int opened = open.get();
      if (opened >= options().getMaxConnectionsPerHost(hostDistance)) return false;

      if (open.compareAndSet(opened, opened + 1)) break;
    }

    if (isShutdown()) {
      open.decrementAndGet();
      return false;
    }

    // Now really open the connection
    try {
      connections.add(manager.connectionFactory().open(host));
      signalAvailableConnection();
      return true;
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();
      // Skip the open but ignore otherwise
      open.decrementAndGet();
      return false;
    } catch (ConnectionException e) {
      open.decrementAndGet();
      logger.debug("Connection error to {} while creating additional connection", host);
      if (host.getMonitor().signalConnectionFailure(e)) shutdown();
      return false;
    } catch (AuthenticationException e) {
      // This shouldn't really happen in theory
      open.decrementAndGet();
      logger.error(
          "Authentication error while creating additional connection (error is: {})",
          e.getMessage());
      shutdown();
      return false;
    }
  }
  /** {@inheritDoc} */
  @Override
  public R get() throws IgniteCheckedException {
    try {
      if (endTime == 0) {
        if (ignoreInterrupts) acquireShared(0);
        else acquireSharedInterruptibly(0);
      }

      if (getState() == CANCELLED)
        throw new IgniteFutureCancelledCheckedException("Future was cancelled: " + this);

      assert resFlag != 0;

      if (resFlag == ERR) throw U.cast((Throwable) res);

      return (R) res;
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();

      throw new IgniteInterruptedCheckedException(e);
    }
  }
  private Connection waitForConnection(long timeout, TimeUnit unit)
      throws ConnectionException, TimeoutException {
    long start = System.nanoTime();
    long remaining = timeout;
    do {
      try {
        awaitAvailableConnection(remaining, unit);
      } catch (InterruptedException e) {
        Thread.currentThread().interrupt();
        // If we're interrupted fine, check if there is a connection available but stop waiting
        // otherwise
        timeout = 0; // this will make us stop the loop if we don't get a connection right away
      }

      if (isShutdown()) throw new ConnectionException(host.getAddress(), "Pool is shutdown");

      int minInFlight = Integer.MAX_VALUE;
      Connection leastBusy = null;
      for (Connection connection : connections) {
        int inFlight = connection.inFlight.get();
        if (inFlight < minInFlight) {
          minInFlight = inFlight;
          leastBusy = connection;
        }
      }

      while (true) {
        int inFlight = leastBusy.inFlight.get();

        if (inFlight >= Connection.MAX_STREAM_PER_CONNECTION) break;

        if (leastBusy.inFlight.compareAndSet(inFlight, inFlight + 1)) return leastBusy;
      }

      remaining = timeout - Cluster.timeSince(start, unit);
    } while (remaining > 0);

    throw new TimeoutException();
  }
예제 #15
0
 /**
  * Spins/blocks until node s is fulfilled.
  *
  * @param s the waiting node
  * @param e the comparison value for checking match
  * @param timed true if timed wait
  * @param nanos timeout value
  * @return matched item, or s if cancelled
  */
 Object awaitFulfill(QNode s, Object e, boolean timed, long nanos) {
   /* Same idea as TransferStack.awaitFulfill */
   long lastTime = timed ? System.nanoTime() : 0;
   Thread w = Thread.currentThread();
   int spins = ((head.next == s) ? (timed ? maxTimedSpins : maxUntimedSpins) : 0);
   for (; ; ) {
     if (w.isInterrupted()) s.tryCancel(e);
     Object x = s.item;
     if (x != e) return x;
     if (timed) {
       long now = System.nanoTime();
       nanos -= now - lastTime;
       lastTime = now;
       if (nanos <= 0) {
         s.tryCancel(e);
         continue;
       }
     }
     if (spins > 0) --spins;
     else if (s.waiter == null) s.waiter = w;
     else if (!timed) LockSupport.park(this);
     else if (nanos > spinForTimeoutThreshold) LockSupport.parkNanos(this, nanos);
   }
 }
예제 #16
0
    void updateStateMachines(UPDATE_STATE_MACHINE caller)
          // We've got quite the little state machine here!
        {
      synchronized (callbackLock) {
        // ----------------------------------------------------------------------------------
        // If we're calling from other than the callback (in which we *know* the port is
        // ready), we need to check whether things are currently busy. We defer until
        // later if they are.
        if (caller == UPDATE_STATE_MACHINE.FROM_USER_WRITE) {
          if (!i2cDevice.isI2cPortReady() || callbackThread == null) return;

          // Optimized calling from user mode is not yet implemented
          return;
        }

        // ----------------------------------------------------------------------------------
        // Some ancillary bookkeeping

        if (caller == UPDATE_STATE_MACHINE.FROM_CALLBACK) {
          // Capture the current callback thread if we haven't already
          if (callbackThread == null) {
            callbackThread = Thread.currentThread();
            callbackThreadOriginalPriority = callbackThread.getPriority();
          } else
            assertTrue(
                !BuildConfig.DEBUG || callbackThread.getId() == Thread.currentThread().getId());

          // Set the thread name to make the system more debuggable
          if (0 == hardwareCycleCount)
            Thread.currentThread().setName(String.format("RWLoop(%s)", i2cDevice.getDeviceName()));

          // Adjust the target thread priority. Note that we only ever adjust it upwards,
          // not downwards, because in reality the thread is shared by other I2C objects
          // on the same controller and we don't want to fight with their understanding
          // of what the priority should be.
          int targetPriority = callbackThreadOriginalPriority + callbackThreadPriorityBoost;
          if (callbackThread.getPriority() < targetPriority) {
            try {
              callbackThread.setPriority(targetPriority);
            } catch (Exception e) {
              /* ignore: just run as is */
            }
          }

          // Update cycle statistics
          hardwareCycleCount++;
        }

        // ----------------------------------------------------------------------------------
        // Initialize state for managing state transition

        setActionFlag = false;
        queueFullWrite = false;
        queueRead = false;
        heartbeatRequired =
            (msHeartbeatInterval > 0
                && milliseconds(timeSinceLastHeartbeat) >= msHeartbeatInterval);
        enabledReadMode = false;
        enabledWriteMode = false;

        prevReadCacheStatus = readCacheStatus;
        prevWriteCacheStatus = writeCacheStatus;
        prevModeCacheStatus = modeCacheStatus;

        // ----------------------------------------------------------------------------------
        // Handle the state machine

        if (caller == UPDATE_STATE_MACHINE.FROM_CALLBACK) {
          // --------------------------------------------------------------------------
          // Deal with the fact that we've completed any previous queueing operation

          if (modeCacheStatus == MODE_CACHE_STATUS.QUEUED) modeCacheStatus = MODE_CACHE_STATUS.IDLE;

          if (readCacheStatus == READ_CACHE_STATUS.QUEUED
              || readCacheStatus == READ_CACHE_STATUS.VALID_QUEUED) {
            readCacheStatus = READ_CACHE_STATUS.QUEUE_COMPLETED;
            nanoTimeReadCacheValid = System.nanoTime();
          }

          if (writeCacheStatus == WRITE_CACHE_STATUS.QUEUED) {
            writeCacheStatus = WRITE_CACHE_STATUS.IDLE;
            // Our write mode status should have been reported back to us
            assertTrue(!BuildConfig.DEBUG || i2cDevice.isI2cPortInWriteMode());
          }

          // --------------------------------------------------------------------------
          // That limits the number of states the caches can now be in

          assertTrue(
              !BuildConfig.DEBUG
                  || (readCacheStatus == READ_CACHE_STATUS.IDLE
                      || readCacheStatus == READ_CACHE_STATUS.SWITCHINGTOREADMODE
                      || readCacheStatus == READ_CACHE_STATUS.VALID_ONLYONCE
                      || readCacheStatus == READ_CACHE_STATUS.QUEUE_COMPLETED));
          assertTrue(
              !BuildConfig.DEBUG
                  || (writeCacheStatus == WRITE_CACHE_STATUS.IDLE
                      || writeCacheStatus == WRITE_CACHE_STATUS.DIRTY));

          // --------------------------------------------------------------------------
          // Complete any read mode switch if there is one

          if (readCacheStatus == READ_CACHE_STATUS.SWITCHINGTOREADMODE) {
            // We're trying to switch into read mode. Are we there yet?
            if (i2cDevice.isI2cPortInReadMode()) {
              // See also below XYZZY
              readCacheStatus = READ_CACHE_STATUS.QUEUED;
              setActionFlag = true; // actually do an I2C read
              queueRead = true; // read the I2C read results
            } else {
              queueRead = true; // read the mode byte
            }
          }

          // --------------------------------------------------------------------------
          // If there's a write request pending, and it's ok to issue the write, do so

          else if (writeCacheStatus == WRITE_CACHE_STATUS.DIRTY) {
            issueWrite();

            // Our ordering rules are that any reads after a write have to wait until
            // the write is actually sent to the hardware, so anything we've read before is junk.
            // Note that there's an analogous check in read().
            readCacheStatus = READ_CACHE_STATUS.IDLE;
          }

          // --------------------------------------------------------------------------
          // Initiate reading if we should. Be sure to honor the policy of the read mode

          else if (readCacheStatus == READ_CACHE_STATUS.IDLE || readWindowChanged) {
            if (readWindow != null && readWindow.isOkToRead()) {
              // We're going to read from this window. If it's an only-once, then
              // ensure we don't come down this path again with the same ReadWindow instance.
              readWindow.setReadIssued();

              // You know...we might *already* have set up the controller to read what we want.
              // Maybe the previous read was a one-shot, for example.
              if (readWindowSentToController != null
                  && readWindowSentToController.contains(readWindow)
                  && i2cDevice.isI2cPortInReadMode()) {
                // Lucky us! We can go ahead and queue the read right now!
                // See also above XYZZY
                readWindowActuallyRead = readWindowSentToController;
                readCacheStatus = READ_CACHE_STATUS.QUEUED;
                setActionFlag = true; // actually do an I2C read
                queueRead = true; // read the results of the read
              } else {
                // We'll start switching now, and queue the read later
                readWindowActuallyRead = readWindow;
                startSwitchingToReadMode(readWindow);
              }
            } else {
              // There's nothing to read. Make *sure* we are idle.
              readCacheStatus = READ_CACHE_STATUS.IDLE;
            }

            readWindowChanged = false;
          }

          // --------------------------------------------------------------------------
          // Reissue any previous read if we should. The only way we are here and
          // see READ_CACHE_STATUS.QUEUE_COMPLETED is if we completed a queuing operation
          // above.

          else if (readCacheStatus == READ_CACHE_STATUS.QUEUE_COMPLETED) {
            if (readWindow != null && readWindow.isOkToRead()) {
              readCacheStatus = READ_CACHE_STATUS.VALID_QUEUED;
              setActionFlag = true; // actually do an I2C read
              queueRead = true; // read the results of the read
            } else {
              readCacheStatus = READ_CACHE_STATUS.VALID_ONLYONCE;
            }
          }

          // --------------------------------------------------------------------------
          // Completing the possibilities:

          else if (readCacheStatus == READ_CACHE_STATUS.VALID_ONLYONCE) {
            // Just leave it there until someone reads it
          }

          // ----------------------------------------------------------------------------------
          // Ok, after all that we finally know what how we're required to
          // interact with the device controller according to what we've been
          // asked to read or write. But what, now, about heartbeats?

          if (!setActionFlag && heartbeatRequired) {
            if (heartbeatAction != null) {
              if (readWindowSentToController != null && heartbeatAction.rereadLastRead) {
                // Controller is in or is switching to read mode. If he's there
                // yet, then issue an I2C read; if he's not, then he soon will be.
                if (i2cDevice.isI2cPortInReadMode()) {
                  setActionFlag = true; // issue an I2C read
                } else {
                  assertTrue(
                      !BuildConfig.DEBUG
                          || readCacheStatus == READ_CACHE_STATUS.SWITCHINGTOREADMODE);
                }
              } else if (readWindowSentToControllerInitialized
                  && readWindowSentToController == null
                  && heartbeatAction.rewriteLastWritten) {
                // Controller is in write mode, and the write cache has what we last wrote
                queueFullWrite = true;
                setActionFlag = true; // issue an I2C write
              } else if (heartbeatAction.heartbeatReadWindow != null) {
                // The simplest way to do this is just to do a new read from the outside, as that
                // means it has literally zero impact here on our state machine. That unfortunately
                // introduces concurrency where otherwise none might exist, but that's ONLY if you
                // choose this flavor of heartbeat, so that's a reasonable tradeoff.
                final ReadWindow window =
                    heartbeatAction
                        .heartbeatReadWindow; // capture here while we still have the lock
                Thread thread =
                    new Thread(
                        new Runnable() {
                          @Override
                          public void run() {
                            try {
                              I2cDeviceClient.this.read(window.getIregFirst(), window.getCreg());
                            } catch (Exception e) // paranoia
                            {
                              // ignored
                            }
                          }
                        });
                // Start the thread a-going. It will run relatively quickly and then shut down
                thread.setName("I2C heartbeat read thread");
                thread.setPriority(heartbeatAction.explicitReadPriority);
                thread.start();
              }
            }
          }

          if (setActionFlag) {
            // We're about to communicate on I2C right now, so reset the heartbeat.
            // Note that we reset() *before* we talk to the device so as to do
            // conservative timing accounting.
            timeSinceLastHeartbeat.reset();
          }
        } else if (caller == UPDATE_STATE_MACHINE.FROM_USER_WRITE) {
          // There's nothing we know to do that would speed things up, so we
          // just do nothing here and wait until the next portIsReady() callback.
        }

        // ----------------------------------------------------------------------------------
        // Read, set action flag and / or queue to module as requested

        if (setActionFlag) i2cDevice.setI2cPortActionFlag();
        else clearActionFlag();

        if (setActionFlag && !queueFullWrite) {
          i2cDevice.writeI2cPortFlagOnlyToController();
        } else if (queueFullWrite) {
          i2cDevice.writeI2cCacheToController();
          //
          if (modeCacheStatus == MODE_CACHE_STATUS.DIRTY)
            modeCacheStatus = MODE_CACHE_STATUS.QUEUED;
        }

        // Queue a read after queuing any write for a bit of paranoia: if we're mode switching
        // to write, we want that write to go out first, THEN read the mode status. It probably
        // would anyway, but why not...
        if (queueRead) {
          i2cDevice.readI2cCacheFromController();
        }

        // ----------------------------------------------------------------------------------
        // Do logging

        if (loggingEnabled) {
          StringBuilder message = new StringBuilder();

          switch (caller) {
            case FROM_CALLBACK:
              message.append(String.format("cyc %d", hardwareCycleCount));
              break;
            case FROM_USER_WRITE:
              message.append(String.format("usr write"));
              break;
          }
          if (setActionFlag) message.append("|flag");
          if (setActionFlag && !queueFullWrite) message.append("|f");
          else if (queueFullWrite) message.append("|w");
          else message.append("|.");
          if (queueRead) message.append("|r");
          if (readCacheStatus != prevReadCacheStatus)
            message.append(
                "| R." + prevReadCacheStatus.toString() + "->" + readCacheStatus.toString());
          if (writeCacheStatus != prevWriteCacheStatus)
            message.append(
                "| W." + prevWriteCacheStatus.toString() + "->" + writeCacheStatus.toString());
          // if (modeCacheStatus != prevModeCacheStatus)   message.append("| M." +
          // prevModeCacheStatus.toString() + "->" + modeCacheStatus.toString());
          if (enabledWriteMode)
            message.append(String.format("| setWrite(0x%02x,%d)", iregWriteFirst, cregWrite));
          if (enabledReadMode)
            message.append(
                String.format(
                    "| setRead(0x%02x,%d)", readWindow.getIregFirst(), readWindow.getCreg()));

          log(Log.DEBUG, message.toString());
        }

        // ----------------------------------------------------------------------------------
        // Notify anyone blocked in read() or write()
        callbackLock.notifyAll();
      }
    }