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

org.gstreamer.glib.MainContextExecutorService Maven / Gradle / Ivy

There is a newer version: 1.6
Show newest version
/* 
 * Copyright (c) 2007, 2008 Wayne Meissner
 * 
 * This file is part of gstreamer-java.
 *
 * This code is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Lesser General Public License version 3 only, as
 * published by the Free Software Foundation.
 *
 * This code 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 Lesser General Public License
 * version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with this work.  If not, see .
 */

package org.gstreamer.glib;

import static org.gstreamer.lowlevel.GlibAPI.GLIB_API;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.AbstractExecutorService;
import java.util.concurrent.Callable;
import java.util.concurrent.Delayed;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;

import org.gstreamer.lowlevel.GMainContext;
import org.gstreamer.lowlevel.GSource;

/**
 * Wraps the glib main loop/main context in a ScheduledExecutor interface.
 */
public class MainContextExecutorService extends AbstractExecutorService implements ScheduledExecutorService {
    private final GMainContext context;
    private GSource idleSource = null;
    private final List bgTasks = new LinkedList();
    private volatile boolean running = true;
    
    public MainContextExecutorService(GMainContext context) {
        this.context = context;
    }
    private final Callable idleCallback = new Callable() {

        public Boolean call() throws Exception {
            //            System.out.println("Running g_idle callbacks");
            List tasks = new ArrayList();
            synchronized (bgTasks) {
                tasks.addAll(bgTasks);
                bgTasks.clear();
            }
            for (Runnable r : tasks) {
                r.run();
            }
            return false;
        }
    };
    private void invokeLater(final Runnable r) {
        //        System.out.println("Scheduling idle callbacks");
        synchronized (bgTasks) {
            boolean empty = bgTasks.isEmpty();
            bgTasks.add(r);
            // Only trigger the callback if there were no existing elements in the list
            // otherwise it is already triggered
            if (empty) {
                idleSource = GLIB_API.g_idle_source_new();
                idleSource.setCallback(idleCallback);
                idleSource.attach(context);
            }
        }
    }
    public void shutdown() {
        shutdownNow();
    }

    public List shutdownNow() {
        List tasks = new ArrayList();
        synchronized (bgTasks) {
            tasks.addAll(bgTasks);
            bgTasks.clear();
        }
        return tasks;
    }

    public boolean isShutdown() {
        return !running;
    }

    public boolean isTerminated() {
        synchronized (bgTasks) {
            return !isShutdown() && bgTasks.isEmpty();
        }
    }

    public boolean awaitTermination(long timeout, TimeUnit units) throws InterruptedException {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    public void execute(Runnable runnable) {
        invokeLater(runnable);
    }
    private class ScheduledTimeout extends FutureTask implements ScheduledFuture {
        private volatile GSource source;
        private Callable delayCallback = new Callable() {
            public Boolean call() {
                // Now start the periodic timer
                if (period != 0 && !isCancelled()) {
                    start(period, periodCallback);
                }
                // If periodic, don't bother returning a result
                if (period != 0) {
                    runAndReset();
                } else {
                    run();
                }
                return false;
            }
        };
        private Callable periodCallback = new Callable() {
            public Boolean call() {
                runAndReset();
                return !isCancelled();
            }
        };
        private final long period;
        private final TimeUnit units;
        
        public ScheduledTimeout(Callable call, long delay, TimeUnit units) {
            this(call, delay, 0, units);
        }
        public ScheduledTimeout(Callable call, long delay, long period, TimeUnit units) {
            super(call);

            this.period = period;
            this.units = units;
            start(delay, delayCallback);
        }
        
        private final int getMilliseconds(long time) {
            return (int) units.toMillis(time);
        }
        
        private void start(long timeout, Callable callback) {
            int milliseconds = getMilliseconds(timeout);
            /*
             * If the timeout is a multiple of seconds, use the more efficient
             * g_timeout_add_seconds, if it is available.
             */
            if ((milliseconds % 1000) == 0) {
                try {
                    source = GLIB_API.g_timeout_source_new_seconds(milliseconds / 1000);
                } catch (UnsatisfiedLinkError e) {
                    source = GLIB_API.g_timeout_source_new(milliseconds);
                }
            } else {
                source = GLIB_API.g_timeout_source_new(milliseconds);
            }
            source.setCallback(callback);
            source.attach(context);
        }
        public long getDelay(TimeUnit units) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

        public int compareTo(Delayed delayed) {
            //return delayed.getDelay(TimeUnit.MILLISECONDS)
            throw new UnsupportedOperationException("Not supported yet.");
        }
    }
    public ScheduledFuture schedule(Runnable runnable, long delay, TimeUnit units) {
        return new ScheduledTimeout(Executors.callable(runnable), delay, units);
    }

    public  ScheduledFuture schedule(Callable callable, long delay, TimeUnit units) {
        return new ScheduledTimeout(callable, delay, units);
    }

    public ScheduledFuture scheduleAtFixedRate(Runnable runnable, long initialiDelay, long period, TimeUnit units) {
        return new ScheduledTimeout(Executors.callable(runnable), initialiDelay, period, units);
    }

    public ScheduledFuture scheduleWithFixedDelay(Runnable runnable, long initialiDelay, long delay, TimeUnit units) {
        return new ScheduledTimeout(Executors.callable(runnable), initialiDelay, delay, units);
    }
}