/*
* Copyright (c) 2011-2013 The original author or authors
* ------------------------------------------------------
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* The Apache License v2.0 is available at
* http://www.opensource.org/licenses/apache2.0.php
*
* You may elect to redistribute this code under either of these licenses.
*/
package io.vertx.core.impl;
import io.vertx.core.logging.Logger;
import io.vertx.core.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);
// @protectedby tasks
private final LinkedList<Runnable> tasks = new LinkedList<>();
// @protectedby tasks
private boolean running;
private final Runnable runner;
public TaskQueue() {
runner = () -> {
for (; ; ) {
final Runnable task;
synchronized (tasks) {
task = tasks.poll();
if (task == null) {
running = false;
return;
}
}
try {
task.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(task);
if (!running) {
running = true;
executor.execute(runner);
}
}
}
}