/*_########################################################################## _## _## Copyright (C) 2012 Kaito Yamada _## _########################################################################## */ package com.github.kaitoy.sneo.util; import java.util.HashMap; import java.util.Map; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; import java.util.concurrent.TimeUnit; import org.snmp4j.log.LogAdapter; import org.snmp4j.log.LogFactory; import org.snmp4j.util.WorkerPool; import org.snmp4j.util.WorkerTask; public class ContextfulWorkerPool<T> implements WorkerPool { private static final LogAdapter logger = LogFactory.getLogger(ContextfulWorkerPool.class.getPackage().getName()); private static final long SHUTDOWN_TIMEOUT = 2000; private static final TimeUnit SHUTDOWN_TIMEOUT_UNIT = TimeUnit.MILLISECONDS; private final Map<Thread, T> contextHolder = new HashMap<Thread, T>(); private final ExecutorService executer; public ContextfulWorkerPool(String prefix, int numWorker) { executer = Executors.newFixedThreadPool( numWorker, new NamedThreadFactory(prefix, true) ); } public void registerContext(T context) { contextHolder.put(Thread.currentThread(), context); } public T unregisterContext() { return contextHolder.remove(Thread.currentThread()); } public void execute(final WorkerTask task) { T context = contextHolder.remove(Thread.currentThread()); executer.submit( new ContextfulWorkerTask(task, context) ); } public boolean tryToExecute(WorkerTask task) { execute(task); return true; } public void stop() { executer.shutdown(); try { boolean terminated = executer.awaitTermination(SHUTDOWN_TIMEOUT, SHUTDOWN_TIMEOUT_UNIT); if (!terminated) { logger.warn("Termination timeout occured."); } } catch (InterruptedException e) { logger.warn("Termination was interrupted."); } } public void cancel() { executer.shutdownNow(); } public boolean isIdle() { return true; } private class ContextfulWorkerTask implements Runnable { private final WorkerTask task; private final T context; private ContextfulWorkerTask(WorkerTask task, T context) { this.task = task; this.context = context; } public void run() { if (context != null) { contextHolder.put( Thread.currentThread(), context ); } task.run(); } } }