1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch/* Copyright (c) 2013 The Chromium Authors. All rights reserved. 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * Use of this source code is governed by a BSD-style license that can be 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch * found in the LICENSE file. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch */ 5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#ifndef LIBRARIES_NACL_IO_EVENT_LISTENER_H_ 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#define LIBRARIES_NACL_IO_EVENT_LISTENER_H_ 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <pthread.h> 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <map> 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <set> 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include <vector> 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "nacl_io/error.h" 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "nacl_io/event_emitter.h" 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "sdk_util/auto_lock.h" 1968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)#include "sdk_util/macros.h" 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "sdk_util/scoped_ref.h" 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Kernel Events 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Certain file objects such as pipes or sockets can become signaled when 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// read or write buffers become available, or when the connection is torn 26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// down. EventListener provides a mechanism for a thread to wait on 27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// specific events from these objects which are derived from EventEmitters. 28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 2968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Calling RegisterListener_Locked on an event emitter, will cause all 3068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Listeners matching the event mask are signaled so they may try to make 3168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// progress. In the case of "select" or "poll", multiple threads could be 3268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// notified that one or more emitters are signaled and allowed to make 3368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// progress. In the case of "read" or "write", only one thread at a time 3468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// should make progress, to ensure that if one thread consumes the signal, 3568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// the other can correctly timeout. 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 3768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// Events Listeners requirements: 3868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 1- Must reference counting Emitters to ensure they are not destroyed 3968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// while waiting for a signal. 4068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 2- Must unregister themselves from all emitters prior to being destoryed. 4168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 3- Must never be shared between threads since interals may not be locked 4268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// to prevent dead-locks with emitter signals. 4368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 4- Must never lock themselves before locking an emitter to prevent 4468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// dead-locks 45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 4668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// There are two types of listeners, EventListenerSingle and EventListenerGroup 4768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// For Single listeners, all listeners are unblocked by the Emitter, but 4868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// they individually take the emitters lock and test against the current 4968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// status to ensure another listener didn't consume the signal. 50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Locking: 5268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventEmitter::<Backgroun IO> 5368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// *LOCK* EventEmitter::emitter_lock_ 5468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventEmitter::RaiseEvent_Locked 5568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventListenerSingle::ReceiveEvents 5668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// <no locking, using emitter's lock> 5768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventListenerGroup::ReceiveEvents 5868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// *LOCK* EventListenerGroup::signal_lock_ 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 6068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventListenerSingle::WaitOnLock 6168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// *LOCK* EventEmitter::emitter_lock_ 62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 6368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventListenerGroup::WaitOnAny 6468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// *LOCK* EventListenerGroup::signal_lock_ 65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace nacl_io { 68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstruct EventData { 703240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch // Bit Mask of signaled POLL events. 71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint32_t events; 72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch uint64_t user_data; 73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}; 74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)struct EventRequest { 7668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ScopedEventEmitter emitter; 7768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) uint32_t filter; 7868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) uint32_t events; 7968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 8068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListener; 8268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListenerGroup; 8368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListenerSingle; 8468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 8568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)typedef std::map<EventEmitter*, EventRequest*> EmitterRequestMap_t; 86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// EventListener 88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// 89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// The EventListener class provides an object to wait on for specific events 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// from EventEmitter objects. The EventListener becomes signalled for 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// read when events are waiting, making it is also an Emitter. 9268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListener { 93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public: 9468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EventListener(); 9568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ~EventListener(); 9668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 9768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Called by EventEmitter to signal the Listener that a new event is 9868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // available. 9968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events) = 0; 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch protected: 10268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) pthread_cond_t signal_cond_; 10368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EventListener); 10468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 10568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 10668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// EventListenerLock 10768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// 10868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// On construction, references and locks the emitter. WaitOnEvent will 10968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// temporarily unlock waiting for any event in |events| to become signaled. 11068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// The functione exits with the lock taken. The destructor will automatically 11168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)// unlock the emitter. 11268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListenerLock : public EventListener { 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch public: 11468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) explicit EventListenerLock(EventEmitter* emitter); 11568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) ~EventListenerLock(); 11668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 11768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Called by EventEmitter to signal the Listener that a new event is 11868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // available. 11968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events); 12068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 12168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Called with the emitters lock held (which happens in the constructor). 12268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Waits in a condvar until one of the events in |events| is raised or 12368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // or the timeout expired. Returns with the emitter lock held, which 12468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // will be release when the destructor is called. 12568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // 12668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // On Error: 12768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // ETIMEOUT if the timeout is exceeded. 12868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // EINTR if the wait was interrupted. 12968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Error WaitOnEvent(uint32_t events, int ms_max); 13068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 13146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) private: 13268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EventEmitter* emitter_; 13368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) sdk_util::AutoLock* lock_; 13468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) uint32_t events_; 13568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EventListenerLock); 13668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}; 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 13868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)class EventListenerPoll : public EventListener { 13968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) public: 14068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EventListenerPoll() : EventListener(), signaled_(0) {} 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 14268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Called by EventEmitter to signal the Listener that a new event is 14368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // available. 14468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events); 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 14668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // Wait for the any requested emitter/filter pairs to emit one of the 14768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // events in the matching filter. Returns 0 on success. 14868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // 14968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // On Error: 15068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // ETIMEOUT if the timeout is exceeded. 15168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) // EINTR if the wait was interrupted. 15268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) Error WaitOnAny(EventRequest* requests, size_t cnt, int ms_max); 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) private: 15568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) sdk_util::SimpleLock signal_lock_; 15668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) EmitterRequestMap_t emitters_; 15768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) size_t signaled_; 15868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(EventListenerPoll); 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch}; 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace nacl_io 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif /* LIBRARIES_NACL_IO_EVENT_LISTENER_H_ */ 164