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 class EventListener;
     82 class EventListenerGroup;
     83 class EventListenerSingle;
     84 
     85 typedef std::map<EventEmitter*, EventRequest*> EmitterRequestMap_t;
     86 
     87 // EventListener
     88 //
     89 // The EventListener class provides an object to wait on for specific events
     90 // from EventEmitter objects.  The EventListener becomes signalled for
     91 // read when events are waiting, making it is also an Emitter.
     92 class EventListener {
     93  public:
     94   EventListener();
     95   ~EventListener();
     96 
     97   // Called by EventEmitter to signal the Listener that a new event is
     98   // available.
     99   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events) = 0;
    100 
    101  protected:
    102   pthread_cond_t signal_cond_;
    103   DISALLOW_COPY_AND_ASSIGN(EventListener);
    104 };
    105 
    106 // EventListenerLock
    107 //
    108 // On construction, references and locks the emitter.  WaitOnEvent will
    109 // temporarily unlock waiting for any event in |events| to become signaled.
    110 // The functione exits with the lock taken.  The destructor will automatically
    111 // unlock the emitter.
    112 class EventListenerLock : public EventListener {
    113  public:
    114   explicit EventListenerLock(EventEmitter* emitter);
    115   ~EventListenerLock();
    116 
    117   // Called by EventEmitter to signal the Listener that a new event is
    118   // available.
    119   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events);
    120 
    121   // Called with the emitters lock held (which happens in the constructor).
    122   // Waits in a condvar until one of the events in |events| is raised or
    123   // or the timeout expired.  Returns with the emitter lock held, which
    124   // will be release when the destructor is called.
    125   //
    126   // On Error:
    127   //   ETIMEOUT if the timeout is exceeded.
    128   //   EINTR if the wait was interrupted.
    129   Error WaitOnEvent(uint32_t events, int ms_max);
    130 
    131  private:
    132   EventEmitter* emitter_;
    133   sdk_util::AutoLock* lock_;
    134   uint32_t events_;
    135   DISALLOW_COPY_AND_ASSIGN(EventListenerLock);
    136 };
    137 
    138 class EventListenerPoll : public EventListener {
    139  public:
    140   EventListenerPoll() : EventListener(), signaled_(0) {}
    141 
    142   // Called by EventEmitter to signal the Listener that a new event is
    143   // available.
    144   virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events);
    145 
    146   // Wait for the any requested emitter/filter pairs to emit one of the
    147   // events in the matching filter.  Returns 0 on success.
    148   //
    149   // On Error:
    150   //   ETIMEOUT if the timeout is exceeded.
    151   //   EINTR if the wait was interrupted.
    152   Error WaitOnAny(EventRequest* requests, size_t cnt, int ms_max);
    153 
    154  private:
    155   sdk_util::SimpleLock signal_lock_;
    156   EmitterRequestMap_t emitters_;
    157   size_t signaled_;
    158   DISALLOW_COPY_AND_ASSIGN(EventListenerPoll);
    159 };
    160 
    161 }  // namespace nacl_io
    162 
    163 #endif  /* LIBRARIES_NACL_IO_EVENT_LISTENER_H_ */
    164