/** Initializes a random variable */ private void createRandom() { this.random = new Random( System.currentTimeMillis() + Thread.currentThread().getId() - Thread.currentThread().hashCode() + this.cname.hashCode()); }
/** * 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(); } }
/** * 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(); } }
// 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; }
@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); } }
// 提供一个线程安全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(); } }
/** * 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(); }
/** * 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); } }
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(); } }