Best method to peek into a Scala Actor's Mailbox

前端 未结 2 1892
感情败类
感情败类 2021-01-13 02:17

Using Scala 2.8 RC1 or newer, what is the best (easiest and/or most direct) method to \"peek\" at the waiting messages in an actor\'s mailbox (from within the same actor\'s

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-13 02:34

    You don't need to peek ahead. Just keep track of the fact that an exit has been requested and use a reactWithin(0) to determine when the queue is empty after an exit has been requested.

    import scala.actors._
    
    sealed case class Message
    case object Exit extends Message
    case class Unimportant(n:Int) extends Message
    case class Important(n:Int) extends Message
    
    class SafeExitingActor extends Actor {
      def act : Nothing = react {
          case Exit => {
               println("exit requested, clearing the queue")
               exitRequested
          }
          case message => {
               processMessage(message, false)
               act
          }
      }
    
      // reactWithin(0) gives a TIMEOUT as soon as the mailbox is empty
      def exitRequested : Nothing = reactWithin(0) {
         case Exit => {
             println("extra exit requested, ignoring")
             exitRequested // already know about the exit, keep processing
         }
         case TIMEOUT => {
             println("timeout, queue is empty, shutting down")
             exit // TIMEOUT so nothing more to process, we can shut down
         }
         case message => {
             processMessage(message, true)
             exitRequested
         }
      }
    
      // process is a separate method to avoid duplicating in act and exitRequested
      def processMessage(message : Any, importantOnly : Boolean) = {
         message match {
           case Unimportant(n) if !importantOnly => println("Unimportant " + n)
           case Unimportant(n) => () // do nothing
           case Important(n) => println("Important! " + n)
         }
         Thread sleep 100 // sleep a little to ensure mailbox backlog
      }
    }
    
    object TestProcessing {
      def main(args : Array[String]) {
        val actor = new SafeExitingActor()
        actor.start()
        for (i <- 1 to 10) {
            actor ! Unimportant(i)
            actor ! Important(i)
        }
        actor ! Exit
        for (i <- 11 to 20) {
            actor ! Unimportant(i)
            actor ! Important(i)
        }
        actor ! Exit
        actor ! Important(100)
      }
    }
    

    That should output

    Unimportant 1
    Important! 1
    Unimportant 2
    Important! 2
    Unimportant 3
    Important! 3
    Unimportant 4
    Important! 4
    Unimportant 5
    Important! 5
    Unimportant 6
    Important! 6
    Unimportant 7
    Important! 7
    Unimportant 8
    Important! 8
    Unimportant 9
    Important! 9
    Unimportant 10
    Important! 10
    exit requested, clearing the queue
    Important! 11
    Important! 12
    Important! 13
    Important! 14
    Important! 15
    Important! 16
    Important! 17
    Important! 18
    Important! 19
    Important! 20
    extra exit requested, ignoring
    Important! 100
    timeout, queue is empty, shutting down
    

提交回复
热议问题