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
67namespace nacl_io {
68
69struct EventData {
70  // Bit Mask of signaled POLL events.
71  uint32_t events;
72  uint64_t user_data;
73};
74
75struct EventRequest {
76  ScopedEventEmitter emitter;
77  uint32_t filter;
78  uint32_t events;
79};
80
81class EventListener;
82class EventListenerGroup;
83class EventListenerSingle;
84
85typedef 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.
92class 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.
112class 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
138class 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