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

uk.co.caprica.vlcj.support.eventmanager.TaskExecutor Maven / Gradle / Ivy

There is a newer version: 5.0.0-M1
Show newest version
/*
 * This file is part of VLCJ.
 *
 * VLCJ is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VLCJ is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with VLCJ.  If not, see .
 *
 * Copyright 2009-2019 Caprica Software Limited.
 */

package uk.co.caprica.vlcj.support.eventmanager;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

/**
 * Singleton component used to execute tasks on a thread different to the native event handler background thread.
 * 

* Native events are generated on a native event callback thread. It is not allowed to call back into LibVLC from this * thread, if you do either the call will be ineffective, strange behaviour will happen, or a fatal JVM crash may occur. *

* To mitigate this, tasks can be submitted, serialised and executed using this service. *

* Internally a single-threaded executor service is used to execute tasks that need to be off-loaded from a native * callback thread. *

* See {@link #submit(Runnable)}. */ public final class TaskExecutor { /** * Default timeout to use when waiting for scheduled tasks to complete during shutdown. *

* The same timeout is used twice, first waiting for a clean shutdown then again waiting after forcing a shutdown if * necessary. */ private static final long DEFAULT_TIMEOUT = 5000; /** * Single-threaded service to execute tasks that need to be off-loaded from a native callback thread. *

* Native events are generated on a native event callback thread. It is not allowed to call back into LibVLC from * this thread, if you do either the call will be ineffective, strange behaviour will happen, or a fatal JVM crash * may occur. *

* To mitigate this, tasks can be serialised and executed using this service. *

* See {@link #submit(Runnable)}. */ private final ExecutorService executor = Executors.newSingleThreadExecutor(); /** * Submit a task for asynchronous execution. * * @param r task to submit */ public void submit(Runnable r) { executor.submit(r); } /** * Release this component. *

* An attempt is made to perform an orderly shutdown, so any tasks in the queue are given a chance to complete * cleanly within the default timeout period. *

* Consequently there may be a short delay before this method returns. *

* If there are no tasks waiting, this method will return immediately. */ public void release() { shutdownExecutor(DEFAULT_TIMEOUT); } /** * Release this component. *

* An attempt is made to perform an orderly shutdown, so any tasks in the queue are given a chance to complete * cleanly within the specified timeout period. *

* Consequently there may be a short delay before this method returns. *

* If there are no tasks waiting, this method will return immediately. * * @param timeout timeout, milliseconds */ public void release(long timeout) { shutdownExecutor(timeout); } /** * Shutdown the task executor service. *

* Care must be taken to prevent fatal JVM crashes during shutdown due to tasks that may be still be waiting in the * queue to be executed (e.g. we do not want to destroy the native media player if a task is running that is going * to invoke a call on the native media player). *

* So, we first shutdown the executor service then await termination of all tasks. If there are no pending tasks we * will terminate immediately as normal. If there are tasks, we wait for a short timeout period before forcing a * termination anyway. *

* We should never really be waiting any significant amount of time for the queued tasks to terminate because they * will be very few in number, and should execute very quickly anyway. Even the short wait before timeout may be * useful to avoid any hard crashes during clean-up. */ private void shutdownExecutor(long timeout) { // Immediately stop accepting new tasks executor.shutdown(); try { // Give a chance for all existing tasks to complete cleanly if (!executor.awaitTermination(timeout, TimeUnit.MILLISECONDS)) { // Not all tasks completed cleanly in time, so force a shutdown executor.shutdownNow(); executor.awaitTermination(timeout, TimeUnit.MILLISECONDS); } } catch (InterruptedException e) { executor.shutdownNow(); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy