Add fd event support to EventTaskRunner

This change allows applications to perform
general I/O completion handling as part of the
Run() loop, rather than just timeout completion.

Change-Id: Idce97a33f7a35348ac5a7d226491f9907edc3405
Reviewed-on: https://weave-review.googlesource.com/1447
Reviewed-by: Vitaly Buka <vitalybuka@google.com>
diff --git a/examples/provider/event_task_runner.h b/examples/provider/event_task_runner.h
index 473441e..7291314 100644
--- a/examples/provider/event_task_runner.h
+++ b/examples/provider/event_task_runner.h
@@ -10,9 +10,10 @@
 #include <vector>
 
 #include <event2/event.h>
-
 #include <weave/provider/task_runner.h>
 
+#include "examples/provider/event_deleter.h"
+
 namespace weave {
 namespace examples {
 
@@ -23,6 +24,40 @@
                        const base::Closure& task,
                        base::TimeDelta delay) override;
 
+  // Defines the types of I/O completion events that the
+  // application can register to receive on a file descriptor.
+  enum IOEvent : int16_t {
+    kReadable = 0x01,
+    kWriteable = 0x02,
+    kClosed = 0x04,
+    kReadableWriteable = kReadable | kWriteable,
+    kReadableOrClosed = kReadable | kClosed,
+    kAll = kReadableOrClosed | kWriteable,
+  };
+
+  // Callback type for I/O completion events.
+  // Arguments:
+  //  fd -      file descriptor that triggered the event
+  //  what -    combination of IOEvent flags indicating
+  //            which event(s) occurred
+  //  sender -  reference to the EventTaskRunner that
+  //            called the IoCompletionCallback
+  using IoCompletionCallback =
+      base::Callback<void(int fd, int16_t what, EventTaskRunner* sender)>;
+
+  // Adds a handler for the specified IO completion events on a file
+  // descriptor. The 'what' parameter is a combination of IOEvent flags.
+  // Only one callback is allowed per file descriptor; calling this function
+  // with an fd that has already been registered will replace the previous
+  // callback with the new one.
+  void AddIoCompletionTask(int fd,
+                           int16_t what,
+                           const IoCompletionCallback& task);
+
+  // Remove the callback associated with this fd and stop listening for
+  // events related to it.
+  void RemoveIoCompletionTask(int fd);
+
   event_base* GetEventBase() const { return base_.get(); }
 
   void Run();
@@ -33,6 +68,9 @@
   static void FreeEvent(event* evnt);
   void Process();
 
+  static void FdEventHandler(int fd, int16_t what, void* runner);
+  void ProcessFd(int fd, int16_t what);
+
   using QueueItem = std::pair<std::pair<base::Time, size_t>, base::Closure>;
 
   struct Greater {
@@ -47,10 +85,12 @@
                       std::vector<QueueItem>,
                       EventTaskRunner::Greater> queue_;
 
-  std::unique_ptr<event_base, decltype(&event_base_free)> base_{
-      event_base_new(), &event_base_free};
-  std::unique_ptr<event, decltype(&FreeEvent)> task_event_{
-      event_new(base_.get(), -1, EV_TIMEOUT, &EventHandler, this), &FreeEvent};
+  EventPtr<event_base> base_{event_base_new()};
+
+  EventPtr<event> task_event_{
+      event_new(base_.get(), -1, EV_TIMEOUT, &EventHandler, this)};
+
+  std::map<int, std::pair<EventPtr<event>, IoCompletionCallback>> fd_task_map_;
 };
 
 }  // namespace examples