PoolFiber.java :  » Messenger » jetlang » org » jetlang » fibers » Java Open Source

Java Open Source » Messenger » jetlang 
jetlang » org » jetlang » fibers » PoolFiber.java
package org.jetlang.fibers;

import org.jetlang.core.*;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * Fiber that uses a thread pool for execution.
 *
 * @author mrettig
 */
class PoolFiber implements Fiber {
    private final AtomicBoolean _flushPending = new AtomicBoolean(false);
    private final EventQueue _queue = new RunnableBlockingQueue();
    private final Executor _flushExecutor;
    private final AtomicReference<ExecutionState> _started = new AtomicReference<ExecutionState>(ExecutionState.Created);
    private final BatchExecutor _commandExecutor;
    private final Collection<Disposable> _disposables = Collections.synchronizedList(new ArrayList<Disposable>());
    private final SchedulerImpl _scheduler;
    private final Runnable _flushRunnable;
    private EventBuffer buffer = new EventBuffer();

    public PoolFiber(Executor pool, BatchExecutor executor, ScheduledExecutorService scheduler) {
        _flushExecutor = pool;
        _commandExecutor = executor;
        _scheduler = new SchedulerImpl(this, scheduler);
        _flushRunnable = new Runnable() {
            public void run() {
                flush();
            }
        };
    }

    public void execute(Runnable commands) {
        if (_started.get() == ExecutionState.Stopped) {
            return;
        }

        _queue.put(commands);

        if (_started.get() == ExecutionState.Created) {
            return;
        }

        flushIfNotPending();
    }

    private void flushIfNotPending() {
        if (_flushPending.compareAndSet(false, true)) {
            _flushExecutor.execute(_flushRunnable);
        }
    }

    private void flush() {
        buffer = _queue.swap(buffer);
        _commandExecutor.execute(buffer);
        buffer.clear();

        _flushPending.compareAndSet(true, false);

        if (!_queue.isEmpty()) {
            flushIfNotPending();
        }
    }

    public void start() {
        ExecutionState state = _started.get();

        if (state == ExecutionState.Running) {
            throw new RuntimeException("Already Started");
        }

        if (_started.compareAndSet(state, ExecutionState.Running)) {
            execute(new Runnable() {
                public void run() {
                    //flush any pending events in execute
                }
            });
        }
    }

    public void dispose() {
        _started.set(ExecutionState.Stopped);
        synchronized (_disposables) {
            //copy list to prevent concurrent mod
            for (Disposable r : _disposables.toArray(new Disposable[_disposables.size()])) {
                r.dispose();
            }
        }
    }

    public void add(Disposable runOnStop) {
        _disposables.add(runOnStop);
    }

    public boolean remove(Disposable disposable) {
        return _disposables.remove(disposable);
    }

    public int size() {
        return _disposables.size();
    }

    public Disposable schedule(Runnable command, long delay, TimeUnit unit) {
        return _scheduler.schedule(command, delay, unit);
    }

    public Disposable scheduleAtFixedRate(Runnable command, long initialDelay, long delay, TimeUnit unit) {
        return register(_scheduler.scheduleAtFixedRate(command, initialDelay, delay, unit));
    }

    public Disposable scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
        return register(_scheduler.scheduleWithFixedDelay(command, initialDelay, delay, unit));
    }

    private Disposable register(final Disposable stopper) {
        Disposable wrapper = new Disposable() {
            public void dispose() {
                stopper.dispose();
                remove(this);
            }
        };
        //scheduler is shared so tasks removed individually
        add(wrapper);
        return wrapper;

    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.