• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
EventListenerPoll()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