io.vertx.core.impl.TaskQueue.java Source code

Java tutorial

Introduction

Here is the source code for io.vertx.core.impl.TaskQueue.java

Source

/*
 * Copyright (c) 2011-2019 Contributors to the Eclipse Foundation
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 * which is available at https://www.apache.org/licenses/LICENSE-2.0.
 *
 * SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 */

package io.vertx.core.impl;

import io.vertx.core.impl.logging.Logger;
import io.vertx.core.impl.logging.LoggerFactory;

import java.util.LinkedList;
import java.util.concurrent.Executor;

/**
 * A task queue that always run all tasks in order. The executor to run the tasks is passed when
 * the tasks when the tasks are executed, this executor is not guaranteed to be used, as if several
 * tasks are queued, the original thread will be used.
 *
 * More specifically, any call B to the {@link #execute(Runnable, Executor)} method that happens-after another call A to the
 * same method, will result in B's task running after A's.
 *
 * @author <a href="david.lloyd@jboss.com">David Lloyd</a>
 * @author <a href="mailto:tim.fox@jboss.com">Tim Fox</a>
 * @author <a href="mailto:julien@julienviet.com">Julien Viet</a>
 */
public class TaskQueue {

    static final Logger log = LoggerFactory.getLogger(TaskQueue.class);

    private static class Task {

        private final Runnable runnable;
        private final Executor exec;

        public Task(Runnable runnable, Executor exec) {
            this.runnable = runnable;
            this.exec = exec;
        }
    }

    // @protectedby tasks
    private final LinkedList<Task> tasks = new LinkedList<>();

    // @protectedby tasks
    private Executor current;

    private final Runnable runner;

    public TaskQueue() {
        runner = this::run;
    }

    private void run() {
        for (;;) {
            final Task task;
            synchronized (tasks) {
                task = tasks.poll();
                if (task == null) {
                    current = null;
                    return;
                }
                if (task.exec != current) {
                    tasks.addFirst(task);
                    task.exec.execute(runner);
                    current = task.exec;
                    return;
                }
            }
            try {
                task.runnable.run();
            } catch (Throwable t) {
                log.error("Caught unexpected Throwable", t);
            }
        }
    };

    /**
     * Run a task.
     *
     * @param task the task to run.
     */
    public void execute(Runnable task, Executor executor) {
        synchronized (tasks) {
            tasks.add(new Task(task, executor));
            if (current == null) {
                current = executor;
                executor.execute(runner);
            }
        }
    }
}