Home | History | Annotate | Download | only in nacl_io
      1 /* Copyright (c) 2013 The Chromium Authors. All rights reserved.
      2  * Use of this source code is governed by a BSD-style license that can be
      3  * found in the LICENSE file.
      4  */
      5 
      6 #ifndef LIBRARIES_NACL_IO_EVENT_LISTENER_H_
      7 #define LIBRARIES_NACL_IO_EVENT_LISTENER_H_
      8 
      9 #include <pthread.h>
     10 
     11 #include <map>
     12 #include <set>
     13 #include <vector>
     14 
     15 #include "nacl_io/error.h"
     16 #include "nacl_io/event_emitter.h"
     17 
     18 #include "sdk_util/auto_lock.h"
     19 #include "sdk_util/macros.h"
     20 #include "sdk_util/scoped_ref.h"
     21 
     22 // Kernel Events
     23 //
     24 // Certain file objects such as pipes or sockets can become signaled when
     25 // read or write buffers become available, or when the connection is torn
     26 // down.  EventListener provides a mechanism for a thread to wait on
     27 // specific events from these objects which are derived from EventEmitters.
     28 //
     29 // Calling RegisterListener_Locked on an event emitter, will cause all
     30 // Listeners matching the event mask are signaled so they may try to make
     31 // progress.  In the case of "select" or "poll", multiple threads could be
     32 // notified that one or more emitters are signaled and allowed to make
     33 // progress.  In the case of "read" or "write", only one thread at a time
     34 // should make progress, to ensure that if one thread consumes the signal,
     35 // the other can correctly timeout.
     36 //
     37 // Events Listeners requirements:
     38 //   1- Must reference counting Emitters to ensure they are not destroyed
     39 //      while waiting for a signal.
     40 //   2- Must unregister themselves from all emitters prior to being destoryed.
     41 //   3- Must never be shared between threads since interals may not be locked
     42 //      to prevent dead-locks with emitter signals.
     43 //   4- Must never lock themselves before locking an emitter to prevent
     44 //      dead-locks
     45 //
     46 // There are two types of listeners, EventListenerSingle and EventListenerGroup
     47 // For Single listeners, all listeners are unblocked by the Emitter, but
     48 // they individually take the emitters lock and test against the current
     49 // status to ensure another listener didn't consume the signal.
     50 //
     51 //  Locking:
     52 //    EventEmitter::<Backgroun IO>
     53 //      *LOCK* EventEmitter::emitter_lock_
     54 //        EventEmitter::RaiseEvent_Locked
     55 //          EventListenerSingle::ReceiveEvents
     56 //            <no locking, using emitter's lock>
     57 //        EventListenerGroup::ReceiveEvents
     58 //          *LOCK*  EventListenerGroup::signal_lock_
     59 //
     60 //    EventListenerSingle::WaitOnLock
     61 //      *LOCK* EventEmitter::emitter_lock_
     62 //
     63 //    EventListenerGroup::WaitOnAny
     64 //      *LOCK* EventListenerGroup::signal_lock_
     65 //
     66 
     67 namespace nacl_io {
     68 
     69 struct EventData {
     70   // Bit Mask of signaled POLL events.
     71   uint32_t events;
     72   uint64_t user_data;
     73 };
     74 
     75 struct EventRequest {
     76   ScopedEventEmitter emitter;
     77   uint32_t filter;
     78   uint32_t events;
     79 };
     80 
     81 
     82 class EventListener;
     83 class EventListenerGroup;
     84 class EventListenerSingle;
     85 
     86 typedef std::map<EventEmitter*, EventRequest*> EmitterRequestMap_t;
     87 
     88 // EventListener
     89 //
     90 // The EventListener class provides an object to wait on for specific events
     91 // from EventEmitter objects.  The EventListener becomes signalled for
     92 // read when events are waiting, making it is also an Emitter.
     93 class EventListener {
     94  public:
     95   EventListener();
     96   ~EventListener();
     97 
     98   // Called by EventEmitter to signal the Listener that a new event is
     99   // available.
    100   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events) = 0;
    101 
    102  protected:
    103   pthread_cond_t signal_cond_;
    104   DISALLOW_COPY_AND_ASSIGN(EventListener);
    105 };
    106 
    107 
    108 // EventListenerLock
    109 //
    110 // On construction, references and locks the emitter.  WaitOnEvent will
    111 // temporarily unlock waiting for any event in |events| to become signaled.
    112 // The functione exits with the lock taken.  The destructor will automatically
    113 // unlock the emitter.
    114 class EventListenerLock : public EventListener {
    115  public:
    116   explicit EventListenerLock(EventEmitter* emitter);
    117   ~EventListenerLock();
    118 
    119   // Called by EventEmitter to signal the Listener that a new event is
    120   // available.
    121   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events);
    122 
    123   // Called with the emitters lock held (which happens in the constructor).
    124   // Waits in a condvar until one of the events in |events| is raised or
    125   // or the timeout expired.  Returns with the emitter lock held, which
    126   // will be release when the destructor is called.
    127   //
    128   // On Error:
    129   //   ETIMEOUT if the timeout is exceeded.
    130   //   EINTR if the wait was interrupted.
    131   Error WaitOnEvent(uint32_t events, int ms_max);
    132 
    133 private:
    134   EventEmitter* emitter_;
    135   sdk_util::AutoLock* lock_;
    136   uint32_t events_;
    137   DISALLOW_COPY_AND_ASSIGN(EventListenerLock);
    138 };
    139 
    140 
    141 class EventListenerPoll : public EventListener {
    142  public:
    143   EventListenerPoll() : EventListener(), signaled_(0) {}
    144 
    145   // Called by EventEmitter to signal the Listener that a new event is
    146   // available.
    147   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events);
    148 
    149   // Wait for the any requested emitter/filter pairs to emit one of the
    150   // events in the matching filter.  Returns 0 on success.
    151   //
    152   // On Error:
    153   //   ETIMEOUT if the timeout is exceeded.
    154   //   EINTR if the wait was interrupted.
    155   Error WaitOnAny(EventRequest* requests, size_t cnt, int ms_max);
    156 
    157  private:
    158   sdk_util::SimpleLock signal_lock_;
    159   EmitterRequestMap_t emitters_;
    160   size_t signaled_;
    161   DISALLOW_COPY_AND_ASSIGN(EventListenerPoll);
    162 };
    163 
    164 }  // namespace nacl_io
    165 
    166 #endif  /* LIBRARIES_NACL_IO_EVENT_LISTENER_H_ */
    167