public WindowFuture offer()

in ch-commons-util/src/main/java/com/cloudhopper/commons/util/windowing/Window.java [359:411]


    public WindowFuture offer(K key, R request, long offerTimeoutMillis, long expireTimeoutMillis, boolean callerWaitingHint) throws DuplicateKeyException, OfferTimeoutException, PendingOfferAbortedException, InterruptedException {
        if (offerTimeoutMillis < 0) {
            throw new IllegalArgumentException("offerTimeoutMillis must be >= 0 [actual=" + offerTimeoutMillis + "]");
        }
        
        // does this key already exist?
        if (this.futures.containsKey(key)) {
            throw new DuplicateKeyException("The key [" + key + "] already exists in the window");
        }

        long offerTimestamp = System.currentTimeMillis();
        
        this.lock.lockInterruptibly();
        try {
            // does enough room exist in the "window" for another pending request?
            // NOTE: wait for room up to the offerTimeoutMillis
            // NOTE: multiple signals may be received that will need to be ignored
            while (getFreeSize() <= 0) {
                // check if there time remaining to wait
                long currentOfferTime = System.currentTimeMillis() - offerTimestamp;
                if (currentOfferTime >= offerTimeoutMillis) {
                    throw new OfferTimeoutException("Unable to accept offer within [" + offerTimeoutMillis + " ms] (window full)");
                }
                
                // check if slow waiting was canceled (terminate early)
                if (this.pendingOffersAborted.get()) {
                    throw new PendingOfferAbortedException("Pending offer aborted (by an explicit call to abortPendingOffers())");
                }
                
                // calculate the amount of timeout remaining
                long remainingOfferTime = offerTimeoutMillis - currentOfferTime;
                try {
                    // await for a new signal for this max amount of time
                    this.beginPendingOffer();
                    this.completedCondition.await(remainingOfferTime, TimeUnit.MILLISECONDS);
                } finally {
                    boolean abortPendingOffer = this.endPendingOffer();
                    if (abortPendingOffer) {
                        throw new PendingOfferAbortedException("Pending offer aborted (by an explicit call to abortPendingOffers())");
                    }
                }
            }
            
            long acceptTimestamp = System.currentTimeMillis();
            long expireTimestamp = (expireTimeoutMillis > 0 ? (acceptTimestamp + expireTimeoutMillis) : -1);
            int callerStateHint = (callerWaitingHint ? WindowFuture.CALLER_WAITING : WindowFuture.CALLER_NOT_WAITING);
            DefaultWindowFuture<K,R,P> future = new DefaultWindowFuture<K,R,P>(this, lock, completedCondition, key, request, callerStateHint, offerTimeoutMillis, (futures.size() + 1), offerTimestamp, acceptTimestamp, expireTimestamp);
            this.futures.put(key, future);
            return future;
        } finally {
            this.lock.unlock();
        }
    }