2009-08-17 20:46:05 +02:00
|
|
|
/*
|
|
|
|
|
* Copyright 2007 WorldWide Conferencing, LLC
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
2010-05-21 08:18:56 +02:00
|
|
|
*
|
|
|
|
|
* Rework of David Pollak's ActorPing class in the Lift Project
|
|
|
|
|
* which is licensed under the Apache 2 License.
|
2009-08-17 20:46:05 +02:00
|
|
|
*/
|
2010-10-26 12:49:25 +02:00
|
|
|
package akka.actor
|
2009-08-17 18:42:41 +02:00
|
|
|
|
2010-08-19 07:01:09 +02:00
|
|
|
import scala.collection.JavaConversions
|
2010-08-28 16:48:27 +02:00
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
import java.util.concurrent._
|
2009-09-07 18:41:45 +02:00
|
|
|
|
2011-03-23 15:12:09 +01:00
|
|
|
import akka.event.EventHandler
|
2010-10-26 12:49:25 +02:00
|
|
|
import akka.AkkaException
|
2011-07-09 19:17:49 +02:00
|
|
|
import atomic.AtomicLong
|
2009-08-17 18:42:41 +02:00
|
|
|
|
2011-02-28 22:54:32 +01:00
|
|
|
object Scheduler {
|
2010-05-08 10:04:13 +02:00
|
|
|
import Actor._
|
2010-05-21 20:08:49 +02:00
|
|
|
|
2011-06-23 16:02:35 +02:00
|
|
|
case class SchedulerException(msg: String, e: Throwable) extends AkkaException(msg, e)
|
2010-05-21 08:18:56 +02:00
|
|
|
|
2011-05-18 17:25:30 +02:00
|
|
|
@volatile
|
|
|
|
|
private var service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory)
|
2010-08-06 17:13:31 +02:00
|
|
|
|
2010-08-18 19:01:34 +02:00
|
|
|
/**
|
2011-06-29 08:43:51 +02:00
|
|
|
* Schedules to send the specified message to the receiver after initialDelay and then repeated after delay.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* send of the message.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
2010-08-06 17:13:31 +02:00
|
|
|
def schedule(receiver: ActorRef, message: AnyRef, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = {
|
2009-08-17 18:42:41 +02:00
|
|
|
try {
|
2010-08-06 17:13:31 +02:00
|
|
|
service.scheduleAtFixedRate(
|
2010-05-21 20:08:49 +02:00
|
|
|
new Runnable { def run = receiver ! message },
|
2010-05-21 08:18:56 +02:00
|
|
|
initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]]
|
2009-08-17 18:42:41 +02:00
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: Exception ⇒
|
2011-03-18 23:04:48 +01:00
|
|
|
val error = SchedulerException(message + " could not be scheduled on " + receiver, e)
|
|
|
|
|
EventHandler.error(error, this, "%s @ %s".format(receiver, message))
|
|
|
|
|
throw error
|
2009-08-17 18:42:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-08-18 19:01:34 +02:00
|
|
|
/**
|
|
|
|
|
* Schedules to run specified function to the receiver after initialDelay and then repeated after delay,
|
2011-06-29 08:43:51 +02:00
|
|
|
* avoid blocking operations since this is executed in the schedulers thread.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* execution of the function.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
2011-05-18 17:25:30 +02:00
|
|
|
def schedule(f: () ⇒ Unit, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] =
|
2010-08-18 19:01:34 +02:00
|
|
|
schedule(new Runnable { def run = f() }, initialDelay, delay, timeUnit)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Schedules to run specified runnable to the receiver after initialDelay and then repeated after delay,
|
2011-06-29 08:43:51 +02:00
|
|
|
* avoid blocking operations since this is executed in the schedulers thread.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* execution of the runnable.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
|
|
|
|
def schedule(runnable: Runnable, initialDelay: Long, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = {
|
|
|
|
|
try {
|
2011-03-02 00:14:45 +01:00
|
|
|
service.scheduleAtFixedRate(runnable, initialDelay, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]]
|
2010-08-18 19:01:34 +02:00
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: Exception ⇒
|
2011-03-18 23:04:48 +01:00
|
|
|
val error = SchedulerException("Failed to schedule a Runnable", e)
|
|
|
|
|
EventHandler.error(error, this, error.getMessage)
|
|
|
|
|
throw error
|
2010-08-18 19:01:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2011-06-29 08:43:51 +02:00
|
|
|
* Schedules to send the specified message to the receiver after delay.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* send of the message.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
2010-08-06 17:13:31 +02:00
|
|
|
def scheduleOnce(receiver: ActorRef, message: AnyRef, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = {
|
2010-07-01 09:59:29 +02:00
|
|
|
try {
|
2010-08-06 17:13:31 +02:00
|
|
|
service.schedule(
|
2010-08-18 19:01:34 +02:00
|
|
|
new Runnable { def run = receiver ! message },
|
|
|
|
|
delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]]
|
|
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: Exception ⇒
|
|
|
|
|
val error = SchedulerException(message + " could not be scheduleOnce'd on " + receiver, e)
|
2011-03-18 23:04:48 +01:00
|
|
|
EventHandler.error(e, this, receiver + " @ " + message)
|
|
|
|
|
throw error
|
2010-08-18 19:01:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Schedules a function to be run after delay,
|
2011-06-29 08:43:51 +02:00
|
|
|
* avoid blocking operations since the runnable is executed in the schedulers thread.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* execution of the function.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
2011-05-18 17:25:30 +02:00
|
|
|
def scheduleOnce(f: () ⇒ Unit, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] =
|
2010-08-18 19:01:34 +02:00
|
|
|
scheduleOnce(new Runnable { def run = f() }, delay, timeUnit)
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Schedules a runnable to be run after delay,
|
2011-06-29 08:43:51 +02:00
|
|
|
* avoid blocking operations since the runnable is executed in the schedulers thread.
|
|
|
|
|
* The returned java.util.concurrent.ScheduledFuture can be used to cancel the
|
|
|
|
|
* execution of the runnable.
|
2010-08-18 19:01:34 +02:00
|
|
|
*/
|
|
|
|
|
def scheduleOnce(runnable: Runnable, delay: Long, timeUnit: TimeUnit): ScheduledFuture[AnyRef] = {
|
|
|
|
|
try {
|
2011-05-18 17:25:30 +02:00
|
|
|
service.schedule(runnable, delay, timeUnit).asInstanceOf[ScheduledFuture[AnyRef]]
|
2010-07-01 09:59:29 +02:00
|
|
|
} catch {
|
2011-05-18 17:25:30 +02:00
|
|
|
case e: Exception ⇒
|
2011-03-18 23:04:48 +01:00
|
|
|
val error = SchedulerException("Failed to scheduleOnce a Runnable", e)
|
|
|
|
|
EventHandler.error(e, this, error.getMessage)
|
|
|
|
|
throw error
|
2010-07-01 09:59:29 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2011-04-29 10:20:16 +02:00
|
|
|
def shutdown() {
|
|
|
|
|
synchronized {
|
|
|
|
|
service.shutdown()
|
|
|
|
|
}
|
2009-08-17 18:42:41 +02:00
|
|
|
}
|
|
|
|
|
|
2011-04-29 10:20:16 +02:00
|
|
|
def restart() {
|
|
|
|
|
synchronized {
|
|
|
|
|
shutdown()
|
|
|
|
|
service = Executors.newSingleThreadScheduledExecutor(SchedulerThreadFactory)
|
|
|
|
|
}
|
2010-05-21 08:18:56 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
private object SchedulerThreadFactory extends ThreadFactory {
|
2011-07-09 19:17:49 +02:00
|
|
|
private val count = new AtomicLong(0)
|
2009-08-17 18:42:41 +02:00
|
|
|
val threadFactory = Executors.defaultThreadFactory()
|
2009-08-17 20:46:05 +02:00
|
|
|
|
2009-08-17 18:42:41 +02:00
|
|
|
def newThread(r: Runnable): Thread = {
|
|
|
|
|
val thread = threadFactory.newThread(r)
|
2011-07-09 19:17:49 +02:00
|
|
|
thread.setName("akka:scheduler-" + count.incrementAndGet())
|
2009-08-17 18:42:41 +02:00
|
|
|
thread.setDaemon(true)
|
|
|
|
|
thread
|
|
|
|
|
}
|
2010-07-02 10:51:08 +02:00
|
|
|
}
|