Saturday, December 27, 2008

Event driven programming

Most programmers think “Threads” when they are told to make a piece of code that should run concurrently. Also it hits them right in the face the last time they tried to make a threaded programs when they were faced by the usual problems (Races, deadlocks, etc) which are hard to detect, debug and at some time to reproduce. The behavior of threads is too unexpected as it's fully controlled by the threads scheduler not by the programmer. Another issue, the overhead of creating threads which sometimes is painful which produces an important question “What is the alternative ?”
Lets think of concurrency in the following way: we will receive all the requests at the same time and queue them. Then we will assign each of them to a specific function. When this function blocks (i.e. for IO requests) or finishes we will make another one start till it blocks or finishes and so on. The question you'll have in mind “Wait a minute, that's not concurrency!!”
Well, think of it this way. You have no stack management overhead, you have no scheduling overhead, you know exactly where the program is going to stop so bye bye races and deadlocks and the users gets to feel they are being served at the same time (Remember that you make all functions make the blocking calls at the same time). Is it that simple??
Lets see an example:
Threaded program will do something like the following,

   on a new event
   create a new thread that does
   {
      something
   }

A simple ruby server that listens on port 9000 on the localhost will create a new thread every time it receives any message on the socket like the following,
 socket = TCPServer.new(“localhost”,9000)
loop do
Thread.new(socket.accept) do |connection|
#do something with the connection
connection.close
end
end
But an evented program will do something like this,

   on a new event
   if free
      assign a handler for the event
      launch the handler
   else
      queue the event until free

It will kind of hard to demonstrate how exactly the events are handled as they are handled inside the evented library but it will look like the following using EventMachine (a ruby library). First we define a handler class (it could be named anything) with a recv_data method that eventmachine searches for in the module. Then we start the events loop. The code will look something like the following,
require 'eventmachine'
class EventHandler < EventMachine::Connection
def receive_data data
# do something
end
end
EventMachine::run {
   EventMachine::start_server("localhost", 9000, EventHandler)
}
Actually it's kind of hard to imagine at first and with large programs (where it perfectly fits) it's hard to debug so I wouldn't recommend it for any newbie to use. But for implementing, let's say a server, event driven programming has proved its efficiency compared to threaded programming.
Note: A lot of debate has been made in this area so you should read more to get to know the opinions of both sides and I recommend that you Google the topic if you are interested.
Waiting for your comments!!

3 comments:

  1. interesting topic , i had no idea about it :D ..
    Does this technique work for all cases where we use thread ? or there are some cases where we still need threads implementation ?

    ReplyDelete
  2. Well, you can use it instead of threads any where but most of the time threads are much easier to think of and much easier to implement and you find events not worth the complexity you'll add.

    ReplyDelete
  3. Event programming is a good paradigm in many applications like what you have mentioned "Listening to a port", where the nature of the application depends on external events, but if the application does not depend / loosely depends on external events, I think that using another paradigm is more convenient in this case, no matter how to implement concurrency, threads or whatever. But I can get your point of view, that "Wrapping" an event driven application in the batch paradigm (using threads to handle concurrency) is bad, I agree with you, Good work.

    ReplyDelete