 Chromium Code Reviews
 Chromium Code Reviews Issue 23498015:
  [NaCl SDK] Support non blocking TCP/UDP  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src
    
  
    Issue 23498015:
  [NaCl SDK] Support non blocking TCP/UDP  (Closed) 
  Base URL: svn://svn.chromium.org/chrome/trunk/src| Index: native_client_sdk/src/libraries/nacl_io/event_listener.h | 
| diff --git a/native_client_sdk/src/libraries/nacl_io/event_listener.h b/native_client_sdk/src/libraries/nacl_io/event_listener.h | 
| index cb93f116b2f1b91179e78193ba8bb9551641c45a..4ad4090b8a5bfe9e312be0fd8759df94697e5c70 100644 | 
| --- a/native_client_sdk/src/libraries/nacl_io/event_listener.h | 
| +++ b/native_client_sdk/src/libraries/nacl_io/event_listener.h | 
| @@ -15,6 +15,7 @@ | 
| #include "nacl_io/error.h" | 
| #include "nacl_io/event_emitter.h" | 
| +#include "sdk_util/auto_lock.h" | 
| #include "sdk_util/scoped_ref.h" | 
| // Kernel Events | 
| @@ -24,43 +25,43 @@ | 
| // down. EventListener provides a mechanism for a thread to wait on | 
| // specific events from these objects which are derived from EventEmitters. | 
| // | 
| -// EventEmitter and EventListener together provide support for an "epoll" | 
| -// like interface. See: | 
| -// http://man7.org/linux/man-pages/man7/epoll.7.html | 
| +// Calling RegisterListener_Locked on an event emitter, will cause all | 
| +// Listeners matching the event mask are signaled so they may try to make | 
| +// progress. In the case of "select" or "poll", multiple threads could be | 
| +// notified that one or more emitters are signaled and allowed to make | 
| +// progress. In the case of "read" or "write", only one thread at a time | 
| +// should make progress, to ensure that if one thread consumes the signal, | 
| +// the other can correctly timeout. | 
| // | 
| -// Such that we map the arguments at behavior of | 
| -// epoll_wait maps to Wait, and | 
| -// epoll_ctl maps to Track, Update, Free. | 
| +// Events Listeners requirements: | 
| +// 1- Must reference counting Emitters to ensure they are not destroyed | 
| +// while waiting for a signal. | 
| +// 2- Must unregister themselves from all emitters prior to being destoryed. | 
| +// 3- Must never be shared between threads since interals may not be locked | 
| +// to prevent dead-locks with emitter signals. | 
| +// 4- Must never lock themselves before locking an emitter to prevent | 
| +// dead-locks | 
| // | 
| -// Behavior of EventListeners | 
| -// FDs are automatically removed when closed. | 
| -// KE_SHUTDOWN can not be masked. | 
| -// KE_SHUTDOWN is only seen if the hangup happens after Wait starts. | 
| -// Dup'd FDs get their own event info which must also get signaled. | 
| -// Adding a non streaming FD will fail. | 
| -// EventEmitters can also be waited on. | 
| -// It is illegal for an a EventListener to add itself. | 
| +// There are two types of listeners, EventListenerSingle and EventListenerGroup | 
| +// For Single listeners, all listeners are unblocked by the Emitter, but | 
| +// they individually take the emitters lock and test against the current | 
| +// status to ensure another listener didn't consume the signal. | 
| // | 
| // Locking: | 
| -// EventListener::{Track/Update/Free} | 
| -// AUTO_LOCK(EventListener::info_lock_) | 
| -// EventEmitter::RegisterEventInfo | 
| -// AUTO_LOCK(EventEmitter::emitter_lock_) | 
| +// EventEmitter::<Backgroun IO> | 
| +// *LOCK* EventEmitter::emitter_lock_ | 
| +// EventEmitter::RaiseEvent_Locked | 
| +// EventListenerSingle::ReceiveEvents | 
| +// <no locking, using emitter's lock> | 
| +// EventListenerGroup::ReceiveEvents | 
| +// *LOCK* EventListenerGroup::signal_lock_ | 
| // | 
| -// EventEmitter::Destroy | 
| -// EventListener::AbandonedEventInfo | 
| -// AUTO_LOCK(EventListener::info_lock_) | 
| +// EventListenerSingle::WaitOnLock | 
| +// *LOCK* EventEmitter::emitter_lock_ | 
| // | 
| -// EventListener::RaiseEvent | 
| -// AUTO_LOCK(EventEmitter::emitter_lock_) | 
| -// EventListener::Signal | 
| -// AUTO_LOCK(EventListener::signal_lock_) | 
| +// EventListenerGroup::WaitOnAny | 
| +// *LOCK* EventListenerGroup::signal_lock_ | 
| // | 
| -// EventListener::Wait | 
| -// AUTO_LOCK(EventListener::info_lock_) | 
| -// ... | 
| -// AUTO_LOCK(EventListener::signal_lock_) | 
| -// ... | 
| namespace nacl_io { | 
| @@ -70,74 +71,96 @@ struct EventData { | 
| uint64_t user_data; | 
| }; | 
| +struct EventRequest { | 
| + ScopedEventEmitter emitter; | 
| + uint32_t filter; | 
| + uint32_t events; | 
| +}; | 
| + | 
| + | 
| +class EventListener; | 
| +class EventListenerGroup; | 
| +class EventListenerSingle; | 
| + | 
| +typedef std::map<EventEmitter*, EventRequest*> EmitterRequestMap_t; | 
| // EventListener | 
| // | 
| // The EventListener class provides an object to wait on for specific events | 
| // from EventEmitter objects. The EventListener becomes signalled for | 
| // read when events are waiting, making it is also an Emitter. | 
| -class EventListener : public EventEmitter { | 
| +class EventListener { | 
| public: | 
| EventListener(); | 
| ~EventListener(); | 
| - protected: | 
| - // Called prior to free to unregister all EventInfos from the EventEmitters. | 
| - void Destroy(); | 
| - | 
| public: | 
| - // Declared in EventEmitter | 
| - virtual uint32_t GetEventStatus(); | 
| - virtual int GetType(); | 
| - | 
| // Called by EventEmitter to signal the Listener that a new event is | 
| // available. | 
| - void Signal(const ScopedEventInfo& info); | 
| + virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events) = 0; | 
| - // Wait for one or more previously Tracked events to take place | 
| - // or until ms_timeout expires, and fills |events| up to |max| limit. | 
| - // The number of events recored is returned in |count|. | 
| - Error Wait(EventData* events, int max, int ms_timeout, int* out_count); | 
| + protected: | 
| + pthread_cond_t signal_cond_; | 
| +}; | 
| - // Tracks a new set of POLL events for a given unique |id|. The | 
| - // |user_data| will be returned in the Wait when an event of type |filter| | 
| - // is received with that |id|. | 
| - Error Track(int id, | 
| - const ScopedEventEmitter& emitter, | 
| - uint32_t filter, | 
| - uint64_t user_data); | 
| - // Updates the tracking of events for |id|, replacing the |user_data| | 
| - // that's returned, as well as which events will signal. | 
| - Error Update(int id, uint32_t filter, uint64_t user_data); | 
| +// EventListenerLock | 
| +// | 
| +// On construction, references and locks the emitter. WaitOnEvent will | 
| +// temporarily unlock waiting for any event in |events| to become signaled. | 
| +// The functione exits with the lock taken. The destructor will automatically | 
| +// unlock the emitter. | 
| +class EventListenerLock : public EventListener { | 
| + public: | 
| + explicit EventListenerLock(EventEmitter* emitter); | 
| 
binji
2013/09/12 01:47:57
nit: two space indent here
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| + ~EventListenerLock(); | 
| - // Unregisters the existing |id|. | 
| - Error Free(int id); | 
| + // Called by EventEmitter to signal the Listener that a new event is | 
| + // available. | 
| + virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events); | 
| - // Notification by EventEmitter that it is abandoning the event. Do not | 
| - // access the emitter after this. | 
| - void AbandonedEventInfo(const ScopedEventInfo& event); | 
| + public: | 
| 
binji
2013/09/12 01:47:57
remove
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| + // Called with the emitters lock held (which happens in the constructor). | 
| + // Waits in a condvar until one of the events in |events| is raised or | 
| + // or the timeout expired. Returns with the emitter lock held, which | 
| + // will be release when the destructor is called. | 
| + // | 
| + // On Error: | 
| + // ETIMEOUT if the timeout is exceeded. | 
| + // EINTR if the wait was interrupted. | 
| + Error WaitOnEvent(uint32_t events, int ms_max); | 
| + | 
| +protected: | 
| 
binji
2013/09/12 01:47:57
private:
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| + EventEmitter* emitter_; | 
| + sdk_util::AutoLock* lock_; | 
| + uint32_t events_; | 
| 
binji
2013/09/12 01:47:57
disable copy and assign?
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| +}; | 
| - private: | 
| - // Protects the data in the EventInfo map. | 
| - sdk_util::SimpleLock info_lock_; | 
| - // Map from ID to live a event info. | 
| - EventInfoMap_t event_info_map_; | 
| +class EventListenerPoll : public EventListener { | 
| + public: | 
| + EventListenerPoll() : EventListener(), signaled_(0) {} | 
| - // Protects waiting_, signaled_ and used with the signal_cond_. | 
| + // Called by EventEmitter to signal the Listener that a new event is | 
| + // available. | 
| + virtual void ReceiveEvents(EventEmitter* emitter, uint32_t events); | 
| + | 
| +public: | 
| 
binji
2013/09/12 01:47:57
remove
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| + // Wait for the any requested emitter/filter pairs to emit one of the | 
| + // events in the matching filter. Returns 0 on success. | 
| + // | 
| + // On Error: | 
| + // ETIMEOUT if the timeout is exceeded. | 
| + // EINTR if the wait was interrupted. | 
| + Error WaitOnAny(EventRequest* requests, size_t cnt, int ms_max); | 
| + | 
| +protected: | 
| 
binji
2013/09/12 01:47:57
private:
 
noelallen1
2013/09/12 23:19:03
Done.
 | 
| sdk_util::SimpleLock signal_lock_; | 
| - pthread_cond_t signal_cond_; | 
| + EmitterRequestMap_t emitters_; | 
| + size_t signaled_; | 
| - // The number of threads currently waiting on this Listener. | 
| - uint32_t waiting_; | 
| - | 
| - // Set of event infos signaled during a wait. | 
| - EventInfoSet_t signaled_; | 
| }; | 
| -typedef sdk_util::ScopedRef<EventListener> ScopedEventListener; | 
| - | 
| } // namespace nacl_io | 
| #endif /* LIBRARIES_NACL_IO_EVENT_LISTENER_H_ */ |