],
srcs: [
"message_loop_thread.cc",
- "execution_barrier.cc",
"metrics.cc",
"time_util.cc",
],
"system/bt/stack/include",
],
srcs : [
- "execution_barrier_unittest.cc",
"leaky_bonded_queue_unittest.cc",
"message_loop_thread_unittest.cc",
"metrics_unittest.cc",
#include <base/run_loop.h>
#include <base/threading/thread.h>
#include <benchmark/benchmark.h>
+#include <future>
#include <memory>
#include <thread>
-#include "common/execution_barrier.h"
#include "common/message_loop_thread.h"
#include "osi/include/fixed_queue.h"
#include "osi/include/thread.h"
using ::benchmark::State;
-using bluetooth::common::ExecutionBarrier;
using bluetooth::common::MessageLoopThread;
#define NUM_MESSAGES_TO_SEND 100000
volatile static int g_counter = 0;
-static std::unique_ptr<ExecutionBarrier> g_counter_barrier = nullptr;
+static std::unique_ptr<std::promise<void>> g_counter_promise = nullptr;
void pthread_callback_batch(void* context) {
auto queue = static_cast<fixed_queue_t*>(context);
fixed_queue_dequeue(queue);
g_counter++;
if (g_counter >= NUM_MESSAGES_TO_SEND) {
- g_counter_barrier->NotifyFinished();
+ g_counter_promise->set_value();
}
}
-void callback_sequential(void* context) { g_counter_barrier->NotifyFinished(); }
+void callback_sequential(void* context) { g_counter_promise->set_value(); }
void callback_sequential_queue(fixed_queue_t* queue, void* context) {
CHECK_NE(queue, nullptr);
fixed_queue_dequeue(queue);
- g_counter_barrier->NotifyFinished();
+ g_counter_promise->set_value();
}
void callback_batch(fixed_queue_t* queue, void* data) {
fixed_queue_dequeue(queue);
g_counter++;
if (g_counter >= NUM_MESSAGES_TO_SEND) {
- g_counter_barrier->NotifyFinished();
+ g_counter_promise->set_value();
}
}
protected:
void SetUp(State& st) override {
benchmark::Fixture::SetUp(st);
- set_up_barrier_ = std::make_unique<ExecutionBarrier>();
+ set_up_promise_ = std::make_unique<std::promise<void>>();
g_counter = 0;
bt_msg_queue_ = fixed_queue_new(SIZE_MAX);
}
void TearDown(State& st) override {
fixed_queue_free(bt_msg_queue_, nullptr);
bt_msg_queue_ = nullptr;
- set_up_barrier_.reset(nullptr);
- g_counter_barrier.reset(nullptr);
+ set_up_promise_.reset(nullptr);
+ g_counter_promise.reset(nullptr);
benchmark::Fixture::TearDown(st);
}
fixed_queue_t* bt_msg_queue_ = nullptr;
- std::unique_ptr<ExecutionBarrier> set_up_barrier_;
+ std::unique_ptr<std::promise<void>> set_up_promise_;
};
class BM_MessageLoop : public BM_ThreadPerformance {
message_loop_ = new base::MessageLoop();
run_loop_ = new base::RunLoop();
message_loop_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
+ FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
run_loop_->Run();
delete message_loop_;
message_loop_ = nullptr;
protected:
void SetUp(State& st) override {
BM_MessageLoop::SetUp(st);
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = thread_new("BM_MessageLoopOnOsiThread thread");
thread_post(thread_, &BM_MessageLoop::RunThread, this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown(State& st) override {
BENCHMARK_F(BM_MessageLoopOsiThread, batch_enque_dequeue)(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
BENCHMARK_F(BM_MessageLoopOsiThread, sequential_execution)(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
protected:
void SetUp(State& st) override {
BM_MessageLoop::SetUp(st);
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = new std::thread(&BM_MessageLoop::RunThread, this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown(State& st) override {
BENCHMARK_F(BM_MessageLoopStlThread, batch_enque_dequeue)(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
BENCHMARK_F(BM_MessageLoopStlThread, sequential_execution)(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
protected:
void SetUp(State& st) override {
BM_MessageLoop::SetUp(st);
+ std::future<void> set_up_future = set_up_promise_->get_future();
pthread_create(&thread_, nullptr, &BM_MessageLoop::RunPThread, (void*)this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown(State& st) override {
BENCHMARK_F(BM_MessageLoopPosixThread, batch_enque_dequeue)(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
BENCHMARK_F(BM_MessageLoopPosixThread, sequential_execution)(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
thread_post(thread_, pthread_callback_batch, bt_msg_queue_);
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
thread_post(thread_, callback_sequential, nullptr);
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
callback_batch, nullptr);
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
callback_sequential_queue, nullptr);
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
protected:
void SetUp(State& st) override {
BM_ThreadPerformance::SetUp(st);
+ std::future<void> set_up_future = set_up_promise_->get_future();
message_loop_thread_ =
new MessageLoopThread("BM_MessageLooopThread thread");
message_loop_thread_->StartUp();
message_loop_thread_->DoInThread(
- FROM_HERE, base::BindOnce(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
- set_up_barrier_->WaitForExecution();
+ FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
+ set_up_future.wait();
}
void TearDown(State& st) override {
BENCHMARK_F(BM_MessageLooopThread, batch_enque_dequeue)(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
message_loop_thread_->DoInThread(
FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
BENCHMARK_F(BM_MessageLooopThread, sequential_execution)(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
message_loop_thread_->DoInThread(
FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
protected:
void SetUp(State& st) override {
BM_ThreadPerformance::SetUp(st);
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = new base::Thread("BM_LibChromeThread thread");
thread_->Start();
thread_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
- set_up_barrier_->WaitForExecution();
+ FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
+ set_up_future.wait();
}
void TearDown(State& st) override {
BENCHMARK_F(BM_LibChromeThread, batch_enque_dequeue)(State& state) {
for (auto _ : state) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ 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);
thread_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
};
BENCHMARK_F(BM_LibChromeThread, sequential_execution)(State& state) {
for (auto _ : state) {
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
thread_->task_runner()->PostTask(
FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
}
}
};
return 1;
}
::benchmark::RunSpecifiedBenchmarks();
-}
\ No newline at end of file
+}
+++ /dev/null
-/*
- * Copyright 2018 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 "execution_barrier.h"
-
-namespace bluetooth {
-
-namespace common {
-
-void ExecutionBarrier::WaitForExecution() {
- std::unique_lock<std::mutex> lock(execution_mutex_);
- while (!finished_) {
- execution_cv_.wait(lock);
- }
-}
-
-void ExecutionBarrier::NotifyFinished() {
- std::unique_lock<std::mutex> lock(execution_mutex_);
- finished_ = true;
- execution_cv_.notify_all();
-}
-
-} // namespace common
-
-} // namespace bluetooth
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright 2018 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 <condition_variable>
-#include <memory>
-#include <mutex>
-
-#include <base/macros.h>
-
-namespace bluetooth {
-
-namespace common {
-
-/**
- * A utility to wait for an event on another thread
- *
- * This class can be used once only. This means that after the first time
- * NotifyFinished() is called, WaitForExecution() will no longer block. User
- * needs to create a new instance if another ExecutionBarrier is needed.
- *
- * No reset mechanism is provided for this class to avoid racy scenarios and
- * unsafe API usage
- *
- * Similar to std::experimental::barrier, but this can be used only once
- */
-class ExecutionBarrier final {
- public:
- explicit ExecutionBarrier() : finished_(false){};
-
- /**
- * Blocks until NotifyFinished() is called on this object
- *
- */
- void WaitForExecution();
-
- /**
- * Unblocks any caller who are blocked on WaitForExecution() method call
- */
- void NotifyFinished();
-
- private:
- bool finished_;
- std::mutex execution_mutex_;
- std::condition_variable execution_cv_;
-
- /**
- * Prevent COPY and ASSIGN since many internal states cannot be copied or
- * assigned
- */
- DISALLOW_COPY_AND_ASSIGN(ExecutionBarrier);
-};
-
-} // namespace common
-
-} // namespace bluetooth
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright 2018 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 <thread>
-
-#include <gtest/gtest.h>
-
-#include "execution_barrier.h"
-
-using bluetooth::common::ExecutionBarrier;
-
-static constexpr int kSleepTimeMs = 100;
-static constexpr int kSchedulingDelayMaxMs = 5;
-
-TEST(ExecutionBarrierTest, test_two_threads_wait_before_execution) {
- ExecutionBarrier execution_barrier;
- std::thread caller1([&]() {
- auto start = std::chrono::high_resolution_clock::now();
- execution_barrier.WaitForExecution();
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> elapsed_ms = end - start;
- EXPECT_NEAR(elapsed_ms.count(), kSleepTimeMs, kSchedulingDelayMaxMs);
- });
- std::thread executor([&]() {
- // Wait for kSleepTimeMs so that caller1 starts waiting first
- std::this_thread::sleep_for(std::chrono::milliseconds(kSleepTimeMs));
- execution_barrier.NotifyFinished();
- });
- executor.join();
- caller1.join();
- // Further calls to WaitForExecution() no longer blocks
- std::thread caller2([&]() {
- auto start = std::chrono::high_resolution_clock::now();
- execution_barrier.WaitForExecution();
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> elapsed_ms = end - start;
- EXPECT_LT(elapsed_ms.count(), kSchedulingDelayMaxMs);
- });
- caller2.join();
-}
-
-TEST(ExecutionBarrierTest, test_two_threads_execution_before_wait) {
- ExecutionBarrier execution_barrier;
- std::thread executor([&]() { execution_barrier.NotifyFinished(); });
- std::thread caller1([&]() {
- // Wait for kSleepTimeMs so that executor finishes running first
- std::this_thread::sleep_for(std::chrono::milliseconds(kSleepTimeMs));
- auto start = std::chrono::high_resolution_clock::now();
- execution_barrier.WaitForExecution();
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> elapsed_ms = end - start;
- EXPECT_LT(elapsed_ms.count(), kSchedulingDelayMaxMs);
- });
- executor.join();
- caller1.join();
-}
-
-TEST(ExecutionBarrierTest, test_two_callers_one_executor) {
- ExecutionBarrier execution_barrier;
- std::thread caller1([&]() {
- auto start = std::chrono::high_resolution_clock::now();
- execution_barrier.WaitForExecution();
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> elapsed_ms = end - start;
- EXPECT_NEAR(elapsed_ms.count(), kSleepTimeMs, 5);
- });
- std::thread caller2([&]() {
- auto start = std::chrono::high_resolution_clock::now();
- execution_barrier.WaitForExecution();
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double, std::milli> elapsed_ms = end - start;
- EXPECT_NEAR(elapsed_ms.count(), kSleepTimeMs, 5);
- });
- std::thread executor([&]() {
- std::this_thread::sleep_for(std::chrono::milliseconds(kSleepTimeMs));
- execution_barrier.NotifyFinished();
- });
- executor.join();
- caller1.join();
- caller2.join();
-}
LOG(WARNING) << __func__ << ": thread " << *this << " is already started";
return;
}
- std::shared_ptr<ExecutionBarrier> start_up_barrier =
- std::make_shared<ExecutionBarrier>();
- thread_ =
- new std::thread(&MessageLoopThread::RunThread, this, start_up_barrier);
- start_up_barrier->WaitForExecution();
+ std::promise<void> start_up_promise;
+ std::future<void> start_up_future = start_up_promise.get_future();
+ thread_ = new std::thread(&MessageLoopThread::RunThread, this,
+ std::move(start_up_promise));
+ start_up_future.wait();
}
bool MessageLoopThread::DoInThread(const tracked_objects::Location& from_here,
}
// Non API method, should not be protected by API mutex
-void MessageLoopThread::RunThread(
- MessageLoopThread* thread,
- std::shared_ptr<ExecutionBarrier> start_up_barrier) {
- thread->Run(std::move(start_up_barrier));
+void MessageLoopThread::RunThread(MessageLoopThread* thread,
+ std::promise<void> start_up_promise) {
+ thread->Run(std::move(start_up_promise));
}
base::MessageLoop* MessageLoopThread::message_loop() const {
}
// Non API method, should NOT be protected by API mutex to avoid deadlock
-void MessageLoopThread::Run(
- std::shared_ptr<ExecutionBarrier> start_up_barrier) {
+void MessageLoopThread::Run(std::promise<void> start_up_promise) {
LOG(INFO) << __func__ << ": message loop starting for thread "
<< thread_name_;
base::PlatformThread::SetName(thread_name_);
run_loop_ = new base::RunLoop();
thread_id_ = base::PlatformThread::CurrentId();
linux_tid_ = static_cast<pid_t>(syscall(SYS_gettid));
- start_up_barrier->NotifyFinished();
+ start_up_promise.set_value();
// Blocking until ShutDown() is called
run_loop_->Run();
thread_id_ = -1;
#pragma once
#include <unistd.h>
+#include <future>
#include <memory>
#include <string>
#include <thread>
#include <base/threading/platform_thread.h>
#include <base/tracked_objects.h>
-#include "common/execution_barrier.h"
-
namespace bluetooth {
namespace common {
* This is used instead of a C++ lambda because of the use of std::shared_ptr
*
* @param context needs to be a pointer to an instance of MessageLoopThread
- * @param start_up_barrier an ExecutionBarrier that is used to notify calling
+ * @param start_up_promise a std::promise that is used to notify calling
* thread the completion of message loop start-up
*/
static void RunThread(MessageLoopThread* context,
- std::shared_ptr<ExecutionBarrier> start_up_barrier);
+ std::promise<void> start_up_promise);
/**
* Actual method to run the thread, blocking until ShutDown() is called
*
- * @param start_up_barrier an ExecutionBarrier that is used to notify calling
+ * @param start_up_promise a std::promise that is used to notify calling
* thread the completion of message loop start-up
*/
- void Run(std::shared_ptr<ExecutionBarrier> start_up_barrier);
+ void Run(std::promise<void> start_up_promise);
mutable std::recursive_mutex api_mutex_;
std::string thread_name_;
#include <sys/capability.h>
#include <syscall.h>
-#include "execution_barrier.h"
#include "message_loop_thread.h"
-using bluetooth::common::ExecutionBarrier;
using bluetooth::common::MessageLoopThread;
/**
public:
void ShouldNotHappen() { FAIL() << "Should not happen"; }
- void GetThreadId(base::PlatformThreadId* thread_id,
- std::shared_ptr<ExecutionBarrier> execution_barrier) {
- *thread_id = base::PlatformThread::CurrentId();
- execution_barrier->NotifyFinished();
+ void GetThreadId(std::promise<base::PlatformThreadId> thread_id_promise) {
+ thread_id_promise.set_value(base::PlatformThread::CurrentId());
}
- void GetLinuxTid(pid_t* tid,
- std::shared_ptr<ExecutionBarrier> execution_barrier) {
- *tid = static_cast<pid_t>(syscall(SYS_gettid));
- execution_barrier->NotifyFinished();
+ void GetLinuxTid(std::promise<pid_t> tid_promise) {
+ tid_promise.set_value(static_cast<pid_t>(syscall(SYS_gettid)));
}
- void GetName(std::string* name,
- std::shared_ptr<ExecutionBarrier> execution_barrier) {
+ void GetName(std::promise<std::string> name_promise) {
char my_name[256];
pthread_getname_np(pthread_self(), my_name, sizeof(my_name));
- name->append(my_name);
- execution_barrier->NotifyFinished();
+ name_promise.set_value(my_name);
}
- void GetSchedulingPolicyAndPriority(
- int* scheduling_policy, int* schedule_priority,
- std::shared_ptr<ExecutionBarrier> execution_barrier) {
+ void GetSchedulingPolicyAndPriority(int* scheduling_policy,
+ int* schedule_priority,
+ std::promise<void> execution_promise) {
*scheduling_policy = sched_getscheduler(0);
struct sched_param param = {};
ASSERT_EQ(sched_getparam(0, ¶m), 0);
*schedule_priority = param.sched_priority;
- execution_barrier->NotifyFinished();
+ execution_promise.set_value();
}
protected:
MessageLoopThread message_loop_thread(name);
message_loop_thread.StartUp();
ASSERT_GE(message_loop_thread.GetThreadId(), 0);
- std::shared_ptr<ExecutionBarrier> execution_barrier =
- std::make_shared<ExecutionBarrier>();
- std::string myName;
+ std::promise<std::string> name_promise;
+ std::future<std::string> name_future = name_promise.get_future();
message_loop_thread.DoInThread(
FROM_HERE,
- base::Bind(&MessageLoopThreadTest::GetName, base::Unretained(this),
- &myName, execution_barrier));
- execution_barrier->WaitForExecution();
- ASSERT_EQ(name, myName);
+ base::BindOnce(&MessageLoopThreadTest::GetName, base::Unretained(this),
+ std::move(name_promise)));
+ std::string my_name = name_future.get();
+ ASSERT_EQ(name, my_name);
ASSERT_EQ(name, message_loop_thread.GetName());
}
message_loop_thread.StartUp();
base::PlatformThreadId thread_id = message_loop_thread.GetThreadId();
ASSERT_GE(thread_id, 0);
- std::shared_ptr<ExecutionBarrier> execution_barrier =
- std::make_shared<ExecutionBarrier>();
- base::PlatformThreadId my_thread_id;
+ std::promise<base::PlatformThreadId> thread_id_promise;
+ std::future<base::PlatformThreadId> thread_id_future =
+ thread_id_promise.get_future();
message_loop_thread.DoInThread(
FROM_HERE,
- base::Bind(&MessageLoopThreadTest::GetThreadId, base::Unretained(this),
- &my_thread_id, execution_barrier));
- execution_barrier->WaitForExecution();
+ base::BindOnce(&MessageLoopThreadTest::GetThreadId,
+ base::Unretained(this), std::move(thread_id_promise)));
+ base::PlatformThreadId my_thread_id = thread_id_future.get();
ASSERT_EQ(thread_id, my_thread_id);
}
return;
}
}
- std::shared_ptr<ExecutionBarrier> execution_barrier =
- std::make_shared<ExecutionBarrier>();
+ std::promise<void> execution_promise;
+ std::future<void> execution_future = execution_promise.get_future();
int scheduling_policy = -1;
int scheduling_priority = -1;
message_loop_thread.DoInThread(
FROM_HERE,
- base::Bind(&MessageLoopThreadTest::GetSchedulingPolicyAndPriority,
- base::Unretained(this), &scheduling_policy,
- &scheduling_priority, execution_barrier));
- execution_barrier->WaitForExecution();
+ base::BindOnce(&MessageLoopThreadTest::GetSchedulingPolicyAndPriority,
+ base::Unretained(this), &scheduling_policy,
+ &scheduling_priority, std::move(execution_promise)));
+ execution_future.wait();
ASSERT_EQ(scheduling_policy, SCHED_FIFO);
// Internal implementation verified here
ASSERT_EQ(scheduling_priority, 1);
- execution_barrier = std::make_shared<ExecutionBarrier>();
- pid_t linux_tid = -1;
+ std::promise<pid_t> tid_promise;
+ std::future<pid_t> tid_future = tid_promise.get_future();
message_loop_thread.DoInThread(
FROM_HERE,
- base::Bind(&MessageLoopThreadTest::GetLinuxTid, base::Unretained(this),
- &linux_tid, execution_barrier));
- execution_barrier->WaitForExecution();
+ base::BindOnce(&MessageLoopThreadTest::GetLinuxTid,
+ base::Unretained(this), std::move(tid_promise)));
+ pid_t linux_tid = tid_future.get();
ASSERT_GT(linux_tid, 0);
ASSERT_EQ(sched_getscheduler(linux_tid), SCHED_FIFO);
struct sched_param param = {};
// String representation should look the same when thread is not running
ASSERT_STREQ(thread_string_after_shutdown.c_str(),
thread_string_before_start.c_str());
-}
\ No newline at end of file
+}
#include <gtest/gtest.h>
#include <unistd.h>
#include <chrono>
+#include <future>
#include <iostream>
#include <thread>
-#include "common/execution_barrier.h"
#include "common/message_loop_thread.h"
#include "osi/include/fixed_queue.h"
#include "osi/include/thread.h"
-using bluetooth::common::ExecutionBarrier;
using bluetooth::common::MessageLoopThread;
#define NUM_MESSAGES_TO_SEND 100000
volatile static int g_counter = 0;
-static std::unique_ptr<ExecutionBarrier> g_counter_barrier = nullptr;
+static std::unique_ptr<std::promise<void>> g_counter_promise = nullptr;
void callback_batch(fixed_queue_t* queue, void* data) {
if (queue != nullptr) {
}
g_counter++;
if (g_counter >= NUM_MESSAGES_TO_SEND) {
- g_counter_barrier->NotifyFinished();
+ g_counter_promise->set_value();
}
}
class PerformanceTest : public testing::Test {
protected:
void SetUp() override {
- set_up_barrier_ = std::make_unique<ExecutionBarrier>();
+ set_up_promise_ = std::make_unique<std::promise<void>>();
g_counter = 0;
bt_msg_queue_ = fixed_queue_new(SIZE_MAX);
}
void TearDown() override {
fixed_queue_free(bt_msg_queue_, nullptr);
bt_msg_queue_ = nullptr;
- set_up_barrier_.reset(nullptr);
- g_counter_barrier.reset(nullptr);
+ set_up_promise_.reset(nullptr);
+ g_counter_promise.reset(nullptr);
}
fixed_queue_t* bt_msg_queue_ = nullptr;
- std::unique_ptr<ExecutionBarrier> set_up_barrier_ = nullptr;
+ std::unique_ptr<std::promise<void>> set_up_promise_ = nullptr;
};
class MessageLoopPerformanceTest : public PerformanceTest {
message_loop_ = new base::MessageLoop();
run_loop_ = new base::RunLoop();
message_loop_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
+ FROM_HERE, base::Bind(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
run_loop_->Run();
delete message_loop_;
message_loop_ = nullptr;
protected:
void SetUp() override {
MessageLoopPerformanceTest::SetUp();
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = thread_new("OsiThreadMessageLoopPerformanceTest thread");
thread_post(thread_, &MessageLoopPerformanceTest::RunThread, this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown() override {
TEST_F(OsiThreadMessageLoopPerformanceTest, message_loop_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();
protected:
void SetUp() override {
MessageLoopPerformanceTest::SetUp();
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = new std::thread(&MessageLoopPerformanceTest::RunThread, this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown() override {
TEST_F(StlThreadMessageLoopPerformanceTest, stl_thread_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();
protected:
void SetUp() override {
MessageLoopPerformanceTest::SetUp();
+ std::future<void> set_up_future = set_up_promise_->get_future();
pthread_create(&thread_, nullptr, &MessageLoopPerformanceTest::RunPThread,
(void*)this);
- set_up_barrier_->WaitForExecution();
+ set_up_future.wait();
}
void TearDown() override {
TEST_F(PosixThreadMessageLoopPerformanceTest, stl_thread_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
message_loop_->task_runner()->PostTask(
FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();
TEST_F(ReactorPerformanceTest, reactor_thread_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
callback_batch, nullptr);
for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();
protected:
void SetUp() override {
PerformanceTest::SetUp();
+ std::future<void> set_up_future = set_up_promise_->get_future();
worker_thread_ =
new MessageLoopThread("WorkerThreadPerformanceTest thread");
worker_thread_->StartUp();
worker_thread_->DoInThread(
- FROM_HERE, base::Bind(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
- set_up_barrier_->WaitForExecution();
+ FROM_HERE, base::Bind(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
+ set_up_future.wait();
}
void TearDown() override {
TEST_F(WorkerThreadPerformanceTest, worker_thread_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
worker_thread_->DoInThread(
FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();
protected:
void SetUp() override {
PerformanceTest::SetUp();
+ std::future<void> set_up_future = set_up_promise_->get_future();
thread_ = new base::Thread("LibChromeThreadPerformanceTest thread");
thread_->Start();
thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&ExecutionBarrier::NotifyFinished,
- base::Unretained(set_up_barrier_.get())));
- set_up_barrier_->WaitForExecution();
+ FROM_HERE, base::Bind(&std::promise<void>::set_value,
+ base::Unretained(set_up_promise_.get())));
+ set_up_future.wait();
}
void TearDown() override {
TEST_F(LibChromeThreadPerformanceTest, worker_thread_speed_test) {
g_counter = 0;
- g_counter_barrier = std::make_unique<ExecutionBarrier>();
+ g_counter_promise = std::make_unique<std::promise<void>>();
+ std::future<void> counter_future = g_counter_promise->get_future();
std::chrono::steady_clock::time_point start_time =
std::chrono::steady_clock::now();
thread_->task_runner()->PostTask(
FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
}
- g_counter_barrier->WaitForExecution();
+ counter_future.wait();
std::chrono::steady_clock::time_point end_time =
std::chrono::steady_clock::now();