/* * 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); } } } }