OSDN Git Service

Common: remove GD related stuff from common
authorJack He <siyuanh@google.com>
Mon, 1 Apr 2019 23:20:14 +0000 (16:20 -0700)
committerJack He <siyuanh@google.com>
Tue, 2 Apr 2019 18:11:04 +0000 (11:11 -0700)
* Remove reactor, thread, handler, alarm, repeating alarm from common/
  since they are already copied into gd/os
* Extract thread and alarm benchmarks into gd:bluetooth_benchmark_gd
* Enable host side unit tests for system/bt in TEST_MAPPING

Bug: 129537494
Test: run benchmark, run unit tests
Change-Id: Id5d7592067bab3275976dfc710e4d751c43b9df8

25 files changed:
TEST_MAPPING
common/Android.bp
common/alarm.cc [deleted file]
common/alarm.h [deleted file]
common/alarm_unittest.cc [deleted file]
common/benchmark/thread_performance_benchmark.cc
common/benchmark/timer_performance_benchmark.cc
common/handler.cc [deleted file]
common/handler.h [deleted file]
common/handler_unittest.cc [deleted file]
common/reactor.cc [deleted file]
common/reactor.h [deleted file]
common/reactor_unittest.cc [deleted file]
common/repeating_alarm.cc [deleted file]
common/repeating_alarm.h [deleted file]
common/repeating_alarm_unittest.cc [deleted file]
common/thread.cc [deleted file]
common/thread.h [deleted file]
common/thread_unittest.cc [deleted file]
gd/Android.bp
gd/benchmark.cc [new file with mode: 0644]
gd/os/Android.bp
gd/os/alarm_benchmark.cc [new file with mode: 0644]
gd/os/linux_generic/handler_unittest.cc
gd/os/thread_benchmark.cc [new file with mode: 0644]

index f090f04..5f6e378 100644 (file)
@@ -50,7 +50,9 @@
     },
     {
       "name" : "net_test_types"
-    },
+    }
+  ],
+  "presubmit" : [
     {
       "name" : "bluetooth_test_common",
       "host" : true
index 0dd1fa2..202559d 100644 (file)
@@ -11,15 +11,10 @@ cc_library_static {
     ],
     srcs: [
         "address_obfuscator.cc",
-        "alarm.cc",
-        "handler.cc",
         "message_loop_thread.cc",
         "metrics.cc",
         "once_timer.cc",
-        "reactor.cc",
-        "repeating_alarm.cc",
         "repeating_timer.cc",
-        "thread.cc",
         "time_util.cc",
     ],
     shared_libs: [
@@ -44,17 +39,12 @@ cc_test {
     ],
     srcs : [
         "address_obfuscator_unittest.cc",
-        "alarm_unittest.cc",
-        "handler_unittest.cc",
         "leaky_bonded_queue_unittest.cc",
         "message_loop_thread_unittest.cc",
         "metrics_unittest.cc",
         "once_timer_unittest.cc",
-        "reactor_unittest.cc",
-        "repeating_alarm_unittest.cc",
         "repeating_timer_unittest.cc",
         "state_machine_unittest.cc",
-        "thread_unittest.cc",
         "time_util_unittest.cc",
         "id_generator_unittest.cc",
     ],
diff --git a/common/alarm.cc b/common/alarm.cc
deleted file mode 100644 (file)
index 247acb2..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "alarm.h"
-
-#include <sys/timerfd.h>
-#include <cstring>
-
-#include "base/logging.h"
-#include "utils.h"
-
-namespace bluetooth {
-namespace common {
-
-Alarm::Alarm(Thread* thread)
-  : thread_(thread),
-    fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
-  CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
-
-  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
-}
-
-Alarm::~Alarm() {
-  thread_->GetReactor()->Unregister(token_);
-
-  int close_status;
-  RUN_NO_INTR(close_status = close(fd_));
-  CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
-}
-
-void Alarm::Schedule(Closure task, std::chrono::milliseconds delay) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  long delay_ms = delay.count();
-  itimerspec timer_itimerspec{
-    {/* interval for periodic timer */},
-    {delay_ms / 1000, delay_ms % 1000 * 1000000}
-  };
-  int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
-  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
-
-  task_ = std::move(task);
-}
-
-void Alarm::Cancel() {
-  std::lock_guard<std::mutex> lock(mutex_);
-  itimerspec disarm_itimerspec{/* disarm timer */};
-  int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
-  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
-}
-
-void Alarm::on_fire() {
-  std::unique_lock<std::mutex> lock(mutex_);
-  auto task = std::move(task_);
-  uint64_t times_invoked;
-  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
-  lock.unlock();
-  task();
-  CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
-  CHECK_EQ(times_invoked, static_cast<uint64_t>(1));
-}
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/alarm.h b/common/alarm.h
deleted file mode 100644 (file)
index 1b35b8f..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <functional>
-#include <memory>
-#include <mutex>
-
-#include "common/thread.h"
-#include "common/utils.h"
-
-namespace bluetooth {
-namespace common {
-
-// A single-shot alarm for reactor-based thread, implemented by Linux timerfd.
-// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
-// itself from the thread.
-class Alarm {
- public:
-  // Create and register a single-shot alarm on given thread
-  explicit Alarm(Thread* thread);
-
-  // Unregister this alarm from the thread and release resource
-  ~Alarm();
-
-  DISALLOW_COPY_AND_ASSIGN(Alarm);
-
-  // Schedule the alarm with given delay
-  void Schedule(Closure task, std::chrono::milliseconds delay);
-
-  // Cancel the alarm. No-op if it's not armed.
-  void Cancel();
-
- private:
-  Closure task_;
-  Thread* thread_;
-  int fd_ = 0;
-  Reactor::Reactable* token_;
-  mutable std::mutex mutex_;
-  void on_fire();
-};
-
-}  // namespace common
-
-}  // namespace bluetooth
diff --git a/common/alarm_unittest.cc b/common/alarm_unittest.cc
deleted file mode 100644 (file)
index 25c20ad..0000000
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "alarm.h"
-
-#include <future>
-
-#include "base/logging.h"
-#include "gtest/gtest.h"
-
-namespace bluetooth {
-namespace common {
-namespace {
-
-class AlarmTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
-    alarm_ = new Alarm(thread_);
-  }
-
-  void TearDown() override {
-    delete alarm_;
-    delete thread_;
-  }
-  Alarm* alarm_;
-
- private:
-  Thread* thread_;
-};
-
-TEST_F(AlarmTest, cancel_while_not_armed) {
-  alarm_->Cancel();
-}
-
-TEST_F(AlarmTest, schedule) {
-  std::promise<void> promise;
-  auto future = promise.get_future();
-  auto before = std::chrono::steady_clock::now();
-  int delay_ms = 10;
-  int delay_error_ms = 3;
-  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(delay_ms));
-  future.get();
-  auto after = std::chrono::steady_clock::now();
-  auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
-  ASSERT_NEAR(duration_ms.count(), delay_ms, delay_error_ms);
-}
-
-TEST_F(AlarmTest, cancel_alarm) {
-  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(3));
-  alarm_->Cancel();
-  std::this_thread::sleep_for(std::chrono::milliseconds(5));
-}
-
-TEST_F(AlarmTest, cancel_alarm_from_callback) {
-  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
-  std::this_thread::sleep_for(std::chrono::milliseconds(5));
-}
-
-TEST_F(AlarmTest, schedule_while_alarm_armed) {
-  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
-  std::promise<void> promise;
-  auto future = promise.get_future();
-  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
-  future.get();
-}
-
-TEST_F(AlarmTest, delete_while_alarm_armed) {
-  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
-  delete alarm_;
-  alarm_ = nullptr;
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
-}
-
-}  // namespace
-}  // namespace common
-}  // namespace bluetooth
index 01f332f..74f157f 100644 (file)
 #include <memory>
 #include <thread>
 
-#include "common/handler.h"
 #include "common/message_loop_thread.h"
-#include "common/thread.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/thread.h"
 
 using ::benchmark::State;
-using bluetooth::common::Handler;
 using bluetooth::common::MessageLoopThread;
-using bluetooth::common::Thread;
 
 #define NUM_MESSAGES_TO_SEND 100000
 
@@ -423,54 +419,6 @@ BENCHMARK_F(BM_LibChromeThread, sequential_execution)(State& state) {
   }
 };
 
-class BM_ReactorThread : public BM_ThreadPerformance {
- protected:
-  void SetUp(State& st) override {
-    BM_ThreadPerformance::SetUp(st);
-    std::future<void> set_up_future = set_up_promise_->get_future();
-    thread_ = new Thread("BM_ReactorThread thread", Thread::Priority::NORMAL);
-    handler_ = new Handler(thread_);
-    handler_->Post([this]() { set_up_promise_->set_value(); });
-    set_up_future.wait();
-  }
-
-  void TearDown(State& st) override {
-    delete handler_;
-    handler_ = nullptr;
-    thread_->Stop();
-    delete thread_;
-    thread_ = nullptr;
-    BM_ThreadPerformance::TearDown(st);
-  }
-
-  Thread* thread_ = nullptr;
-  Handler* handler_ = nullptr;
-};
-
-BENCHMARK_F(BM_ReactorThread, batch_enque_dequeue)(State& state) {
-  for (auto _ : state) {
-    g_counter = 0;
-    g_counter_promise = std::make_unique<std::promise<void>>();
-    std::future<void> counter_future = g_counter_promise->get_future();
-    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
-      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
-      handler_->Post([this]() { callback_batch(bt_msg_queue_, nullptr); });
-    }
-    counter_future.wait();
-  }
-};
-
-BENCHMARK_F(BM_ReactorThread, sequential_execution)(State& state) {
-  for (auto _ : state) {
-    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
-      g_counter_promise = std::make_unique<std::promise<void>>();
-      std::future<void> counter_future = g_counter_promise->get_future();
-      handler_->Post([]() { callback_sequential(nullptr); });
-      counter_future.wait();
-    }
-  }
-};
-
 int main(int argc, char** argv) {
   // Disable LOG() output from libchrome
   logging::LoggingSettings log_settings;
index 2f7826b..deaaad8 100644 (file)
 #include <benchmark/benchmark.h>
 #include <future>
 
-#include "common/alarm.h"
 #include "common/message_loop_thread.h"
 #include "common/once_timer.h"
-#include "common/repeating_alarm.h"
 #include "common/repeating_timer.h"
-#include "common/thread.h"
 #include "common/time_util.h"
 #include "osi/include/alarm.h"
 
 using ::benchmark::State;
-using bluetooth::common::Alarm;
 using bluetooth::common::MessageLoopThread;
 using bluetooth::common::OnceTimer;
-using bluetooth::common::RepeatingAlarm;
 using bluetooth::common::RepeatingTimer;
-using bluetooth::common::Thread;
 using bluetooth::common::time_get_os_boottime_us;
 
 // fake get_main_message_loop implementation for alarm
@@ -274,88 +268,6 @@ BENCHMARK_REGISTER_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy)
     ->Iterations(1)
     ->UseRealTime();
 
-class BM_ReactableAlarm : public ::benchmark::Fixture {
- protected:
-  void SetUp(State& st) override {
-    ::benchmark::Fixture::SetUp(st);
-    thread_ = std::make_unique<Thread>("timer_benchmark", Thread::Priority::REAL_TIME);
-    alarm_ = std::make_unique<Alarm>(thread_.get());
-    repeating_alarm_ = std::make_unique<RepeatingAlarm>(thread_.get());
-    g_map.clear();
-    g_promise = std::make_shared<std::promise<void>>();
-    g_scheduled_tasks = 0;
-    g_task_length = 0;
-    g_task_interval = 0;
-    g_task_counter = 0;
-  }
-
-  void TearDown(State& st) override {
-    g_promise = nullptr;
-    alarm_ = nullptr;
-    repeating_alarm_ = nullptr;
-    thread_->Stop();
-    thread_ = nullptr;
-    ::benchmark::Fixture::TearDown(st);
-  }
-
-  std::unique_ptr<Thread> thread_;
-  std::unique_ptr<Alarm> alarm_;
-  std::unique_ptr<RepeatingAlarm> repeating_alarm_;
-};
-
-BENCHMARK_DEFINE_F(BM_ReactableAlarm, timer_performance_ms)(State& state) {
-  auto milliseconds = static_cast<int>(state.range(0));
-  for (auto _ : state) {
-    auto start_time_point = time_get_os_boottime_us();
-    alarm_->Schedule(std::bind(TimerFire, nullptr), std::chrono::milliseconds(milliseconds));
-    g_promise->get_future().get();
-    auto end_time_point = time_get_os_boottime_us();
-    auto duration = end_time_point - start_time_point;
-    state.SetIterationTime(duration * 1e-6);
-    alarm_->Cancel();
-  }
-};
-
-BENCHMARK_REGISTER_F(BM_ReactableAlarm, timer_performance_ms)
-    ->Arg(1)
-    ->Arg(5)
-    ->Arg(10)
-    ->Arg(20)
-    ->Arg(100)
-    ->Arg(1000)
-    ->Arg(2000)
-    ->Iterations(1)
-    ->UseRealTime();
-
-BENCHMARK_DEFINE_F(BM_ReactableAlarm, periodic_accuracy)
-(State& state) {
-  for (auto _ : state) {
-    g_scheduled_tasks = state.range(0);
-    g_task_length = state.range(1);
-    g_task_interval = state.range(2);
-    g_start_time = time_get_os_boottime_us();
-    repeating_alarm_->Schedule([] { AlarmSleepAndCountDelayedTime(nullptr); },
-                               std::chrono::milliseconds(g_task_interval));
-    g_promise->get_future().get();
-    repeating_alarm_->Cancel();
-  }
-  for (const auto& delay : g_map) {
-    state.counters[std::to_string(delay.first)] = delay.second;
-  }
-};
-
-BENCHMARK_REGISTER_F(BM_ReactableAlarm, periodic_accuracy)
-    ->Args({2000, 1, 5})
-    ->Args({2000, 3, 5})
-    ->Args({2000, 1, 7})
-    ->Args({2000, 3, 7})
-    ->Args({2000, 1, 20})
-    ->Args({2000, 5, 20})
-    ->Args({2000, 10, 20})
-    ->Args({2000, 15, 20})
-    ->Iterations(1)
-    ->UseRealTime();
-
 int main(int argc, char** argv) {
   // Disable LOG() output from libchrome
   logging::LoggingSettings log_settings;
diff --git a/common/handler.cc b/common/handler.cc
deleted file mode 100644 (file)
index 219dd82..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "handler.h"
-
-#include <sys/eventfd.h>
-#include <cstring>
-
-#include "base/logging.h"
-
-#include "reactor.h"
-#include "utils.h"
-
-#ifndef EFD_SEMAPHORE
-#define EFD_SEMAPHORE 1
-#endif
-
-namespace bluetooth {
-namespace common {
-
-Handler::Handler(Thread* thread)
-  : thread_(thread),
-    fd_(eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) {
-  CHECK_NE(fd_, -1) << __func__ << ": cannot create eventfd: " << strerror(errno);
-
-  reactable_ = thread_->GetReactor()->Register(fd_, [this] { this->handle_next_event(); }, nullptr);
-}
-
-Handler::~Handler() {
-  thread_->GetReactor()->Unregister(reactable_);
-  reactable_ = nullptr;
-
-  int close_status;
-  RUN_NO_INTR(close_status = close(fd_));
-  CHECK_NE(close_status, -1) << __func__ << ": cannot close eventfd: " << strerror(errno);
-}
-
-void Handler::Post(Closure closure) {
-  {
-    std::lock_guard<std::mutex> lock(mutex_);
-    tasks_.emplace(std::move(closure));
-  }
-  uint64_t val = 1;
-  auto write_result = eventfd_write(fd_, val);
-  CHECK_NE(write_result, -1) << __func__ << ": failed to write: " << strerror(errno);
-}
-
-void Handler::Clear() {
-  std::lock_guard<std::mutex> lock(mutex_);
-
-  std::queue<Closure> empty;
-  std::swap(tasks_, empty);
-
-  uint64_t val;
-  while (eventfd_read(fd_, &val) == 0) {
-  }
-}
-
-void Handler::handle_next_event() {
-  Closure closure;
-  uint64_t val = 0;
-  auto read_result = eventfd_read(fd_, &val);
-  CHECK_NE(read_result, -1) << __func__ << ": failed to read fd: " << strerror(errno);
-
-  {
-    std::lock_guard<std::mutex> lock(mutex_);
-    closure = std::move(tasks_.front());
-    tasks_.pop();
-  }
-  closure();
-}
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/handler.h b/common/handler.h
deleted file mode 100644 (file)
index 71b4dba..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <functional>
-#include <memory>
-#include <mutex>
-#include <queue>
-
-#include "common/thread.h"
-#include "common/utils.h"
-
-namespace bluetooth {
-namespace common {
-
-// A message-queue style handler for reactor-based thread to handle incoming events from different threads. When it's
-// constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister itself
-// from the thread.
-class Handler {
- public:
-  // Create and register a handler on given thread
-  explicit Handler(Thread* thread);
-
-  // Unregister this handler from the thread and release resource. Unhandled events will be discarded and not executed.
-  ~Handler();
-
-  DISALLOW_COPY_AND_ASSIGN(Handler);
-
-  // Enqueue a closure to the queue of this handler
-  void Post(Closure closure);
-
-  // Remove all pending events from the queue of this handler
-  void Clear();
-
- private:
-  std::queue<Closure> tasks_;
-  Thread* thread_;
-  int fd_;
-  Reactor::Reactable* reactable_;
-  mutable std::mutex mutex_;
-  void handle_next_event();
-};
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/handler_unittest.cc b/common/handler_unittest.cc
deleted file mode 100644 (file)
index 1850140..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "handler.h"
-
-#include <sys/eventfd.h>
-#include <thread>
-
-#include <gtest/gtest.h>
-#include "base/logging.h"
-
-namespace bluetooth {
-namespace common {
-namespace {
-
-class HandlerTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
-    handler_ = new Handler(thread_);
-  }
-  void TearDown() override {
-    delete handler_;
-    delete thread_;
-  }
-
-  Handler* handler_;
-  Thread* thread_;
-};
-
-TEST_F(HandlerTest, empty) {}
-
-TEST_F(HandlerTest, post_task_invoked) {
-  int val = 0;
-  Closure closure = [&val]() { val++; };
-  handler_->Post(closure);
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
-  EXPECT_EQ(val, 1);
-}
-
-TEST_F(HandlerTest, post_task_cleared) {
-  int val = 0;
-  Closure closure = [&val]() {
-    val++;
-    std::this_thread::sleep_for(std::chrono::milliseconds(5));
-  };
-  handler_->Post(std::move(closure));
-  closure = []() { EXPECT_EQ(0, 1) << "Should not happen"; };
-  std::this_thread::sleep_for(std::chrono::milliseconds(5));
-  handler_->Post(std::move(closure));
-  handler_->Clear();
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
-  EXPECT_EQ(val, 1);
-}
-
-TEST_F(HandlerTest, post_task_from_callback) {
-  int val = 0;
-  Closure closure = [&val, this] {
-    Closure inner_closure = [&val] { val++; };
-    handler_->Post(inner_closure);
-  };
-  handler_->Post(closure);
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
-  EXPECT_EQ(val, 1);
-}
-
-TEST_F(HandlerTest, clear_task_from_callback) {
-  int val = 0;
-  Closure closure = [&val, this] {
-    val++;
-    handler_->Clear();
-    std::this_thread::sleep_for(std::chrono::milliseconds(5));
-  };
-  handler_->Post(std::move(closure));
-  closure = []() { EXPECT_EQ(0, 1) << "Should not happen"; };
-  handler_->Post(std::move(closure));
-  std::this_thread::sleep_for(std::chrono::milliseconds(10));
-  EXPECT_EQ(val, 1);
-}
-
-}  // namespace
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/reactor.cc b/common/reactor.cc
deleted file mode 100644 (file)
index 8097732..0000000
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "reactor.h"
-
-#include <fcntl.h>
-#include <sys/epoll.h>
-#include <sys/eventfd.h>
-#include <unistd.h>
-#include <algorithm>
-#include <cerrno>
-#include <cstring>
-
-#include "base/logging.h"
-
-namespace {
-
-// Use at most sizeof(epoll_event) * kEpollMaxEvents kernel memory
-constexpr int kEpollMaxEvents = 64;
-
-}  // namespace
-
-namespace bluetooth {
-namespace common {
-
-class Reactor::Reactable {
- public:
-  Reactable(int fd, Closure on_read_ready, Closure on_write_ready)
-      : fd_(fd),
-        on_read_ready_(std::move(on_read_ready)),
-        on_write_ready_(std::move(on_write_ready)),
-        is_executing_(false) {}
-  const int fd_;
-  Closure on_read_ready_;
-  Closure on_write_ready_;
-  bool is_executing_;
-  std::recursive_mutex lock_;
-};
-
-Reactor::Reactor()
-  : epoll_fd_(0),
-    control_fd_(0),
-    is_running_(false),
-    reactable_removed_(false) {
-  RUN_NO_INTR(epoll_fd_ = epoll_create1(EPOLL_CLOEXEC));
-  CHECK_NE(epoll_fd_, -1) << __func__ << ": cannot create epoll_fd: " << strerror(errno);
-
-  control_fd_ = eventfd(0, EFD_NONBLOCK);
-  CHECK_NE(control_fd_, -1) << __func__ << ": cannot create control_fd: " << strerror(errno);
-
-  epoll_event control_epoll_event = {EPOLLIN, {.ptr = nullptr}};
-  int result;
-  RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, control_fd_, &control_epoll_event));
-  CHECK_NE(result, -1) << __func__ << ": cannot register control_fd: " << strerror(errno);
-}
-
-Reactor::~Reactor() {
-  int result;
-  RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, control_fd_, nullptr));
-  CHECK_NE(result, -1) << __func__ << ": cannot unregister control_fd: " << strerror(errno);
-
-  RUN_NO_INTR(result = close(control_fd_));
-  CHECK_NE(result, -1) << __func__ << ": cannot close control_fd: " << strerror(errno);
-
-  RUN_NO_INTR(result = close(epoll_fd_));
-  CHECK_NE(result, -1) << __func__ << ": cannot close epoll_fd: " << strerror(errno);
-}
-
-void Reactor::Run() {
-  bool previously_running = is_running_.exchange(true);
-  CHECK_EQ(previously_running, false) << __func__ << ": already running";
-  LOG(INFO) << __func__ << ": started";
-
-  for (;;) {
-    invalidation_list_.clear();
-    epoll_event events[kEpollMaxEvents];
-    int count;
-    RUN_NO_INTR(count = epoll_wait(epoll_fd_, events, kEpollMaxEvents, -1));
-    CHECK_NE(count, -1) << __func__ << ": Error polling for fds: " << strerror(errno);
-
-    for (int i = 0; i < count; ++i) {
-      auto event = events[i];
-      CHECK_NE(event.events, 0u) << __func__ << ": no result in epoll result";
-
-      // If the ptr stored in epoll_event.data is nullptr, it means the control fd triggered
-      if (event.data.ptr == nullptr) {
-        uint64_t value;
-        eventfd_read(control_fd_, &value);
-        LOG(INFO) << __func__ << ": stopped";
-        is_running_ = false;
-        return;
-      }
-      auto* reactable = static_cast<Reactor::Reactable*>(event.data.ptr);
-      {
-        std::unique_lock<std::mutex> lock(mutex_);
-        // See if this reactable has been removed in the meantime.
-        if (std::find(invalidation_list_.begin(), invalidation_list_.end(), reactable) != invalidation_list_.end()) {
-          continue;
-        }
-
-        std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
-        lock.unlock();
-        reactable_removed_ = false;
-        reactable->is_executing_ = true;
-        if (event.events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && reactable->on_read_ready_ != nullptr) {
-          reactable->on_read_ready_();
-        }
-        if (!reactable_removed_ && event.events & EPOLLOUT && reactable->on_write_ready_ != nullptr) {
-          reactable->on_write_ready_();
-        }
-        reactable->is_executing_ = false;
-      }
-      if (reactable_removed_) {
-        delete reactable;
-      }
-    }
-  }
-}
-
-void Reactor::Stop() {
-  if (!is_running_) {
-    LOG(WARNING) << __func__ << ": not running, will stop once it's started";
-  }
-  auto control = eventfd_write(control_fd_, 1);
-  CHECK_NE(control, -1) << __func__ << ": failed: " << strerror(errno);
-}
-
-Reactor::Reactable* Reactor::Register(int fd, Closure on_read_ready, Closure on_write_ready) {
-  uint32_t poll_event_type = 0;
-  if (on_read_ready != nullptr) {
-    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
-  }
-  if (on_write_ready != nullptr) {
-    poll_event_type |= EPOLLOUT;
-  }
-  auto* reactable = new Reactable(fd, on_read_ready, on_write_ready);
-  epoll_event event = {
-      .events = poll_event_type,
-      {.ptr = reactable}
-  };
-  int register_fd;
-  RUN_NO_INTR(register_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event));
-  CHECK_NE(register_fd, -1) << __func__ << ": failed: " << strerror(errno);
-  return reactable;
-}
-
-void Reactor::Unregister(Reactor::Reactable* reactable) {
-  CHECK_NE(reactable, nullptr);
-  {
-    std::lock_guard<std::mutex> lock(mutex_);
-    invalidation_list_.push_back(reactable);
-  }
-  {
-    int result;
-    std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
-    RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, reactable->fd_, nullptr));
-    if (result == -1 && errno == ENOENT) {
-      LOG(INFO) << __func__ << ": reactable is invalid or unregistered";
-    } else if (result == -1) {
-      PLOG(FATAL) << __func__ << ": failed";
-    }
-    // If we are unregistering during the callback event from this reactable, we delete it after the callback is executed.
-    // reactable->is_executing_ is protected by reactable->lock_, so it's thread safe.
-    if (reactable->is_executing_) {
-      reactable_removed_ = true;
-    }
-  }
-  // If we are unregistering outside of the callback event from this reactable, we delete it now
-  if (!reactable_removed_) {
-    delete reactable;
-  }
-}
-
-void Reactor::ModifyRegistration(Reactor::Reactable* reactable, Closure on_read_ready, Closure on_write_ready) {
-  CHECK_NE(reactable, nullptr);
-
-  uint32_t poll_event_type = 0;
-  if (on_read_ready != nullptr) {
-    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
-  }
-  if (on_write_ready != nullptr) {
-    poll_event_type |= EPOLLOUT;
-  }
-  {
-    std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
-    reactable->on_read_ready_ = std::move(on_read_ready);
-    reactable->on_write_ready_ = std::move(on_write_ready);
-  }
-  epoll_event event = {
-      .events = poll_event_type,
-      {.ptr = reactable}
-  };
-  int modify_fd;
-  RUN_NO_INTR(modify_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, reactable->fd_, &event));
-  CHECK_NE(modify_fd, -1) << __func__ << ": failed: " << strerror(errno);
-}
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/reactor.h b/common/reactor.h
deleted file mode 100644 (file)
index 27528ce..0000000
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <sys/epoll.h>
-#include <atomic>
-#include <functional>
-#include <list>
-#include <mutex>
-#include <thread>
-
-#include "common/utils.h"
-
-namespace bluetooth {
-namespace common {
-
-// Format of closure to be used in the entire stack
-using Closure = std::function<void()>;
-
-// A simple implementation of reactor-style looper.
-// When a reactor is running, the main loop is polling and blocked until at least one registered reactable is ready to
-// read or write. It will invoke on_read_ready() or on_write_ready(), which is registered with the reactor. Then, it
-// blocks again until ready event.
-class Reactor {
- public:
-  // An object used for Unregister() and ModifyRegistration()
-  class Reactable;
-
-  // Construct a reactor on the current thread
-  Reactor();
-
-  // Destruct this reactor and release its resources
-  ~Reactor();
-
-  DISALLOW_COPY_AND_ASSIGN(Reactor);
-
-  // Start the reactor. The current thread will be blocked until Stop() is invoked and handled.
-  void Run();
-
-  // Stop the reactor. Must be invoked from a different thread. Note: all registered reactables will not be unregistered
-  // by Stop(). If the reactor is not running, it will be stopped once it's started.
-  void Stop();
-
-  // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this object to
-  // unregister or modify registration. Ownership of the memory space is NOT transferred to user.
-  Reactable* Register(int fd, Closure on_read_ready, Closure on_write_ready);
-
-  // Unregister a reactable from this reactor
-  void Unregister(Reactable* reactable);
-
-  // Modify the registration for a reactable with given reactable
-  void ModifyRegistration(Reactable* reactable, Closure on_read_ready, Closure on_write_ready);
-
- private:
-  mutable std::mutex mutex_;
-  int epoll_fd_;
-  int control_fd_;
-  std::atomic<bool> is_running_;
-  std::list<Reactable*> invalidation_list_;
-  bool reactable_removed_;
-};
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/reactor_unittest.cc b/common/reactor_unittest.cc
deleted file mode 100644 (file)
index 5c7e90e..0000000
+++ /dev/null
@@ -1,283 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "reactor.h"
-
-#include <sys/eventfd.h>
-#include <chrono>
-#include <future>
-#include <thread>
-
-#include "base/logging.h"
-#include "gtest/gtest.h"
-
-namespace bluetooth {
-namespace common {
-namespace {
-
-constexpr int kReadReadyValue = 100;
-
-std::promise<int>* g_promise;
-
-class ReactorTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    g_promise = new std::promise<int>;
-    reactor_ = new Reactor;
-  }
-
-  void TearDown() override {
-    delete g_promise;
-    g_promise = nullptr;
-    delete reactor_;
-    reactor_ = nullptr;
-  }
-
-  Reactor* reactor_;
-};
-
-class SampleReactable {
- public:
-  SampleReactable() : fd_(eventfd(0, EFD_NONBLOCK)) {
-    EXPECT_NE(fd_, 0);
-  }
-
-  ~SampleReactable() {
-    close(fd_);
-  }
-
-  void OnReadReady() {}
-
-  void OnWriteReady() {}
-
-  int fd_;
-};
-
-class FakeReactable {
- public:
-  enum EventFdValue {
-    kSetPromise = 1,
-    kRegisterSampleReactable,
-    kUnregisterSampleReactable,
-    kSampleOutputValue,
-  };
-  FakeReactable() : fd_(eventfd(0, 0)), reactor_(nullptr) {
-    EXPECT_NE(fd_, 0);
-  }
-
-  FakeReactable(Reactor* reactor) : fd_(eventfd(0, 0)), reactor_(reactor) {
-    EXPECT_NE(fd_, 0);
-  }
-
-  ~FakeReactable() {
-    close(fd_);
-  }
-
-  void OnReadReady() {
-    uint64_t value = 0;
-    auto read_result = eventfd_read(fd_, &value);
-    EXPECT_EQ(read_result, 0);
-    if (value == kSetPromise && g_promise != nullptr) {
-      g_promise->set_value(kReadReadyValue);
-    }
-    if (value == kRegisterSampleReactable) {
-      reactable_ = reactor_->Register(sample_reactable_.fd_, [this] { this->sample_reactable_.OnReadReady(); },
-                                      [this] { this->sample_reactable_.OnWriteReady(); });
-      g_promise->set_value(kReadReadyValue);
-    }
-    if (value == kUnregisterSampleReactable) {
-      reactor_->Unregister(reactable_);
-      g_promise->set_value(kReadReadyValue);
-    }
-  }
-
-  void OnWriteReady() {
-    auto write_result = eventfd_write(fd_, output_data_);
-    output_data_ = 0;
-    EXPECT_EQ(write_result, 0);
-  }
-
-  SampleReactable sample_reactable_;
-  Reactor::Reactable* reactable_ = nullptr;
-  int fd_;
-
- private:
-  Reactor* reactor_;
-  uint64_t output_data_ = kSampleOutputValue;
-};
-
-TEST_F(ReactorTest, start_and_stop) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  reactor_->Stop();
-  reactor_thread.join();
-}
-
-TEST_F(ReactorTest, stop_and_start) {
-  auto reactor_thread = std::thread(&Reactor::Stop, reactor_);
-  auto another_thread = std::thread(&Reactor::Run, reactor_);
-  reactor_thread.join();
-  another_thread.join();
-}
-
-TEST_F(ReactorTest, stop_multi_times) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  for (int i = 0; i < 5; i++) {
-    reactor_->Stop();
-  }
-  reactor_thread.join();
-}
-
-TEST_F(ReactorTest, cold_register_only) {
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-
-  reactor_->Unregister(reactable);
-}
-
-TEST_F(ReactorTest, cold_register) {
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  auto future = g_promise->get_future();
-
-  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
-  EXPECT_EQ(write_result, 0);
-  EXPECT_EQ(future.get(), kReadReadyValue);
-  reactor_->Stop();
-  reactor_thread.join();
-  reactor_->Unregister(reactable);
-}
-
-TEST_F(ReactorTest, hot_register_from_different_thread) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  auto future = g_promise->get_future();
-
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
-  EXPECT_EQ(write_result, 0);
-  EXPECT_EQ(future.get(), kReadReadyValue);
-  reactor_->Stop();
-  reactor_thread.join();
-
-  reactor_->Unregister(reactable);
-}
-
-TEST_F(ReactorTest, hot_unregister_from_different_thread) {
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  reactor_->Unregister(reactable);
-  auto future = g_promise->get_future();
-
-  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
-  EXPECT_EQ(write_result, 0);
-  future.wait_for(std::chrono::milliseconds(10));
-  g_promise->set_value(2);
-  EXPECT_EQ(future.get(), 2);
-  reactor_->Stop();
-  reactor_thread.join();
-}
-
-TEST_F(ReactorTest, hot_register_from_same_thread) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  auto future = g_promise->get_future();
-
-  FakeReactable fake_reactable(reactor_);
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
-  EXPECT_EQ(write_result, 0);
-  EXPECT_EQ(future.get(), kReadReadyValue);
-  reactor_->Stop();
-  reactor_thread.join();
-
-  reactor_->Unregister(reactable);
-}
-
-TEST_F(ReactorTest, hot_unregister_from_same_thread) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  auto future = g_promise->get_future();
-
-  FakeReactable fake_reactable(reactor_);
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
-  EXPECT_EQ(write_result, 0);
-  EXPECT_EQ(future.get(), kReadReadyValue);
-  delete g_promise;
-  g_promise = new std::promise<int>;
-  future = g_promise->get_future();
-  write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
-  EXPECT_EQ(write_result, 0);
-  EXPECT_EQ(future.get(), kReadReadyValue);
-  reactor_->Stop();
-  reactor_thread.join();
-  LOG(INFO);
-
-  reactor_->Unregister(reactable);
-  LOG(INFO);
-}
-
-TEST_F(ReactorTest, start_and_stop_multi_times) {
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  reactor_->Stop();
-  reactor_thread.join();
-  for (int i = 0; i < 5; i++) {
-    reactor_thread = std::thread(&Reactor::Run, reactor_);
-    reactor_->Stop();
-    reactor_thread.join();
-  }
-}
-
-TEST_F(ReactorTest, on_write_ready) {
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  uint64_t value = 0;
-  auto read_result = eventfd_read(fake_reactable.fd_, &value);
-  EXPECT_EQ(read_result, 0);
-  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
-
-  reactor_->Stop();
-  reactor_thread.join();
-
-  reactor_->Unregister(reactable);
-}
-
-TEST_F(ReactorTest, modify_registration) {
-  FakeReactable fake_reactable;
-  auto* reactable =
-      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
-  reactor_->ModifyRegistration(reactable, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
-  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
-  uint64_t value = 0;
-  auto read_result = eventfd_read(fake_reactable.fd_, &value);
-  EXPECT_EQ(read_result, 0);
-  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
-
-  reactor_->Stop();
-  reactor_thread.join();
-}
-
-}  // namespace
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/repeating_alarm.cc b/common/repeating_alarm.cc
deleted file mode 100644 (file)
index 65c9b3a..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "repeating_alarm.h"
-
-#include <sys/timerfd.h>
-#include <cstring>
-
-#include "base/logging.h"
-#include "utils.h"
-
-namespace bluetooth {
-namespace common {
-
-RepeatingAlarm::RepeatingAlarm(Thread* thread)
-  : thread_(thread),
-    fd_(timerfd_create(CLOCK_BOOTTIME_ALARM, 0)) {
-  CHECK_NE(fd_, -1) << __func__ << ": cannot create timerfd: " << strerror(errno);
-
-  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
-}
-
-RepeatingAlarm::~RepeatingAlarm() {
-  thread_->GetReactor()->Unregister(token_);
-
-  int close_status;
-  RUN_NO_INTR(close_status = close(fd_));
-  CHECK_NE(close_status, -1) << __func__ << ": cannot close timerfd: " << strerror(errno);
-}
-
-void RepeatingAlarm::Schedule(Closure task, std::chrono::milliseconds period) {
-  std::lock_guard<std::mutex> lock(mutex_);
-  long period_ms = period.count();
-  itimerspec timer_itimerspec{
-    {period_ms / 1000, period_ms % 1000 * 1000000},
-    {period_ms / 1000, period_ms % 1000 * 1000000}
-  };
-  int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
-  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
-
-  task_ = std::move(task);
-}
-
-void RepeatingAlarm::Cancel() {
-  std::lock_guard<std::mutex> lock(mutex_);
-  itimerspec disarm_itimerspec{/* disarm timer */};
-  int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
-  CHECK_EQ(result, 0) << __func__ << ": failed, error=" << strerror(errno);
-}
-
-void RepeatingAlarm::on_fire() {
-  std::unique_lock<std::mutex> lock(mutex_);
-  auto task = task_;
-  uint64_t times_invoked;
-  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
-  lock.unlock();
-  task();
-  CHECK_EQ(bytes_read, static_cast<ssize_t>(sizeof(uint64_t))) << __func__ << ": failed, error=" << strerror(errno);
-}
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/repeating_alarm.h b/common/repeating_alarm.h
deleted file mode 100644 (file)
index f1f6aa1..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <functional>
-#include <memory>
-#include <mutex>
-
-#include "common/thread.h"
-#include "common/utils.h"
-
-namespace bluetooth {
-namespace common {
-
-// A repeating alarm for reactor-based thread, implemented by Linux timerfd.
-// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
-// itself from the thread.
-class RepeatingAlarm {
- public:
-  // Create and register a repeating alarm on given thread
-  explicit RepeatingAlarm(Thread* thread);
-
-  // Unregister this alarm from the thread and release resource
-  ~RepeatingAlarm();
-
-  DISALLOW_COPY_AND_ASSIGN(RepeatingAlarm);
-
-  // Schedule a repeating alarm with given period
-  void Schedule(Closure task, std::chrono::milliseconds period);
-
-  // Cancel the alarm. No-op if it's not armed.
-  void Cancel();
-
- private:
-  Closure task_;
-  Thread* thread_;
-  int fd_ = 0;
-  Reactor::Reactable* token_;
-  mutable std::mutex mutex_;
-  void on_fire();
-};
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/repeating_alarm_unittest.cc b/common/repeating_alarm_unittest.cc
deleted file mode 100644 (file)
index 3c0f255..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "repeating_alarm.h"
-
-#include <future>
-
-#include "base/logging.h"
-#include "gtest/gtest.h"
-
-namespace bluetooth {
-namespace common {
-namespace {
-
-constexpr int error_ms = 20;
-
-class RepeatingAlarmTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
-    alarm_ = new RepeatingAlarm(thread_);
-  }
-
-  void TearDown() override {
-    delete alarm_;
-    delete thread_;
-  }
-
-  void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
-    std::promise<void> promise;
-    auto future = promise.get_future();
-    auto start_time = std::chrono::steady_clock::now();
-    int counter = 0;
-    alarm_->Schedule(
-        [&counter, &promise, start_time, scheduled_tasks, task_length_ms, interval_between_tasks_ms]() {
-          counter++;
-          auto time_now = std::chrono::steady_clock::now();
-          auto time_delta = time_now - start_time;
-          if (counter == scheduled_tasks) {
-            promise.set_value();
-          }
-          ASSERT_NEAR(time_delta.count(), interval_between_tasks_ms * 1000000 * counter, error_ms * 1000000);
-          std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
-        },
-        std::chrono::milliseconds(interval_between_tasks_ms));
-    future.get();
-    alarm_->Cancel();
-  }
-
-  RepeatingAlarm* alarm_;
-
- private:
-  Thread* thread_;
-};
-
-TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
-  alarm_->Cancel();
-}
-
-TEST_F(RepeatingAlarmTest, schedule) {
-  std::promise<void> promise;
-  auto future = promise.get_future();
-  auto before = std::chrono::steady_clock::now();
-  int period_ms = 10;
-  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(period_ms));
-  future.get();
-  alarm_->Cancel();
-  auto after = std::chrono::steady_clock::now();
-  auto duration = after - before;
-  ASSERT_NEAR(duration.count(), period_ms * 1000000, error_ms * 1000000);
-}
-
-TEST_F(RepeatingAlarmTest, cancel_alarm) {
-  alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
-  alarm_->Cancel();
-  std::this_thread::sleep_for(std::chrono::milliseconds(5));
-}
-
-TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
-  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
-  std::this_thread::sleep_for(std::chrono::milliseconds(5));
-}
-
-TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
-  alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
-  std::promise<void> promise;
-  auto future = promise.get_future();
-  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
-  future.get();
-  alarm_->Cancel();
-}
-
-TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
-  alarm_->Schedule([]() { LOG(FATAL) << "Should not happen"; }, std::chrono::milliseconds(1));
-  delete alarm_;
-  alarm_ = nullptr;
-  std::this_thread::sleep_for(std::chrono::milliseconds(1));
-}
-
-TEST_F(RepeatingAlarmTest, verify_small) {
-  VerifyMultipleDelayedTasks(100, 1, 10);
-}
-
-TEST_F(RepeatingAlarmTest, verify_large) {
-  VerifyMultipleDelayedTasks(100, 3, 10);
-}
-
-}  // namespace
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/thread.cc b/common/thread.cc
deleted file mode 100644 (file)
index 274eee9..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "common/thread.h"
-
-#include <fcntl.h>
-#include <sys/syscall.h>
-#include <cerrno>
-#include <cstring>
-
-#include "base/logging.h"
-
-namespace bluetooth {
-namespace common {
-
-namespace {
-constexpr int kRealTimeFifoSchedulingPriority = 1;
-}
-
-Thread::Thread(const std::string& name, const Priority priority)
-    : name_(name),
-      reactor_(),
-      running_thread_(&Thread::run, this, priority) {}
-
-void Thread::run(Priority priority) {
-  if (priority == Priority::REAL_TIME) {
-    struct sched_param rt_params = {.sched_priority = kRealTimeFifoSchedulingPriority};
-    auto linux_tid = static_cast<pid_t>(syscall(SYS_gettid));
-    int rc;
-    RUN_NO_INTR(rc = sched_setscheduler(linux_tid, SCHED_FIFO, &rt_params));
-    if (rc != 0) {
-      PLOG(ERROR) << __func__ << ": unable to set SCHED_FIFO priority";
-    }
-  }
-  reactor_.Run();
-}
-
-Thread::~Thread() {
-  Stop();
-}
-
-bool Thread::Stop() {
-  std::lock_guard<std::mutex> lock(mutex_);
-  CHECK_NE(std::this_thread::get_id(), running_thread_.get_id());
-
-  if (!running_thread_.joinable()) {
-    return false;
-  }
-  reactor_.Stop();
-  running_thread_.join();
-  return true;
-}
-
-bool Thread::IsSameThread() const {
-  return std::this_thread::get_id() == running_thread_.get_id();
-}
-
-Reactor* Thread::GetReactor() const {
-  return &reactor_;
-}
-
-std::string Thread::GetThreadName() const {
-  return name_;
-}
-
-std::string Thread::ToString() const {
-  return "Thread " + name_;
-}
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/thread.h b/common/thread.h
deleted file mode 100644 (file)
index 09e6b48..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#pragma once
-
-#include <mutex>
-#include <string>
-#include <thread>
-
-#include "common/reactor.h"
-#include "common/utils.h"
-
-namespace bluetooth {
-namespace common {
-
-// Reactor-based looper thread implementation. The thread runs immediately after it is constructed, and stops after
-// Stop() is invoked. To assign task to this thread, user needs to register a reactable object to the underlying
-// reactor.
-class Thread {
- public:
-  // Used by thread constructor. Suggest the priority to the kernel scheduler. Use REAL_TIME if we need (soft) real-time
-  // scheduling guarantee for this thread; use NORMAL if no real-time guarantee is needed to save CPU time slice for
-  // other threads
-  enum class Priority {
-    REAL_TIME,
-    NORMAL,
-  };
-
-  // name: thread name for POSIX systems
-  // priority: priority for kernel scheduler
-  Thread(const std::string& name, Priority priority);
-
-  // Stop and destroy this thread
-  ~Thread();
-
-  DISALLOW_COPY_AND_ASSIGN(Thread);
-
-  // Stop this thread. Must be invoked from another thread. After this thread is stopped, it cannot be started again.
-  bool Stop();
-
-  // Return true if this function is invoked from this thread
-  bool IsSameThread() const;
-
-  // Return the POSIX thread name
-  std::string GetThreadName() const;
-
-  // Return a user-friendly string representation of this thread object
-  std::string ToString() const;
-
-  // Return the pointer of underlying reactor. The ownership is NOT transferred.
-  Reactor* GetReactor() const;
-
- private:
-  void run(Priority priority);
-  mutable std::mutex mutex_;
-  const std::string name_;
-  mutable Reactor reactor_;
-  std::thread running_thread_;
-};
-
-}  // namespace common
-}  // namespace bluetooth
diff --git a/common/thread_unittest.cc b/common/thread_unittest.cc
deleted file mode 100644 (file)
index 678f34d..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * Copyright 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "thread.h"
-
-#include <sys/eventfd.h>
-
-#include "base/logging.h"
-#include "gtest/gtest.h"
-#include "reactor.h"
-
-namespace bluetooth {
-namespace common {
-namespace {
-
-constexpr int kCheckIsSameThread = 1;
-
-class SampleReactable {
- public:
-  explicit SampleReactable(Thread* thread) : thread_(thread), fd_(eventfd(0, 0)), is_same_thread_checked_(false) {
-    EXPECT_NE(fd_, 0);
-  }
-
-  ~SampleReactable() {
-    close(fd_);
-  }
-
-  void OnReadReady() {
-    EXPECT_TRUE(thread_->IsSameThread());
-    is_same_thread_checked_ = true;
-    uint64_t val;
-    eventfd_read(fd_, &val);
-  }
-
-  bool IsSameThreadCheckDone() {
-    return is_same_thread_checked_;
-  }
-
-  Thread* thread_;
-  int fd_;
-  bool is_same_thread_checked_;
-};
-
-class ThreadTest : public ::testing::Test {
- protected:
-  void SetUp() override {
-    thread = new Thread("test", Thread::Priority::NORMAL);
-  }
-
-  void TearDown() override {
-    delete thread;
-  }
-  Thread* thread = nullptr;
-};
-
-TEST_F(ThreadTest, just_stop_no_op) {
-  thread->Stop();
-}
-
-TEST_F(ThreadTest, thread_name) {
-  EXPECT_EQ(thread->GetThreadName(), "test");
-}
-
-TEST_F(ThreadTest, thread_to_string) {
-  EXPECT_NE(thread->ToString().find("test"), std::string::npos);
-}
-
-TEST_F(ThreadTest, not_same_thread) {
-  EXPECT_FALSE(thread->IsSameThread());
-}
-
-TEST_F(ThreadTest, same_thread) {
-  Reactor* reactor = thread->GetReactor();
-  SampleReactable sample_reactable(thread);
-  auto* reactable =
-      reactor->Register(sample_reactable.fd_, std::bind(&SampleReactable::OnReadReady, &sample_reactable), nullptr);
-  int fd = sample_reactable.fd_;
-  int write_result = eventfd_write(fd, kCheckIsSameThread);
-  EXPECT_EQ(write_result, 0);
-  while (!sample_reactable.IsSameThreadCheckDone()) std::this_thread::yield();
-  reactor->Unregister(reactable);
-}
-
-}  // namespace
-}  // namespace common
-}  // namespace bluetooth
index 9955a45..b3e8a12 100644 (file)
@@ -104,3 +104,16 @@ cc_test {
         cfi: false,
     },
 }
+
+cc_benchmark {
+    name: "bluetooth_benchmark_gd",
+    defaults: ["gd_defaults"],
+    host_supported: true,
+    srcs: [
+        "benchmark.cc",
+        ":BluetoothOsBenchmarkSources",
+    ],
+    static_libs : [
+            "libbluetooth_gd",
+    ],
+}
diff --git a/gd/benchmark.cc b/gd/benchmark.cc
new file mode 100644 (file)
index 0000000..2b11c89
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <benchmark/benchmark.h>
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
+    return 1;
+  }
+  ::benchmark::RunSpecifiedBenchmarks();
+}
index 2f6316c..535f144 100644 (file)
@@ -19,3 +19,11 @@ filegroup {
         "linux_generic/thread_unittest.cc",
     ]
 }
+
+filegroup {
+    name: "BluetoothOsBenchmarkSources",
+    srcs: [
+        "alarm_benchmark.cc",
+        "thread_benchmark.cc",
+    ]
+}
diff --git a/gd/os/alarm_benchmark.cc b/gd/os/alarm_benchmark.cc
new file mode 100644 (file)
index 0000000..54b8a38
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <chrono>
+#include <future>
+#include <unordered_map>
+
+#include "benchmark/benchmark.h"
+
+#include "os/alarm.h"
+#include "os/repeating_alarm.h"
+#include "os/thread.h"
+
+using ::benchmark::State;
+using ::bluetooth::os::Alarm;
+using ::bluetooth::os::RepeatingAlarm;
+using ::bluetooth::os::Thread;
+
+class BM_ReactableAlarm : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    thread_ = std::make_unique<Thread>("timer_benchmark", Thread::Priority::REAL_TIME);
+    alarm_ = std::make_unique<Alarm>(thread_.get());
+    repeating_alarm_ = std::make_unique<RepeatingAlarm>(thread_.get());
+    map_.clear();
+    scheduled_tasks_ = 0;
+    task_length_ = 0;
+    task_interval_ = 0;
+    task_counter_ = 0;
+    promise_ = std::promise<void>();
+  }
+
+  void TearDown(State& st) override {
+    alarm_ = nullptr;
+    repeating_alarm_ = nullptr;
+    thread_->Stop();
+    thread_ = nullptr;
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  void AlarmSleepAndCountDelayedTime() {
+    auto end_time = std::chrono::steady_clock::now();
+    auto duration_since_start = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time_);
+    task_counter_++;
+    map_[duration_since_start.count() - task_counter_ * task_interval_]++;
+    std::this_thread::sleep_for(std::chrono::milliseconds(task_length_));
+    if (task_counter_ >= scheduled_tasks_) {
+      promise_.set_value();
+    }
+  }
+
+  void TimerFire() {
+    promise_.set_value();
+  }
+
+  int64_t scheduled_tasks_;
+  int64_t task_length_;
+  int64_t task_interval_;
+  int task_counter_;
+  std::unordered_map<int, int> map_;
+  std::promise<void> promise_;
+  std::chrono::time_point<std::chrono::steady_clock> start_time_;
+  std::unique_ptr<Thread> thread_;
+  std::unique_ptr<Alarm> alarm_;
+  std::unique_ptr<RepeatingAlarm> repeating_alarm_;
+};
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, timer_performance_ms)(State& state) {
+  auto milliseconds = static_cast<int>(state.range(0));
+  for (auto _ : state) {
+    auto start_time_point = std::chrono::steady_clock::now();
+    alarm_->Schedule([this] { return TimerFire(); }, std::chrono::milliseconds(milliseconds));
+    promise_.get_future().get();
+    auto end_time_point = std::chrono::steady_clock::now();
+    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time_point - start_time_point);
+    state.SetIterationTime(static_cast<double>(duration.count()) * 1e-6);
+    alarm_->Cancel();
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, timer_performance_ms)
+    ->Arg(1)
+    ->Arg(5)
+    ->Arg(10)
+    ->Arg(20)
+    ->Arg(100)
+    ->Arg(1000)
+    ->Arg(2000)
+    ->Iterations(1)
+    ->UseRealTime();
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, periodic_accuracy)(State& state) {
+  for (auto _ : state) {
+    scheduled_tasks_ = state.range(0);
+    task_length_ = state.range(1);
+    task_interval_ = state.range(2);
+    start_time_ = std::chrono::steady_clock::now();
+    repeating_alarm_->Schedule([this] { AlarmSleepAndCountDelayedTime(); }, std::chrono::milliseconds(task_interval_));
+    promise_.get_future().get();
+    repeating_alarm_->Cancel();
+  }
+  for (const auto& delay : map_) {
+    state.counters[std::to_string(delay.first)] = delay.second;
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, periodic_accuracy)
+    ->Args({2000, 1, 5})
+    ->Args({2000, 3, 5})
+    ->Args({2000, 1, 7})
+    ->Args({2000, 3, 7})
+    ->Args({2000, 1, 20})
+    ->Args({2000, 5, 20})
+    ->Args({2000, 10, 20})
+    ->Args({2000, 15, 20})
+    ->Iterations(1)
+    ->UseRealTime();
index f41daa7..7e0488f 100644 (file)
@@ -19,7 +19,7 @@
 #include <sys/eventfd.h>
 #include <thread>
 
-#include <gtest/gtest.h>
+#include "gtest/gtest.h"
 
 namespace bluetooth {
 namespace os {
diff --git a/gd/os/thread_benchmark.cc b/gd/os/thread_benchmark.cc
new file mode 100644 (file)
index 0000000..dc22b9d
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <future>
+#include <memory>
+#include <thread>
+
+#include "benchmark/benchmark.h"
+
+#include "os/handler.h"
+#include "os/thread.h"
+
+using ::benchmark::State;
+using ::bluetooth::os::Handler;
+using ::bluetooth::os::Thread;
+
+#define NUM_MESSAGES_TO_SEND 100000
+
+class BM_ThreadPerformance : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    benchmark::Fixture::SetUp(st);
+    counter_promise_ = std::promise<void>();
+    counter_ = 0;
+  }
+  void TearDown(State& st) override {
+    benchmark::Fixture::TearDown(st);
+  }
+  void callback_batch() {
+    counter_++;
+    if (counter_ >= num_messages_to_send_) {
+      counter_promise_.set_value();
+    }
+  }
+
+  void callback() {
+    counter_promise_.set_value();
+  }
+
+  int64_t num_messages_to_send_;
+  int64_t counter_;
+  std::promise<void> counter_promise_;
+};
+
+class BM_ReactorThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    thread_ = std::make_unique<Thread>("BM_ReactorThread thread", Thread::Priority::NORMAL);
+    handler_ = std::make_unique<Handler>(thread_.get());
+  }
+  void TearDown(State& st) override {
+    handler_ = nullptr;
+    thread_->Stop();
+    thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+  std::unique_ptr<Thread> thread_;
+  std::unique_ptr<Handler> handler_;
+};
+
+BENCHMARK_DEFINE_F(BM_ReactorThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    num_messages_to_send_ = state.range(0);
+    counter_ = 0;
+    counter_promise_ = std::promise<void>();
+    std::future<void> counter_future = counter_promise_.get_future();
+    for (int i = 0; i < num_messages_to_send_; i++) {
+      handler_->Post([this]() { callback_batch(); });
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactorThread, batch_enque_dequeue)
+    ->Arg(10)
+    ->Arg(1000)
+    ->Arg(10000)
+    ->Arg(100000)
+    ->Iterations(1)
+    ->UseRealTime();
+
+BENCHMARK_DEFINE_F(BM_ReactorThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    num_messages_to_send_ = state.range(0);
+    for (int i = 0; i < num_messages_to_send_; i++) {
+      counter_promise_ = std::promise<void>();
+      std::future<void> counter_future = counter_promise_.get_future();
+      handler_->Post([this]() { callback(); });
+      counter_future.wait();
+    }
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactorThread, sequential_execution)
+    ->Arg(10)
+    ->Arg(1000)
+    ->Arg(10000)
+    ->Arg(100000)
+    ->Iterations(1)
+    ->UseRealTime();