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)#include "base/message_loop/message_pump_libevent.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <unistd.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/bind.h"
107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)#include "base/message_loop/message_loop.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/posix/eintr_wrapper.h"
125c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include "base/run_loop.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/thread.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/libevent/event.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace base {
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MessagePumpLibeventTest : public testing::Test {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibeventTest()
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ui_loop_(MessageLoop::TYPE_UI),
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        io_thread_("MessagePumpLibeventTestIOThread") {}
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~MessagePumpLibeventTest() {}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Thread::Options options(MessageLoop::TYPE_IO, 0);
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(io_thread_.StartWithOptions(options));
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_EQ(MessageLoop::TYPE_IO, io_thread_.message_loop()->type());
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int ret = pipe(pipefds_);
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ASSERT_EQ(0, ret);
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE {
35a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(pipefds_[0])) < 0)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(ERROR) << "close";
37a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    if (IGNORE_EINTR(close(pipefds_[1])) < 0)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PLOG(ERROR) << "close";
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop* ui_loop() { return &ui_loop_; }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoopForIO* io_loop() const {
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return static_cast<MessageLoopForIO*>(io_thread_.message_loop());
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void OnLibeventNotification(
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessagePumpLibevent* pump,
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessagePumpLibevent::FileDescriptorWatcher* controller) {
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    pump->OnLibeventNotification(0, EV_WRITE | EV_READ, controller);
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int pipefds_[2];
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessageLoop ui_loop_;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Thread io_thread_;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Concrete implementation of MessagePumpLibevent::Watcher that does
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// nothing useful.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StupidWatcher : public MessagePumpLibevent::Watcher {
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~StupidWatcher() {}
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base:MessagePumpLibevent::Watcher interface
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanReadWithoutBlocking(int fd) OVERRIDE {}
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int fd) OVERRIDE {}
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test to make sure that we catch calling WatchFileDescriptor off of the
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// wrong thread.
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MessagePumpLibeventTest, TestWatchingFromBadThread) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibevent::FileDescriptorWatcher watcher;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StupidWatcher delegate;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_DEATH(io_loop()->WatchFileDescriptor(
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      STDOUT_FILENO, false, MessageLoopForIO::WATCH_READ, &watcher, &delegate),
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Check failed: "
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      "watch_file_descriptor_caller_checker_.CalledOnValidThread\\(\\)");
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(MessagePumpLibeventTest, QuitOutsideOfRun) {
875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  ASSERT_DEATH(pump->Quit(), "Check failed: in_run_. "
895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             "Quit was called outside of Run!");
905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // GTEST_HAS_DEATH_TEST && !defined(NDEBUG)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BaseWatcher : public MessagePumpLibevent::Watcher {
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit BaseWatcher(MessagePumpLibevent::FileDescriptorWatcher* controller)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : controller_(controller) {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(controller_);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~BaseWatcher() {}
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // base:MessagePumpLibevent::Watcher interface
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibevent::FileDescriptorWatcher* controller_;
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DeleteWatcher : public BaseWatcher {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit DeleteWatcher(
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessagePumpLibevent::FileDescriptorWatcher* controller)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseWatcher(controller) {}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~DeleteWatcher() {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(!controller_);
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(controller_);
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    delete controller_;
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_ = NULL;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MessagePumpLibeventTest, DeleteWatcher) {
133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibevent::FileDescriptorWatcher* watcher =
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      new MessagePumpLibevent::FileDescriptorWatcher;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DeleteWatcher delegate(watcher);
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->WatchFileDescriptor(pipefds_[1],
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false, MessagePumpLibevent::WATCH_READ_WRITE, watcher, &delegate);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Spoof a libevent notification.
141868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OnLibeventNotification(pump.get(), watcher);
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class StopWatcher : public BaseWatcher {
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit StopWatcher(
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      MessagePumpLibevent::FileDescriptorWatcher* controller)
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : BaseWatcher(controller) {}
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual ~StopWatcher() {}
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    controller_->StopWatchingFileDescriptor();
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(MessagePumpLibeventTest, StopWatcher) {
158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch  scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  MessagePumpLibevent::FileDescriptorWatcher watcher;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  StopWatcher delegate(&watcher);
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  pump->WatchFileDescriptor(pipefds_[1],
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      false, MessagePumpLibevent::WATCH_READ_WRITE, &watcher, &delegate);
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Spoof a libevent notification.
165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  OnLibeventNotification(pump.get(), &watcher);
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuvoid QuitMessageLoopAndStart(const Closure& quit_closure) {
1695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  quit_closure.Run();
1705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MessageLoop::ScopedNestableTaskAllower allow(MessageLoop::current());
1725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  RunLoop runloop;
1735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MessageLoop::current()->PostTask(FROM_HERE, runloop.QuitClosure());
1745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  runloop.Run();
1755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
1765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liuclass NestedPumpWatcher : public MessagePumpLibevent::Watcher {
1785c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu public:
1795c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NestedPumpWatcher() {}
1805c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual ~NestedPumpWatcher() {}
1815c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1825c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void OnFileCanReadWithoutBlocking(int /* fd */) OVERRIDE {
1835c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    RunLoop runloop;
1845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    MessageLoop::current()->PostTask(FROM_HERE, Bind(&QuitMessageLoopAndStart,
1855c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                                     runloop.QuitClosure()));
1865c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    runloop.Run();
1875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
1885c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  virtual void OnFileCanWriteWithoutBlocking(int /* fd */) OVERRIDE {}
1905c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu};
1915c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1925c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo LiuTEST_F(MessagePumpLibeventTest, NestedPumpWatcher) {
1935c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  scoped_ptr<MessagePumpLibevent> pump(new MessagePumpLibevent);
1945c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  MessagePumpLibevent::FileDescriptorWatcher watcher;
1955c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  NestedPumpWatcher delegate;
1965c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  pump->WatchFileDescriptor(pipefds_[1],
1975c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      false, MessagePumpLibevent::WATCH_READ, &watcher, &delegate);
1985c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
1995c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // Spoof a libevent notification.
2005c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  OnLibeventNotification(pump.get(), &watcher);
2015c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu}
2025c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace base
206