Loading system/btif/src/btif_a2dp_source.cc +3 −3 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ #include "btif_util.h" #include "common/message_loop_thread.h" #include "common/metrics.h" #include "common/repeating_timer.h" #include "common/time_util.h" #include "common/timer.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/osi.h" Loading @@ -51,7 +51,7 @@ using bluetooth::common::A2dpSessionMetrics; using bluetooth::common::BluetoothMetricsLogger; using bluetooth::common::Timer; using bluetooth::common::RepeatingTimer; extern std::unique_ptr<tUIPC_STATE> a2dp_uipc; Loading Loading @@ -212,7 +212,7 @@ class BtifA2dpSource { fixed_queue_t* tx_audio_queue; bool tx_flush; /* Discards any outgoing data when true */ Timer media_alarm; RepeatingTimer media_alarm; const tA2DP_ENCODER_INTERFACE* encoder_interface; uint64_t encoder_interval_ms; /* Local copy of the encoder interval */ BtifMediaStats stats; Loading system/common/Android.bp +4 −2 Original line number Diff line number Diff line Loading @@ -8,9 +8,10 @@ cc_library_static { ], srcs: [ "address_obfuscator.cc", "timer.cc", "message_loop_thread.cc", "metrics.cc", "once_timer.cc", "repeating_timer.cc", "time_util.cc", ], shared_libs: [ Loading @@ -32,10 +33,11 @@ cc_test { ], srcs : [ "address_obfuscator_unittest.cc", "timer_unittest.cc", "leaky_bonded_queue_unittest.cc", "message_loop_thread_unittest.cc", "metrics_unittest.cc", "once_timer_unittest.cc", "repeating_timer_unittest.cc", "state_machine_unittest.cc", "time_util_unittest.cc", ], Loading system/common/benchmark/timer_performance_benchmark.cc +27 −17 Original line number Diff line number Diff line Loading @@ -21,14 +21,16 @@ #include <future> #include "common/message_loop_thread.h" #include "common/once_timer.h" #include "common/repeating_timer.h" #include "common/time_util.h" #include "common/timer.h" #include "osi/include/alarm.h" using ::benchmark::State; using bluetooth::common::MessageLoopThread; using bluetooth::common::OnceTimer; using bluetooth::common::RepeatingTimer; using bluetooth::common::time_get_os_boottime_us; using bluetooth::common::Timer; // fake get_main_message_loop implementation for alarm base::MessageLoop* get_main_message_loop() { return nullptr; } Loading Loading @@ -104,14 +106,17 @@ class BM_AlarmTaskTimer : public ::benchmark::Fixture { message_loop_thread_ = new MessageLoopThread("timer_benchmark"); message_loop_thread_->StartUp(); message_loop_thread_->EnableRealTimeScheduling(); timer_ = new Timer(); once_timer_ = new OnceTimer(); repeating_timer_ = new RepeatingTimer(); g_promise = std::make_shared<std::promise<void>>(); } void TearDown(State& st) override { g_promise = nullptr; delete timer_; timer_ = nullptr; delete once_timer_; once_timer_ = nullptr; delete repeating_timer_; repeating_timer_ = nullptr; message_loop_thread_->ShutDown(); delete message_loop_thread_; message_loop_thread_ = nullptr; Loading @@ -119,18 +124,19 @@ class BM_AlarmTaskTimer : public ::benchmark::Fixture { } MessageLoopThread* message_loop_thread_; Timer* timer_; OnceTimer* once_timer_; RepeatingTimer* repeating_timer_; }; BENCHMARK_DEFINE_F(BM_AlarmTaskTimer, 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(); timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE, base::Bind(&TimerFire, nullptr), once_timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE, base::BindOnce(&TimerFire, nullptr), base::TimeDelta::FromMilliseconds(milliseconds)); g_promise->get_future().get(); timer_->Cancel(); once_timer_->Cancel(); auto end_time_point = time_get_os_boottime_us(); auto duration = end_time_point - start_time_point; state.SetIterationTime(duration * 1e-6); Loading Loading @@ -204,7 +210,8 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { message_loop_thread_ = new MessageLoopThread("timer_benchmark"); message_loop_thread_->StartUp(); message_loop_thread_->EnableRealTimeScheduling(); timer_ = new Timer(); once_timer_ = new OnceTimer(); repeating_timer_ = new RepeatingTimer(); g_map.clear(); g_promise = std::make_shared<std::promise<void>>(); g_scheduled_tasks = 0; Loading @@ -215,8 +222,10 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { void TearDown(State& st) override { g_promise = nullptr; delete timer_; timer_ = nullptr; delete once_timer_; once_timer_ = nullptr; delete repeating_timer_; repeating_timer_ = nullptr; message_loop_thread_->ShutDown(); delete message_loop_thread_; message_loop_thread_ = nullptr; Loading @@ -224,7 +233,8 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { } MessageLoopThread* message_loop_thread_; Timer* timer_; OnceTimer* once_timer_; RepeatingTimer* repeating_timer_; }; BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy) Loading @@ -234,12 +244,12 @@ BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy) g_task_length = state.range(1); g_task_interval = state.range(2); g_start_time = time_get_os_boottime_us(); timer_->SchedulePeriodic( repeating_timer_->SchedulePeriodic( message_loop_thread_->GetWeakPtr(), FROM_HERE, base::Bind(&AlarmSleepAndCountDelayedTime, nullptr), base::BindRepeating(&AlarmSleepAndCountDelayedTime, nullptr), base::TimeDelta::FromMilliseconds(g_task_interval)); g_promise->get_future().get(); timer_->Cancel(); repeating_timer_->Cancel(); } for (const auto& delay : g_map) { state.counters[std::to_string(delay.first)] = delay.second; Loading system/common/message_loop_thread.h +2 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,8 @@ class MessageLoopThread final { bool DoInThreadDelayed(const base::Location& from_here, base::OnceClosure task, const base::TimeDelta& delay); friend class Timer; // allow Timer to use DoInThreadDelayed() friend class RepeatingTimer; // allow Timer to use DoInThreadDelayed() friend class OnceTimer; // allow OnceTimer to use DoInThreadDelayed() /** * Actual method to run the thread, blocking until ShutDown() is called Loading system/common/once_timer.cc 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * 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 "once_timer.h" #include "message_loop_thread.h" #include "time_util.h" namespace bluetooth { namespace common { // This runs on user thread OnceTimer::~OnceTimer() { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); if (message_loop_thread_ != nullptr && message_loop_thread_->IsRunning()) { CancelAndWait(); } } // This runs on user thread bool OnceTimer::Schedule(const base::WeakPtr<MessageLoopThread>& thread, const base::Location& from_here, base::OnceClosure task, base::TimeDelta delay) { uint64_t time_now_us = time_get_os_boottime_us(); uint64_t time_next_task_us = time_now_us + delay.InMicroseconds(); std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); if (thread == nullptr) { LOG(ERROR) << __func__ << ": thread must be non-null"; return false; } CancelAndWait(); task_ = std::move(task); task_wrapper_.Reset( base::BindOnce(&OnceTimer::RunTask, base::Unretained(this))); message_loop_thread_ = thread; delay_ = delay; uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us(); if (!thread->DoInThreadDelayed( from_here, task_wrapper_.callback(), base::TimeDelta::FromMicroseconds(time_until_next_us))) { LOG(ERROR) << __func__ << ": failed to post task to message loop for thread " << *thread << ", from " << from_here.ToString(); task_wrapper_.Cancel(); message_loop_thread_ = nullptr; delay_ = {}; return false; } return true; } // This runs on user thread void OnceTimer::Cancel() { std::promise<void> promise; CancelHelper(std::move(promise)); } // This runs on user thread void OnceTimer::CancelAndWait() { std::promise<void> promise; auto future = promise.get_future(); CancelHelper(std::move(promise)); future.wait(); } // This runs on user thread void OnceTimer::CancelHelper(std::promise<void> promise) { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); MessageLoopThread* scheduled_thread = message_loop_thread_.get(); if (scheduled_thread == nullptr) { promise.set_value(); return; } if (scheduled_thread->GetThreadId() == base::PlatformThread::CurrentId()) { CancelClosure(std::move(promise)); return; } scheduled_thread->DoInThread( FROM_HERE, base::BindOnce(&OnceTimer::CancelClosure, base::Unretained(this), std::move(promise))); } // This runs on message loop thread void OnceTimer::CancelClosure(std::promise<void> promise) { message_loop_thread_ = nullptr; task_wrapper_.Cancel(); std::move(task_); delay_ = base::TimeDelta(); promise.set_value(); } // This runs on user thread bool OnceTimer::IsScheduled() const { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); return message_loop_thread_ != nullptr && message_loop_thread_->IsRunning(); } // This runs on message loop thread void OnceTimer::RunTask() { if (message_loop_thread_ == nullptr || !message_loop_thread_->IsRunning()) { LOG(ERROR) << __func__ << ": message_loop_thread_ is null or is not running"; return; } CHECK_EQ(message_loop_thread_->GetThreadId(), base::PlatformThread::CurrentId()) << ": task must run on message loop thread"; task_wrapper_.Cancel(); std::move(task_).Run(); message_loop_thread_ = nullptr; } } // namespace common } // namespace bluetooth Loading
system/btif/src/btif_a2dp_source.cc +3 −3 Original line number Diff line number Diff line Loading @@ -41,8 +41,8 @@ #include "btif_util.h" #include "common/message_loop_thread.h" #include "common/metrics.h" #include "common/repeating_timer.h" #include "common/time_util.h" #include "common/timer.h" #include "osi/include/fixed_queue.h" #include "osi/include/log.h" #include "osi/include/osi.h" Loading @@ -51,7 +51,7 @@ using bluetooth::common::A2dpSessionMetrics; using bluetooth::common::BluetoothMetricsLogger; using bluetooth::common::Timer; using bluetooth::common::RepeatingTimer; extern std::unique_ptr<tUIPC_STATE> a2dp_uipc; Loading Loading @@ -212,7 +212,7 @@ class BtifA2dpSource { fixed_queue_t* tx_audio_queue; bool tx_flush; /* Discards any outgoing data when true */ Timer media_alarm; RepeatingTimer media_alarm; const tA2DP_ENCODER_INTERFACE* encoder_interface; uint64_t encoder_interval_ms; /* Local copy of the encoder interval */ BtifMediaStats stats; Loading
system/common/Android.bp +4 −2 Original line number Diff line number Diff line Loading @@ -8,9 +8,10 @@ cc_library_static { ], srcs: [ "address_obfuscator.cc", "timer.cc", "message_loop_thread.cc", "metrics.cc", "once_timer.cc", "repeating_timer.cc", "time_util.cc", ], shared_libs: [ Loading @@ -32,10 +33,11 @@ cc_test { ], srcs : [ "address_obfuscator_unittest.cc", "timer_unittest.cc", "leaky_bonded_queue_unittest.cc", "message_loop_thread_unittest.cc", "metrics_unittest.cc", "once_timer_unittest.cc", "repeating_timer_unittest.cc", "state_machine_unittest.cc", "time_util_unittest.cc", ], Loading
system/common/benchmark/timer_performance_benchmark.cc +27 −17 Original line number Diff line number Diff line Loading @@ -21,14 +21,16 @@ #include <future> #include "common/message_loop_thread.h" #include "common/once_timer.h" #include "common/repeating_timer.h" #include "common/time_util.h" #include "common/timer.h" #include "osi/include/alarm.h" using ::benchmark::State; using bluetooth::common::MessageLoopThread; using bluetooth::common::OnceTimer; using bluetooth::common::RepeatingTimer; using bluetooth::common::time_get_os_boottime_us; using bluetooth::common::Timer; // fake get_main_message_loop implementation for alarm base::MessageLoop* get_main_message_loop() { return nullptr; } Loading Loading @@ -104,14 +106,17 @@ class BM_AlarmTaskTimer : public ::benchmark::Fixture { message_loop_thread_ = new MessageLoopThread("timer_benchmark"); message_loop_thread_->StartUp(); message_loop_thread_->EnableRealTimeScheduling(); timer_ = new Timer(); once_timer_ = new OnceTimer(); repeating_timer_ = new RepeatingTimer(); g_promise = std::make_shared<std::promise<void>>(); } void TearDown(State& st) override { g_promise = nullptr; delete timer_; timer_ = nullptr; delete once_timer_; once_timer_ = nullptr; delete repeating_timer_; repeating_timer_ = nullptr; message_loop_thread_->ShutDown(); delete message_loop_thread_; message_loop_thread_ = nullptr; Loading @@ -119,18 +124,19 @@ class BM_AlarmTaskTimer : public ::benchmark::Fixture { } MessageLoopThread* message_loop_thread_; Timer* timer_; OnceTimer* once_timer_; RepeatingTimer* repeating_timer_; }; BENCHMARK_DEFINE_F(BM_AlarmTaskTimer, 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(); timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE, base::Bind(&TimerFire, nullptr), once_timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE, base::BindOnce(&TimerFire, nullptr), base::TimeDelta::FromMilliseconds(milliseconds)); g_promise->get_future().get(); timer_->Cancel(); once_timer_->Cancel(); auto end_time_point = time_get_os_boottime_us(); auto duration = end_time_point - start_time_point; state.SetIterationTime(duration * 1e-6); Loading Loading @@ -204,7 +210,8 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { message_loop_thread_ = new MessageLoopThread("timer_benchmark"); message_loop_thread_->StartUp(); message_loop_thread_->EnableRealTimeScheduling(); timer_ = new Timer(); once_timer_ = new OnceTimer(); repeating_timer_ = new RepeatingTimer(); g_map.clear(); g_promise = std::make_shared<std::promise<void>>(); g_scheduled_tasks = 0; Loading @@ -215,8 +222,10 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { void TearDown(State& st) override { g_promise = nullptr; delete timer_; timer_ = nullptr; delete once_timer_; once_timer_ = nullptr; delete repeating_timer_; repeating_timer_ = nullptr; message_loop_thread_->ShutDown(); delete message_loop_thread_; message_loop_thread_ = nullptr; Loading @@ -224,7 +233,8 @@ class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture { } MessageLoopThread* message_loop_thread_; Timer* timer_; OnceTimer* once_timer_; RepeatingTimer* repeating_timer_; }; BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy) Loading @@ -234,12 +244,12 @@ BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy) g_task_length = state.range(1); g_task_interval = state.range(2); g_start_time = time_get_os_boottime_us(); timer_->SchedulePeriodic( repeating_timer_->SchedulePeriodic( message_loop_thread_->GetWeakPtr(), FROM_HERE, base::Bind(&AlarmSleepAndCountDelayedTime, nullptr), base::BindRepeating(&AlarmSleepAndCountDelayedTime, nullptr), base::TimeDelta::FromMilliseconds(g_task_interval)); g_promise->get_future().get(); timer_->Cancel(); repeating_timer_->Cancel(); } for (const auto& delay : g_map) { state.counters[std::to_string(delay.first)] = delay.second; Loading
system/common/message_loop_thread.h +2 −1 Original line number Diff line number Diff line Loading @@ -176,7 +176,8 @@ class MessageLoopThread final { bool DoInThreadDelayed(const base::Location& from_here, base::OnceClosure task, const base::TimeDelta& delay); friend class Timer; // allow Timer to use DoInThreadDelayed() friend class RepeatingTimer; // allow Timer to use DoInThreadDelayed() friend class OnceTimer; // allow OnceTimer to use DoInThreadDelayed() /** * Actual method to run the thread, blocking until ShutDown() is called Loading
system/common/once_timer.cc 0 → 100644 +130 −0 Original line number Diff line number Diff line /* * 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 "once_timer.h" #include "message_loop_thread.h" #include "time_util.h" namespace bluetooth { namespace common { // This runs on user thread OnceTimer::~OnceTimer() { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); if (message_loop_thread_ != nullptr && message_loop_thread_->IsRunning()) { CancelAndWait(); } } // This runs on user thread bool OnceTimer::Schedule(const base::WeakPtr<MessageLoopThread>& thread, const base::Location& from_here, base::OnceClosure task, base::TimeDelta delay) { uint64_t time_now_us = time_get_os_boottime_us(); uint64_t time_next_task_us = time_now_us + delay.InMicroseconds(); std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); if (thread == nullptr) { LOG(ERROR) << __func__ << ": thread must be non-null"; return false; } CancelAndWait(); task_ = std::move(task); task_wrapper_.Reset( base::BindOnce(&OnceTimer::RunTask, base::Unretained(this))); message_loop_thread_ = thread; delay_ = delay; uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us(); if (!thread->DoInThreadDelayed( from_here, task_wrapper_.callback(), base::TimeDelta::FromMicroseconds(time_until_next_us))) { LOG(ERROR) << __func__ << ": failed to post task to message loop for thread " << *thread << ", from " << from_here.ToString(); task_wrapper_.Cancel(); message_loop_thread_ = nullptr; delay_ = {}; return false; } return true; } // This runs on user thread void OnceTimer::Cancel() { std::promise<void> promise; CancelHelper(std::move(promise)); } // This runs on user thread void OnceTimer::CancelAndWait() { std::promise<void> promise; auto future = promise.get_future(); CancelHelper(std::move(promise)); future.wait(); } // This runs on user thread void OnceTimer::CancelHelper(std::promise<void> promise) { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); MessageLoopThread* scheduled_thread = message_loop_thread_.get(); if (scheduled_thread == nullptr) { promise.set_value(); return; } if (scheduled_thread->GetThreadId() == base::PlatformThread::CurrentId()) { CancelClosure(std::move(promise)); return; } scheduled_thread->DoInThread( FROM_HERE, base::BindOnce(&OnceTimer::CancelClosure, base::Unretained(this), std::move(promise))); } // This runs on message loop thread void OnceTimer::CancelClosure(std::promise<void> promise) { message_loop_thread_ = nullptr; task_wrapper_.Cancel(); std::move(task_); delay_ = base::TimeDelta(); promise.set_value(); } // This runs on user thread bool OnceTimer::IsScheduled() const { std::lock_guard<std::recursive_mutex> api_lock(api_mutex_); return message_loop_thread_ != nullptr && message_loop_thread_->IsRunning(); } // This runs on message loop thread void OnceTimer::RunTask() { if (message_loop_thread_ == nullptr || !message_loop_thread_->IsRunning()) { LOG(ERROR) << __func__ << ": message_loop_thread_ is null or is not running"; return; } CHECK_EQ(message_loop_thread_->GetThreadId(), base::PlatformThread::CurrentId()) << ": task must run on message loop thread"; task_wrapper_.Cancel(); std::move(task_).Run(); message_loop_thread_ = nullptr; } } // namespace common } // namespace bluetooth