Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Let's say I have a simple event system with the following syntax:

object = new Object();
object.bind("my_trigger", function()  { print "hello"; });
object.bind("my_trigger", function()  { print "hello2"; });
object.trigger("my_trigger");

How could I make sure hello2 is printed out first? (I do not want my code to depend on which order the events were bind).

On top of that, how would I prevent my events from propagating? (e.g. I want to stop every other event from being executed)

share|improve this question
add comment

4 Answers

up vote 1 down vote accepted

I recommend priority queues in a producer/consumer setup.

edit: I've used priority queues in sort of a pub/sub system before. I set up a router object; a method of that object was a sender, with the priority and destination point specified. There was a reader method which would be the destination point. Under the hood would be priority queues. The router object would handle reading and writing the queues.

It was actually a multithreaded system; the producers of information would be things like a http server, files, etc, the consumers could be the windows event queue, files, or http messages. The router would handle the messaging between the producers and consumers.

For filtering, I would determine who cares about the filtering, and place the filter block as part of that element. Possibly each element (producer, router, and consumer) would get the capability to hook. (e.g., a list of functions passed in and AND'd together to allow a message to pass).

share|improve this answer
    
Thanks for the suggestion! –  Peeter Mar 21 '12 at 18:05
    
@Peeter: see update for further thoughts –  Paul Nathan Mar 21 '12 at 20:10
    
I took your thoughts into count and this is what I managed to produce: github.com/peeter-tomberg/php-events –  Peeter Mar 27 '12 at 15:31
add comment

I'm thinking a chain-like design would be sufficient.

Here is a quick example of what I'm trying to describe, in Scala.

object Main extends App {

  // Event 1 - Prints Hello and doesn't break the chain
  val event1 = new Event {
    override def trigger = { println("Hello"); continue }
  }

  // Event 2 - Prints Hello2 but breaks the chain
  val event2 = new Event {
    override def trigger = { println("Hello2"); stop }
  }

  // Create new EventChain
  val eventChain = new EventChain

  // Add event1, then event2 at the beginning
  eventChain.addFirst(event1).addFirst(event2)

  // Bind the event chain to the identifier
  EventManager.bind("my_trigger", eventChain)

  // Trigger a new event
  EventManager.trigger("my_trigger")
}

object EventManager {

  // Keeps track of trigger bindings
  var events = Map[String, EventChain]()

  // Binds a trigger
  def bind(id: String, chain: EventChain) {
    events += ((id, chain))
  }

  // Triggers an EventChain
  def trigger(id: String) {
    events.find(e => e._1 == id) match {
      case Some(event) => event._2.trigger
      case None =>
    }
  }
}

// An event
abstract class Event {
  // Your response here
  def trigger: Boolean;

  // To continue
  def continue = true

  // To break the chain
  def stop = false
}

class EventChain {
  // List of Events
  private var events = List[Event]()

  // Adds an event to the beginning
  def addFirst(event: Event) = {
    events ::= event
    this
  }

  // Triggers the EventChain
  def trigger {

    var continue = true
    val itr = events.iterator

    // While it isn't broken and has another event
    while (continue && itr.hasNext) {
      // Assign the return value to continue
      continue = itr.next.trigger
    }
  }
}
share|improve this answer
    
Thta's exactly what I'm not trying to achieve. I'm looking for a way to add events in any order and define their priority in the add function. I'm also not really keen on making more classes, e.g. FilterChain. It should be simple :P –  Peeter Mar 21 '12 at 8:27
    
The problem with making it priority based which has priority over things with the same priority? To clarify, which ones should execute or should they all execute no matter what when multiple events have the same priority? This ambiguity is removed with the idea of a chain, as the priority is defined by the ordering of elements in the chain. Also, you can add more insert methods (by index or id of an event) so that you can have no dependence on order in which they're added, but their relative relation. –  Joe0 Mar 21 '12 at 18:59
add comment

I'd create a pub/sub type class, that will aggregate all the subscriptions, along with a priority, and then publish each event by priority, so rather than subscribing to the object itself, you'd subscribe to the manager class

share|improve this answer
add comment

A co-worker suggested the following:

object = new Object();
object.bind("my_trigger", function()  { print "hello"; });
object.bind("my_trigger", function()  { print "hello2"; return false; }, { priority : 10 });
object.trigger("my_trigger");

Upon binding, I order my events based on the priority and execute them in serial until one of them returns false and stops the execution.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.