/* * Copyright 1999-2006 University of Chicago * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.dcache.ftp.client.dc; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class TaskThread implements Runnable { static final int MAX_TASK_QUEUE = 100; protected static final Logger logger = LoggerFactory.getLogger(TaskThread.class); protected final Buffer buffer; protected boolean stop; protected Thread thread; public TaskThread() { buffer = new Buffer(MAX_TASK_QUEUE); } public synchronized void start() { if (thread == null) { thread = new Thread(this); thread.setName("Task" + thread.getName()); thread.setDaemon(true); thread.start(); } } public void runTask(Task task) { start(); try { buffer.put(task); } catch (Exception e) { } } public Task getNextTask() { try { return (Task) buffer.get(); } catch (Exception e) { return null; } } @Override public void run() { stop = false; Exception exception; Task task; while (!stop) { task = getNextTask(); if (task == null) break; exception = null; try { logger.debug("executing task: " + task.toString()); task.execute(); logger.debug("finished task: " + task.toString()); } catch (Exception e) { exception = e; } task.setComplete(exception); } } public synchronized void stop() { stop = true; buffer.release(); } public void join() { if (thread != null) { try { thread.join(); } catch (InterruptedException e) { } } } class Buffer { protected final Object[] buf; protected int in = 0; protected int out = 0; protected int count = 0; protected final int size; public Buffer(int size) { this.size = size; buf = new Object[size]; } public synchronized void put(Object o) throws InterruptedException { while (count == size) { wait(); if (stop) return; } buf[in] = o; ++count; in = (in + 1) % size; notify(); } public synchronized Object get() throws InterruptedException { while (count == 0) { wait(); if (stop) return null; } Object o = buf[out]; buf[out] = null; --count; out = (out + 1) % size; notify(); return (o); } public synchronized void release() { notify(); } } }