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

com.github.libxjava.concurrent.AbstractSingleThreadRunner Maven / Gradle / Ivy

The newest version!
/*
 * libxjava -- utility library for cross-Java-platform development
 *             Lib-Cross-Java CDC
 *
 * Copyright (c) 2010 Marcel Patzlaff ([email protected])
 *
 * This library is free software: you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library 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 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see .
 */

package com.github.libxjava.concurrent;


/**
 * @author Marcel Patzlaff
 * @version libxjava-cdc - 0.3
 */
public abstract class AbstractSingleThreadRunner {
    public final static byte STARTED= 0x01;
    public final static byte STOPPED= 0x02;
    
    private final static byte TRANSITION= 0x10;
    private final static byte STARTING= TRANSITION | STARTED;
    private final static byte STOPPING= TRANSITION | STOPPED;
    
    private final class Executor implements Runnable {
        protected final String name;
        
        private Thread _workThread;
        private final Object _mutex;
        private int _state;
        
        Executor(String name) {
            _mutex= new Object();
            this.name= name == null ? AbstractSingleThreadRunner.this.getClass().getName() : name;
            _state= STOPPED;
        }

        public void run() {
            synchronized (_mutex) {
                _workThread= Thread.currentThread();
                _state= STARTED;
                _mutex.notifyAll();
            }
            
            try {
                doRun();
            } finally {
                synchronized (_mutex) {
                    _state= STOPPED;
                    _workThread= null;
                    _mutex.notifyAll();
                }
            }
        }
        
        boolean start() {
            synchronized (_mutex) {
                if(_state == STOPPED) {
                    _state= STARTING;
                    
                    forkExecution(this, name);
                    return true;
                }
            }
            
            return false;
        }
        
        boolean stop() {
            synchronized (_mutex) {
                if(_state == STARTED) {
                    _state= STOPPING;
                    unblock();
                    return true;
                }
            }
            
            return false;
        }
        
        void interrupt() {
            synchronized (_mutex) {
                if(_workThread != null) {
                    _workThread.interrupt();
                }
            }
        }
        
        boolean isInState(byte requiredState) {
            synchronized (_mutex) {
                return _state == requiredState;
            }
        }
        
        boolean waitForState(final long timeout, final byte requiredState) throws InterruptedException {
            final long start= System.currentTimeMillis();
            
            synchronized (_mutex) {
                while(_state != requiredState) {
                    if((_state & TRANSITION) <= 0 || Thread.currentThread() == _workThread) {
                        return false;
                    }
                    
                    long toWait= timeout - (System.currentTimeMillis() - start);
                    if(toWait > 0) {
                        _mutex.wait(toWait);
                    } else {
                        throw new InterruptedException("timed out");
                    }
                }
            }
            
            return true;
        }
    }
    
    private final Executor _executor;
    
    protected AbstractSingleThreadRunner(String name) {
        _executor= new Executor(name);
    }
    
    public final String getName() {
        return _executor.name;
    }
    
    public final boolean start() {
        return _executor.start();
    }
    
    public final boolean stop() {
        return _executor.stop();
    }
    
    public final boolean isInState(byte requiredState) {
        return _executor.isInState(requiredState);
    }
    
    public final boolean waitForState(int timeout, byte requiredState) throws InterruptedException {
        return _executor.waitForState(timeout, requiredState);
    }
    
    protected abstract void doRun();
    
    /**
     * This method is called on behalf of the {@link #start()} method.
     * It must set up the concurrent execution of the specified runnable.
     * 

* The default implementation just creates a new thread and starts it. *

* @param runnable to execute in a concurrent thread * @param name an optional name for the thread */ protected void forkExecution(Runnable runnable, String name) { new Thread(runnable, name).start(); } /** * This method is called on behalf of the {@link #stop()} method. *

* If the runner performs blocking operations like I/O reads or * synchronized waits, the implementing class should unblock/notify * the runner in this method. *

*

* The default implementation just signals interruption to the * working thread *

* */ protected void unblock() { _executor.interrupt(); } protected final boolean isCancelled() { return _executor.isInState(STOPPING); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy