Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cd985f72 authored by Jakub Pawlowski's avatar Jakub Pawlowski
Browse files

Split Timer into OnceTimer and RepeatingTimer

Follow the naming convention in libbase, where Callback was split into
OnceCallback, and RepeatingCallback, to make it obvious how many times
callback is expected to be called.

Test: unit tests were split from TimerTest into OnceTimerTest and
RepeatingTimerTest
Bug: 110303473
Change-Id: Ibbb9bb74a2e6e1a0f0f74c6ec44f63c5a4a1537f
parent 680f457c
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -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"
@@ -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;

@@ -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;
+4 −2
Original line number Diff line number Diff line
@@ -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: [
@@ -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",
    ],
+27 −17
Original line number Diff line number Diff line
@@ -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; }
@@ -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;
@@ -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);
@@ -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;
@@ -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;
@@ -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)
@@ -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;
+2 −1
Original line number Diff line number Diff line
@@ -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
+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