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