001/* 002 * This file is part of the Kompics component model runtime. 003 * <p> 004 * Copyright (C) 2009 Swedish Institute of Computer Science (SICS) 005 * Copyright (C) 2009 Royal Institute of Technology (KTH) 006 * 007 * Kompics is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU General Public License 009 * as published by the Free Software Foundation; either version 2 010 * of the License, or (at your option) any later version. 011 * 012 * This program is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 015 * GNU General Public License for more details. 016 * 017 * You should have received a copy of the GNU General Public License 018 * along with this program; if not, write to the Free Software 019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 020 */ 021package se.sics.kompics.timer.java; 022 023import java.util.HashMap; 024import java.util.UUID; 025import org.slf4j.Logger; 026import se.sics.kompics.ComponentDefinition; 027import se.sics.kompics.Handler; 028import se.sics.kompics.Negative; 029import se.sics.kompics.timer.CancelPeriodicTimeout; 030import se.sics.kompics.timer.CancelTimeout; 031import se.sics.kompics.timer.SchedulePeriodicTimeout; 032import se.sics.kompics.timer.ScheduleTimeout; 033import se.sics.kompics.timer.Timeout; 034import se.sics.kompics.timer.Timer; 035 036/** 037 * The <code>JavaTimer</code> class. 038 * <p> 039 * 040 * @author Cosmin Arad {@literal <[email protected]>} 041 * @author Jim Dowling {@literal <[email protected]>} 042 * @version $Id$ 043 */ 044public final class JavaTimer extends ComponentDefinition { 045 046 Negative<Timer> timer = negative(Timer.class); 047 048 final Logger extLogger = this.logger; 049 050 // set of active timers 051 private final HashMap<UUID, TimerSignalTask> activeTimers; 052 053 // set of active periodic timers 054 private final HashMap<UUID, PeriodicTimerSignalTask> activePeriodicTimers; 055 056 private final java.util.Timer javaTimer; 057 private final JavaTimer timerComponent; 058 059 /** 060 * Instantiates a new java timer. 061 */ 062 public JavaTimer() { 063 this.activeTimers = new HashMap<UUID, TimerSignalTask>(); 064 this.activePeriodicTimers = new HashMap<UUID, PeriodicTimerSignalTask>(); 065 this.javaTimer = new java.util.Timer("JavaTimer@" + Integer.toHexString(this.hashCode()), true); 066 timerComponent = this; 067 068 subscribe(handleST, timer); 069 subscribe(handleSPT, timer); 070 subscribe(handleCT, timer); 071 subscribe(handleCPT, timer); 072 } 073 074 Handler<ScheduleTimeout> handleST = new Handler<ScheduleTimeout>() { 075 public void handle(ScheduleTimeout event) { 076 UUID id = event.getTimeoutEvent().getTimeoutId(); 077 078 TimerSignalTask timeOutTask = new TimerSignalTask(timerComponent, event.getTimeoutEvent(), id); 079 080 synchronized (activeTimers) { 081 activeTimers.put(id, timeOutTask); 082 } 083 try { 084 javaTimer.schedule(timeOutTask, event.getDelay()); 085 logger.debug("scheduled timer({}) {}", event.getDelay(), timeOutTask.timeout); 086 } catch (IllegalStateException e) { 087 logger.error("Could not schedule timer {}.", event.getDelay(), timeOutTask.timeout); 088 e.printStackTrace(); 089 } 090 } 091 }; 092 093 Handler<SchedulePeriodicTimeout> handleSPT = new Handler<SchedulePeriodicTimeout>() { 094 public void handle(SchedulePeriodicTimeout event) { 095 UUID id = event.getTimeoutEvent().getTimeoutId(); 096 097 PeriodicTimerSignalTask timeOutTask = new PeriodicTimerSignalTask(event.getTimeoutEvent(), timerComponent); 098 099 synchronized (activePeriodicTimers) { 100 activePeriodicTimers.put(id, timeOutTask); 101 } 102 javaTimer.scheduleAtFixedRate(timeOutTask, event.getDelay(), event.getPeriod()); 103 logger.debug("scheduled periodic timer({}, {}) {}", 104 new Object[] { event.getDelay(), event.getPeriod(), timeOutTask.timeout }); 105 } 106 }; 107 108 Handler<CancelTimeout> handleCT = new Handler<CancelTimeout>() { 109 public void handle(CancelTimeout event) { 110 UUID id = event.getTimeoutId(); 111 112 TimerSignalTask task = null; 113 synchronized (activeTimers) { 114 task = activeTimers.get(id); 115 if (task != null) { 116 task.cancel(); 117 activeTimers.remove(id); 118 logger.debug("canceled timer {}", task.timeout); 119 } 120 } 121 } 122 }; 123 124 Handler<CancelPeriodicTimeout> handleCPT = new Handler<CancelPeriodicTimeout>() { 125 public void handle(CancelPeriodicTimeout event) { 126 UUID id = event.getTimeoutId(); 127 128 PeriodicTimerSignalTask task = null; 129 task = activePeriodicTimers.get(id); 130 if (task != null) { 131 task.cancel(); 132 activePeriodicTimers.remove(id); 133 logger.debug("canceled periodic timer {}", task.timeout); 134 } 135 136 } 137 }; 138 139 // called by the timeout task 140 /** 141 * Timeout. 142 * <p> 143 * 144 * @param timerId 145 * the timer id 146 * @param timeout 147 * the timeout 148 */ 149 final void timeout(UUID timerId, Timeout timeout) { 150 synchronized (activeTimers) { 151 activeTimers.remove(timerId); 152 } 153 logger.debug("trigger timeout {}", timeout); 154 trigger(timeout, timer); 155 } 156 157 // called by the periodic timeout task 158 /** 159 * Periodic timeout. 160 * <p> 161 * 162 * @param timeout 163 * the timeout 164 */ 165 final void periodicTimeout(Timeout timeout) { 166 logger.debug("trigger periodic timeout {}", timeout); 167 trigger(timeout, timer); 168 } 169 170 @Override 171 public void tearDown() { 172 synchronized (activeTimers) { 173 for (TimerSignalTask tst : activeTimers.values()) { 174 tst.cancel(); 175 } 176 activeTimers.clear(); 177 } 178 for (PeriodicTimerSignalTask ptst : activePeriodicTimers.values()) { 179 ptst.cancel(); 180 } 181 activePeriodicTimers.clear(); 182 javaTimer.cancel(); 183 } 184}