15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 57d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#ifndef BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ 67d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#define BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h" 117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_pump.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread_checker.h" 14eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "base/time/time.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Declare structs we need from libevent.h rather than including it 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct event_base; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct event; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Class to monitor sockets and issue callbacks when sockets are ready for I/O 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(dkegel): add support for background file IO somehow 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BASE_EXPORT MessagePumpLibevent : public MessagePump { 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class IOObserver { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IOObserver() {} 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // An IOObserver is an object that receives IO notifications from the 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MessagePump. 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: An IOObserver implementation should be extremely fast! 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void WillProcessIOEvent() = 0; 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void DidProcessIOEvent() = 0; 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~IOObserver() {} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used with WatchFileDescriptor to asynchronously monitor the I/O readiness 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of a file descriptor. 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class Watcher { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called from MessageLoop::Run when an FD can be read from/written to 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // without blocking 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanReadWithoutBlocking(int fd) = 0; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void OnFileCanWriteWithoutBlocking(int fd) = 0; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected: 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual ~Watcher() {} 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Object returned by WatchFileDescriptor to manage further watching. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class FileDescriptorWatcher { 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileDescriptorWatcher(); 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~FileDescriptorWatcher(); // Implicitly calls StopWatchingFileDescriptor. 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: These methods aren't called StartWatching()/StopWatching() to 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // avoid confusion with the win32 ObjectWatcher class. 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Stop watching the FD, always safe to call. No-op if there's nothing 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to do. 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool StopWatchingFileDescriptor(); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MessagePumpLibevent; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MessagePumpLibeventTest; 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called by MessagePumpLibevent, ownership of |e| is transferred to this 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // object. 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void Init(event* e); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Used by MessagePumpLibevent to take ownership of event_. 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event* ReleaseEvent(); 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_pump(MessagePumpLibevent* pump) { pump_ = pump; } 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MessagePumpLibevent* pump() const { return pump_; } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void set_watcher(Watcher* watcher) { watcher_ = watcher; } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnFileCanReadWithoutBlocking(int fd, MessagePumpLibevent* pump); 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void OnFileCanWriteWithoutBlocking(int fd, MessagePumpLibevent* pump); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event* event_; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessagePumpLibevent* pump_; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Watcher* watcher_; 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) WeakPtrFactory<FileDescriptorWatcher> weak_factory_; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcher); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) enum Mode { 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WATCH_READ = 1 << 0, 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WATCH_WRITE = 1 << 1, 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) WATCH_READ_WRITE = WATCH_READ | WATCH_WRITE 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) }; 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MessagePumpLibevent(); 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch virtual ~MessagePumpLibevent(); 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Have the current thread's message loop watch for a a situation in which 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // reading/writing to the FD can be performed without blocking. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Callers must provide a preallocated FileDescriptorWatcher object which 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // can later be used to manage the lifetime of this event. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If a FileDescriptorWatcher is passed in which is already attached to 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an event, then the effect is cumulative i.e. after the call |controller| 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // will watch both the previous event and the new one. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an error occurs while calling this method in a cumulative fashion, the 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // event previously attached to |controller| is aborted. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Returns true on success. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Must be called on the same thread the message_pump is running on. 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(dkegel): switch to edge-triggered readiness notification 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool WatchFileDescriptor(int fd, 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool persistent, 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int mode, 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FileDescriptorWatcher *controller, 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Watcher *delegate); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void AddIOObserver(IOObserver* obs); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void RemoveIOObserver(IOObserver* obs); 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // MessagePump methods: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Run(Delegate* delegate) OVERRIDE; 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void Quit() OVERRIDE; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ScheduleWork() OVERRIDE; 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) virtual void ScheduleDelayedWork(const TimeTicks& delayed_work_time) OVERRIDE; 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) friend class MessagePumpLibeventTest; 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void WillProcessIOEvent(); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void DidProcessIOEvent(); 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Risky part of constructor. Returns true on success. 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool Init(); 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Called by libevent to tell us a registered FD can be read/written to. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnLibeventNotification(int fd, short flags, 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* context); 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Unix pipe used to implement ScheduleWork() 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... callback; called by libevent inside Run() when pipe is ready to read 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static void OnWakeup(int socket, short flags, void* context); 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This flag is set to false when Run should return. 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool keep_running_; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This flag is set when inside Run. 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool in_run_; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This flag is set if libevent has processed I/O events. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool processed_io_events_; 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The time at which we should call DoDelayedWork. 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TimeTicks delayed_work_time_; 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Libevent dispatcher. Watches all sockets registered with it, and sends 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // readiness callbacks when a socket is ready for I/O. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event_base* event_base_; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... write end; ScheduleWork() writes a single byte to it 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wakeup_pipe_in_; 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... read end; OnWakeup reads it and then breaks Run() out of its sleep 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int wakeup_pipe_out_; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // ... libevent wrapper for read end 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) event* wakeup_event_; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ObserverList<IOObserver> io_observers_; 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ThreadChecker watch_file_descriptor_caller_checker_; 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(MessagePumpLibevent); 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace base 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#endif // BASE_MESSAGE_LOOP_MESSAGE_PUMP_LIBEVENT_H_ 178