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