All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.liftweb.actor.LAPinger.scala Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2007-2010 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 _root_.java.util.concurrent._

/**
 * The ActorPing object schedules an actor to be ping-ed with a given message at specific intervals.
 * The schedule methods return a ScheduledFuture object which can be cancelled if necessary
 */
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.
   *
   * @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
    d
  }
}

}
}