/* * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #ifndef TEST_SINGLE_THREADED_TASK_QUEUE_H_ #define TEST_SINGLE_THREADED_TASK_QUEUE_H_ #include #include #include #include #include "api/task_queue/task_queue_base.h" #include "rtc_base/critical_section.h" #include "rtc_base/deprecation.h" #include "rtc_base/event.h" #include "rtc_base/platform_thread.h" #include "rtc_base/task_queue_for_test.h" #include "rtc_base/task_utils/to_queued_task.h" #include "rtc_base/thread_checker.h" namespace webrtc { namespace test { // DEPRECATED. This class doesn't striclty follow rtc::TaskQueue semantics, // which makes it surprising and hard to use correctly. // Please use TaskQueueForTest instead. // This class gives capabilities similar to rtc::TaskQueue, but ensures // everything happens on the same thread. This is intended to make the // threading model of unit-tests (specifically end-to-end tests) more closely // resemble that of real WebRTC, thereby allowing us to replace some critical // sections by thread-checkers. // This task is NOT tuned for performance, but rather for simplicity. class DEPRECATED_SingleThreadedTaskQueueForTesting : public TaskQueueBase { public: using Task = std::function; using TaskId = size_t; constexpr static TaskId kInvalidTaskId = static_cast(-1); explicit DEPRECATED_SingleThreadedTaskQueueForTesting(const char* name); ~DEPRECATED_SingleThreadedTaskQueueForTesting() override; // Sends one task to the task-queue, and returns a handle by which the // task can be cancelled. // This mimics the behavior of TaskQueue, but only for lambdas, rather than // for both lambdas and QueuedTask objects. TaskId PostTask(Task task) { return PostDelayed(ToQueuedTask(std::move(task)), /*delay_ms=*/0); } // Same as PostTask(), but ensures that the task will not begin execution // less than |delay_ms| milliseconds after being posted; an upper bound // is not provided. TaskId PostDelayedTask(Task task, int64_t delay_ms) { return PostDelayed(ToQueuedTask(std::move(task)), delay_ms); } // Given an identifier to the task, attempts to eject it from the queue. // Returns true if the task was found and cancelled. Failure possible // only for invalid task IDs, or for tasks which have already been executed. bool CancelTask(TaskId task_id); // Returns true iff called on the thread associated with the task queue. bool IsCurrent(); // Returns true iff the task queue is actively being serviced. bool IsRunning(); bool HasPendingTasks() const; void Stop(); // Implements TaskQueueBase. void Delete() override; void PostTask(std::unique_ptr task) override { PostDelayed(std::move(task), /*delay_ms=*/0); } void PostDelayedTask(std::unique_ptr task, uint32_t delay_ms) override { PostDelayed(std::move(task), delay_ms); } private: struct StoredTask { StoredTask(TaskId task_id, std::unique_ptr task); ~StoredTask(); TaskId task_id; std::unique_ptr task; }; TaskId PostDelayed(std::unique_ptr task, int64_t delay_ms); static void Run(void* obj); void RunLoop(); rtc::CriticalSection cs_; // Tasks are ordered by earliest execution time. std::multimap tasks_ RTC_GUARDED_BY(cs_); rtc::ThreadChecker owner_thread_checker_; rtc::PlatformThread thread_; bool running_ RTC_GUARDED_BY(cs_); TaskId next_task_id_; // The task-queue will sleep when not executing a task. Wake up occurs when: // * Upon destruction, to make sure that the |thead_| terminates, so that it // may be joined. [Event will be set.] // * New task added. Because we optimize for simplicity rahter than for // performance (this class is a testing facility only), waking up occurs // when we get a new task even if it is scheduled with a delay. The RunLoop // is in charge of sending itself back to sleep if the next task is only // to be executed at a later time. [Event will be set.] // * When the next task in the queue is a delayed-task, and the time for // its execution has come. [Event will time-out.] rtc::Event wake_up_; }; // Warn if new usage. typedef DEPRECATED_SingleThreadedTaskQueueForTesting RTC_DEPRECATED SingleThreadedTaskQueueForTesting; } // namespace test } // namespace webrtc #endif // TEST_SINGLE_THREADED_TASK_QUEUE_H_