예제 #1
0
        internal void CreateNewBatchAndExecutePreviousIfNeeded(RequestBatch <BatchReturnType, RequestResponseType, RequestArgumentType> previousBatch)
        {
            if (previousBatch == null)
            {
                throw new InvalidOperationException("Trying to start null batch which means it was shutdown already.");
            }

            if (Batch.CompareAndSet(previousBatch, new RequestBatch <BatchReturnType, RequestResponseType, RequestArgumentType>(Properties, _commandCollapser, Properties.MaxRequestsInBatch)))
            {
                previousBatch.ExecuteBatchIfNotAlreadyStarted();
            }
        }
예제 #2
0
        public void Shutdown()
        {
            RequestBatch <BatchReturnType, RequestResponseType, RequestArgumentType> currentBatch = batch.GetAndSet(null);

            if (currentBatch != null)
            {
                currentBatch.Shutdown();
            }

            if (timerListenerReference.Value != null)
            {
                // if the timer was started we'll clear it so it stops ticking
                timerListenerReference.Value.Dispose();
            }
        }
예제 #3
0
        public void Tick()
        {
            try
            {
                // we fetch current so that when multiple threads race
                // we can do compareAndSet with the expected/new to ensure only one happens
                RequestBatch <BatchReturnType, ResponseType, RequestArgumentType> currentBatch = rq.Batch.Value;

                // 1) it can be null if it got shutdown
                // 2) we don't execute this batch if it has no requests and let it wait until next tick to be executed
                if (currentBatch != null && currentBatch.Size > 0)
                {
                    // do execution within context of wrapped Callable
                    rq.CreateNewBatchAndExecutePreviousIfNeeded(currentBatch);
                }
            }
            catch (Exception)
            {
                // logger.error("Error occurred trying to execute callable inside CollapsedTask from Timer.", e);
            }
        }
예제 #4
0
        public CollapsedRequest <RequestResponseType, RequestArgumentType> SubmitRequest(RequestArgumentType arg, CancellationToken token)
        {
            /*
             * We only want the timer ticking if there are actually things to do so we register it the first time something is added.
             */
            if (!timerListenerRegistered.Value && timerListenerRegistered.CompareAndSet(false, true))
            {
                /* schedule the collapsing task to be executed every x milliseconds (x defined inside CollapsedTask) */
                timerListenerReference.Value = timer.AddListener(new CollapsedTask <BatchReturnType, RequestResponseType, RequestArgumentType>(this));
            }

            // loop until succeed (compare-and-set spin-loop)
            while (true)
            {
                RequestBatch <BatchReturnType, RequestResponseType, RequestArgumentType> b = batch.Value;
                if (b == null)
                {
                    throw new InvalidOperationException("Submitting requests after collapser is shutdown");
                }

                CollapsedRequest <RequestResponseType, RequestArgumentType> response = b.Offer(arg, token);

                // it will always get an CollapsedRequest unless we hit the max batch size
                if (response != null)
                {
                    return(response);
                }
                else
                {
                    // this batch can't accept requests so create a new one and set it if another thread doesn't beat us
                    CreateNewBatchAndExecutePreviousIfNeeded(b);
                }
            }
        }