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

com.emc.mongoose.api.model.concurrent.DaemonBase Maven / Gradle / Ivy

There is a newer version: 4.0.0-alpha5
Show newest version
package com.emc.mongoose.api.model.concurrent;

import com.github.akurilov.coroutines.CoroutinesProcessor;

import static com.emc.mongoose.api.model.concurrent.Daemon.State.CLOSED;
import static com.emc.mongoose.api.model.concurrent.Daemon.State.INITIAL;
import static com.emc.mongoose.api.model.concurrent.Daemon.State.INTERRUPTED;
import static com.emc.mongoose.api.model.concurrent.Daemon.State.SHUTDOWN;
import static com.emc.mongoose.api.model.concurrent.Daemon.State.STARTED;

import java.io.IOException;
import java.rmi.RemoteException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 Created on 12.07.16.
 */
public abstract class DaemonBase
implements Daemon {

	private static final Logger LOG = Logger.getLogger(DaemonBase.class.getName());
	protected static final CoroutinesProcessor SVC_EXECUTOR = new CoroutinesProcessor();

	public static void setThreadCount(final int threadCount) {
		SVC_EXECUTOR.setThreadCount(threadCount);
	}

	private static final Queue REGISTRY = new ConcurrentLinkedQueue<>();
	
	private AtomicReference stateRef = new AtomicReference<>(INITIAL);
	protected final Object state = new Object();

	protected DaemonBase() {
		REGISTRY.add(this);
	}
	
	@Override
	public final State getState() {
		return stateRef.get();
	}

	protected abstract void doStart()
	throws IllegalStateException;

	protected abstract void doShutdown()
	throws IllegalStateException;

	protected abstract void doInterrupt()
	throws IllegalStateException;

	protected abstract void doClose()
	throws IllegalStateException, IOException;

	@Override
	public final void start()
	throws IllegalStateException {
		if(stateRef.compareAndSet(INITIAL, STARTED)) {
			synchronized(state) {
				state.notifyAll();
			}
			doStart();
		} else {
			throw new IllegalStateException("start failed: state is " + stateRef.get());
		}
	}

	@Override
	public final boolean isStarted() {
		return stateRef.get().equals(STARTED);
	}

	@Override
	public final synchronized void shutdown()
	throws IllegalStateException {
		if(stateRef.compareAndSet(INITIAL, SHUTDOWN) || stateRef.compareAndSet(STARTED, SHUTDOWN)) {
			synchronized(state) {
				state.notifyAll();
			}
			doShutdown();
		} else {
			throw new IllegalStateException("shutdown failed: state is " + stateRef.get());
		}
	}

	@Override
	public final boolean isShutdown() {
		return stateRef.get().equals(SHUTDOWN);
	}
	
	@Override
	public final void await()
	throws InterruptedException, RemoteException {
		await(Long.MAX_VALUE, TimeUnit.SECONDS);
	}
	
	@Override
	public final synchronized void interrupt()
	throws IllegalStateException {
		try {
			shutdown();
		} catch(final IllegalStateException ignored) {
		}
		if(stateRef.compareAndSet(SHUTDOWN, INTERRUPTED)) {
			synchronized(state) {
				state.notifyAll();
			}
			doInterrupt();
		} else {
			throw new IllegalStateException("interrupt failed: state is " + stateRef.get());
		}
	}

	@Override
	public final boolean isInterrupted() {
		return stateRef.get().equals(INTERRUPTED);
	}
	
	@Override
	public final synchronized void close()
	throws IOException, IllegalStateException {
		try {
			interrupt();
		} catch(final IllegalStateException ignored) {
		}
		REGISTRY.remove(this);
		if(stateRef.compareAndSet(INTERRUPTED, CLOSED)) {
			synchronized(state) {
				state.notifyAll();
			}
			doClose();
			// may be closed by another thread right after the interruption
		} else if(!CLOSED.equals(stateRef.get())) {
			throw new IllegalStateException("close failed: state is " + stateRef.get());
		}
	}
	
	@Override
	public final boolean isClosed() {
		return stateRef.get().equals(CLOSED);
	}

	public static void closeAll() {
		while(!REGISTRY.isEmpty()) {
			try {
				REGISTRY.poll().close();
			} catch(final Throwable cause) {
				LOG.log(Level.WARNING, "Failed to close the daemon instance", cause);
			}
		}
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy