bug 532333: part 1: expose libevent signal events through chromium wrappers

This commit is contained in:
Chris Jones 2009-12-02 21:09:24 -06:00
parent 43fec0c5cf
commit e89e8adc89
4 changed files with 158 additions and 0 deletions

View File

@ -632,4 +632,14 @@ bool MessageLoopForIO::WatchFileDescriptor(int fd,
delegate);
}
#if defined(CHROMIUM_MOZILLA_BUILD)
bool
MessageLoopForIO::CatchSignal(int sig,
SignalEvent* sigevent,
SignalWatcher* delegate)
{
return pump_libevent()->CatchSignal(sig, sigevent, delegate);
}
#endif // defined(CHROMIUM_MOZILLA_BUILD)
#endif

View File

@ -507,6 +507,15 @@ class MessageLoopForIO : public MessageLoop {
Mode mode,
FileDescriptorWatcher *controller,
Watcher *delegate);
#if defined(CHROMIUM_MOZILLA_BUILD)
typedef base::MessagePumpLibevent::SignalEvent SignalEvent;
typedef base::MessagePumpLibevent::SignalWatcher SignalWatcher;
bool CatchSignal(int sig,
SignalEvent* sigevent,
SignalWatcher* delegate);
#endif // defined(CHROMIUM_MOZILLA_BUILD)
#endif // defined(OS_POSIX)
};

View File

@ -211,6 +211,91 @@ void MessagePumpLibevent::OnLibeventNotification(int fd, short flags,
}
}
#if defined(CHROMIUM_MOZILLA_BUILD)
MessagePumpLibevent::SignalEvent::SignalEvent() :
event_(NULL)
{
}
MessagePumpLibevent::SignalEvent::~SignalEvent()
{
if (event_) {
StopCatching();
}
}
void
MessagePumpLibevent::SignalEvent::Init(event *e)
{
DCHECK(e);
DCHECK(event_ == NULL);
event_ = e;
}
bool
MessagePumpLibevent::SignalEvent::StopCatching()
{
// XXX/cjones: this code could be shared with
// FileDescriptorWatcher. ironic that libevent is "more"
// object-oriented than this C++
event* e = ReleaseEvent();
if (e == NULL)
return true;
// event_del() is a no-op if the event isn't active.
int rv = event_del(e);
delete e;
return (rv == 0);
}
event *
MessagePumpLibevent::SignalEvent::ReleaseEvent()
{
event *e = event_;
event_ = NULL;
return e;
}
bool
MessagePumpLibevent::CatchSignal(int sig,
SignalEvent* sigevent,
SignalWatcher* delegate)
{
DCHECK(sig > 0);
DCHECK(sigevent);
DCHECK(delegate);
// TODO if we want to support re-using SignalEvents, this code needs
// to jump through the same hoops as WatchFileDescriptor(). Not
// needed at present
DCHECK(NULL == sigevent->event_);
scoped_ptr<event> evt(new event);
signal_set(evt.get(), sig, OnLibeventSignalNotification, delegate);
if (event_base_set(event_base_, evt.get()))
return false;
if (signal_add(evt.get(), NULL))
return false;
// Transfer ownership of evt to controller.
sigevent->Init(evt.release());
return true;
}
void
MessagePumpLibevent::OnLibeventSignalNotification(int sig, short flags,
void* context)
{
DCHECK(sig > 0);
DCHECK(EV_SIGNAL == flags);
DCHECK(context);
reinterpret_cast<SignalWatcher*>(context)->OnSignal(sig);
}
#endif // defined(CHROMIUM_MOZILLA_BUILD)
// Reentrant!
void MessagePumpLibevent::Run(Delegate* delegate) {
DCHECK(keep_running_) << "Quit must have been called outside of Run!";

View File

@ -84,6 +84,54 @@ class MessagePumpLibevent : public MessagePump {
FileDescriptorWatcher *controller,
Watcher *delegate);
#if defined(CHROMIUM_MOZILLA_BUILD)
// This is analagous to FileDescriptorWatcher above, which really is
// just a wrapper around libevent's |struct event|. This class acts
// as a sort of "scoped event watcher" in that it guarantees that
// when this class is out of scope, the signal-event it wraps is
// removed from libevent's guts.
//
// XXX/cjones: this isn't my favorite API, but preserving it in
// order to match code above
class SignalEvent {
friend class MessagePumpLibevent;
public:
SignalEvent();
~SignalEvent(); // implicitly calls StopCatching()
// Have libevent forget this event.
bool StopCatching();
private:
void Init(event* e);
event* ReleaseEvent();
event* event_;
DISALLOW_COPY_AND_ASSIGN(SignalEvent);
};
class SignalWatcher {
public:
virtual ~SignalWatcher() {}
// Called from MessageLoop::Run when |sig| has been delivered to
// this process
virtual void OnSignal(int sig) = 0;
};
// Have the current thread's message loop catch the signal |sig|.
// Multiple watchers can catch the same signal; they're all notified
// upon its delivery. Callers must provide a preallocated
// SignalEvent object which can be used to manage the lifetime of
// this event. Returns true on success.
bool CatchSignal(int sig,
SignalEvent* sigevent,
SignalWatcher* delegate);
#endif // defined(CHROMIUM_MOZILLA_BUILD)
// MessagePump methods:
virtual void Run(Delegate* delegate);
virtual void Quit();
@ -112,6 +160,12 @@ class MessagePumpLibevent : public MessagePump {
static void OnLibeventNotification(int fd, short flags,
void* context);
#if defined(CHROMIUM_MOZILLA_BUILD)
// Called by libevent upon receiving a signal
static void OnLibeventSignalNotification(int sig, short flags,
void* context);
#endif
// Unix pipe used to implement ScheduleWork()
// ... callback; called by libevent inside Run() when pipe is ready to read
static void OnWakeup(int socket, short flags, void* context);