All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.util.concurrent.AsyncCompletionService Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.util.concurrent;

import java.util.PriorityQueue;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;

/**
 * A completion service that orders the completed tasks in the same order as they where submitted.
 */
public class AsyncCompletionService {

    private final Executor executor;
    private final boolean ordered;
    private final PriorityQueue queue;
    private final AtomicInteger nextId = new AtomicInteger();
    private final AtomicInteger index = new AtomicInteger();
    private final ReentrantLock lock;
    private final Condition available;

    public AsyncCompletionService(Executor executor, boolean ordered) {
        this(executor, ordered, null, 0);
    }

    public AsyncCompletionService(Executor executor, boolean ordered, ReentrantLock lock) {
        this(executor, ordered, lock, 0);
    }

    public AsyncCompletionService(Executor executor, boolean ordered, ReentrantLock lock, int capacity) {
        this.executor = executor;
        this.ordered = ordered;
        this.lock = lock != null ? lock : new ReentrantLock();
        this.available = this.lock.newCondition();
        if (capacity > 0) {
            queue = new PriorityQueue<>(capacity);
        } else {
            queue = new PriorityQueue<>();
        }
    }

    public ReentrantLock getLock() {
        return lock;
    }

    public void submit(Consumer> runner) {
        Task f = new Task(nextId.getAndIncrement(), runner);
        this.executor.execute(f);
    }

    public void skip() {
        index.incrementAndGet();
    }

    public V pollUnordered() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Task t = queue.poll();
            return t != null ? t.result : null;
        } finally {
            lock.unlock();
        }
    }

    public V poll() {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Task t = queue.peek();
            if (t != null && (!ordered || index.compareAndSet(t.id, t.id + 1))) {
                queue.poll();
                return t.result;
            } else {
                return null;
            }
        } finally {
            lock.unlock();
        }
    }

    public V poll(long timeout, TimeUnit unit) throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                Task t = queue.peek();
                if (t != null && (!ordered || index.compareAndSet(t.id, t.id + 1))) {
                    queue.poll();
                    return t.result;
                }
                if (nanos <= 0) {
                    return null;
                } else {
                    nanos = available.awaitNanos(nanos);
                }
            }
        } finally {
            lock.unlock();
        }
    }

    public V take() throws InterruptedException {
        final ReentrantLock lock = this.lock;
        lock.lockInterruptibly();
        try {
            for (;;) {
                Task t = queue.peek();
                if (t != null && (!ordered || index.compareAndSet(t.id, t.id + 1))) {
                    queue.poll();
                    return t.result;
                }
                available.await();
            }
        } finally {
            lock.unlock();
        }
    }

    private void complete(Task task) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            queue.add(task);
            available.signalAll();
        } finally {
            lock.unlock();
        }
    }

    private class Task implements Runnable, Comparable, Consumer {
        private final int id;
        private final Consumer> runner;
        private V result;

        Task(int id, Consumer> runner) {
            this.id = id;
            this.runner = runner;
        }

        @Override
        public void run() {
            runner.accept(this);
        }

        @Override
        public void accept(V result) {
            this.result = result;
            complete(this);
        }

        @Override
        public int compareTo(Task other) {
            return Integer.compare(this.id, other.id);
        }

        @Override
        public String toString() {
            return "SubmitOrderedTask[" + this.id + "]";
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy