net.liftweb.actor.LAPinger.scala Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2007-2011 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.
*/
package net.liftweb
package actor
import java.util.concurrent._
/**
* Rules for dealing with thread pools, both in lift-actor and
* in lift-util
*/
object ThreadPoolRules {
/**
* When threads are created in the thread factories, should
* they null the context class loader. By default false,
* but it you set it to true, Tomcat complains less about stuff.
* Must be set in the first line of Boot.scala
*/
@volatile var nullContextClassLoader: Boolean = false
}
/**
* LAPinger is for scheduling LiftActors to be pinged with an arbitrary message at some point
* in the future.
*/
object LAPinger {
/**The underlying java.util.concurrent.ScheduledExecutor
*/
private var service = Executors.newSingleThreadScheduledExecutor(TF)
/**
* Re-create the underlying SingleThreadScheduledExecutor
*/
def restart: Unit = synchronized {
if ((service eq null) || service.isShutdown)
service = Executors.newSingleThreadScheduledExecutor(TF)
}
/**
* Shut down the underlying SingleThreadScheduledExecutor
*/
def shutdown: Unit = synchronized {
service.shutdown
}
/**
* Schedules the sending of a message to occur after the specified delay.
*
* @param to The LiftActor to send the message to.
* @param msg The message to send.
* @param delay The number of milliseconds to delay before sending msg
* @return a ScheduledFuture
which sends the msg
to
* the to Actor after the specified TimeSpan delay
.
*/
def schedule[T](to: SpecializedLiftActor[T], msg: T, delay: Long): ScheduledFuture[Unit] = {
val r = new Callable[Unit] {
def call: Unit = {
to ! msg
}
}
try {
service.schedule(r, delay, TimeUnit.MILLISECONDS)
} catch {
case e: RejectedExecutionException => throw PingerException(msg + " could not be scheduled on " + to, e)
}
}
}
/**
* Exception thrown if a ping can't be scheduled.
*/
case class PingerException(msg: String, e: Throwable) extends RuntimeException(msg, e)
private object TF extends ThreadFactory {
val threadFactory = Executors.defaultThreadFactory()
def newThread(r: Runnable): Thread = {
val d: Thread = threadFactory.newThread(r)
d setName "ActorPinger"
d setDaemon true
if (ThreadPoolRules.nullContextClassLoader) {
d setContextClassLoader null
}
d
}
}