/* * 作成日: 2008/06/12 */ package jp.ac.fit.asura.nao.strategy.schedulers; import java.util.LinkedList; import java.util.Queue; import javax.management.ImmutableDescriptor; import jp.ac.fit.asura.nao.RobotContext; import jp.ac.fit.asura.nao.strategy.StrategyContext; import jp.ac.fit.asura.nao.strategy.Task; import org.apache.log4j.Logger; /** * * 基本的な処理を実装しているスケジューラ. * * Queueを元にタスクを実行/切り替えします. * * @author $Author: sey $ * * @version $Id: BasicSchedulerTask.java 709 2008-11-23 07:40:31Z sey $ * */ public abstract class BasicSchedulerTask extends Scheduler { private Logger log = Logger.getLogger(BasicSchedulerTask.class); protected LinkedList<Task> queue; protected int timeToLive; protected Task currentTask; public BasicSchedulerTask() { queue = new LinkedList<Task>(); } public void enter(StrategyContext context) { queue.clear(); timeToLive = 0; currentTask = null; } public void init(RobotContext context) { } public void leave(StrategyContext context) { queue.clear(); timeToLive = 0; currentTask = null; } public void continueTask(StrategyContext context) { if (timeToLive <= 0) { switchTask(context); return; } currentTask.continueTask(context); timeToLive--; } /** * タスクの切替処理. * * 実行キューに待ち状態のタスクがある場合は切り替える. * * キューが空の場合は{@link #fillQueue(StrategyContext)} を呼び出し,次のタスクを決定する. * * @param context */ private void switchTask(StrategyContext context) { Task next = null; // 実行キューからタスクを取り出す while (!queue.isEmpty()) { Task task = queue.removeFirst(); assert task != null; if (task.canExecute(context)) { next = task; break; } } // 次のタスクがなければfillQueue if (next == null) { fillQueue(context); assert !queue.isEmpty(); next = queue.removeFirst(); } // 現在実行中のタスクを終了 if (currentTask != null) { currentTask.leave(context); } // 次のタスクに切り替える. TTLの初期値は1 currentTask = next; timeToLive = 1; log.info("Scheduler: enter task " + currentTask.getName()); currentTask.enter(context); } /** * このスケジューラのキューにTaskを追加します. * * @param task */ public void pushQueue(Task task) { assert task != null; queue.add(task); } /** * このスケジューラのキューに入っているタスクをすべて削除します. * * すでに実行中のタスクはそのまま継続されます. */ public void clearQueue() { queue.clear(); } /** * 現在実行しているタスクを中断します. 実行キューはそのまま. * * @see #clearQueue() */ public void abort() { timeToLive = 0; } /** * 実行中のタスクを停止し,キューにTaskを割り込ませます. */ public void preempt(Task task) { abort(); queue.clear(); queue.addFirst(task); } /** * 実行キューを返します. * * このキューを変更するべきではありません. */ @Override public Queue<Task> getQueue() { return queue; } /** * 現在実行しているタスクを返します. * * @return 実行中のTask */ public Task getCurrentTask() { return currentTask; } /** * 現在実行しているタスクの残り時間(Time to live)を返します. * * @return */ public int getTTL() { return timeToLive; } /** * 現在実行しているタスクの残り時間を設定します. * * 0に設定した場合は,タスクの実行を中断します. */ public void setTTL(int ttl) { timeToLive = ttl; } abstract protected void fillQueue(StrategyContext context); }