blob: 273c3fc38df15a40e91191bfad5cb3d2abf47fd9 [file] [log] [blame]
// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_BROADCOM_BRCMFMAC_TASK_QUEUE_H_
#define SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_BROADCOM_BRCMFMAC_TASK_QUEUE_H_
#include <condition_variable>
#include <functional>
#include <limits>
#include <list>
#include <mutex>
#include <utility>
namespace wlan {
namespace brcmfmac {
template <typename T>
class task_queue {
public:
using value_type = T;
using container_type = std::list<T>;
task_queue() = default;
~task_queue() = default;
template <typename... Args>
void emplace(Args&&... args) {
container_type task;
task.emplace_back(std::forward<Args>(args)...);
std::lock_guard lock(tasks_mutex_);
const bool should_signal = tasks_.empty();
tasks_.splice(tasks_.end(), std::move(task));
if (should_signal) {
tasks_condvar_.notify_one();
}
}
void splice(task_queue&& tasks) {
container_type other_tasks;
{
std::lock_guard lock(tasks.tasks_mutex_);
other_tasks = std::move(tasks.tasks_);
}
splice(std::move(other_tasks));
}
void splice(container_type&& tasks) {
std::lock_guard lock(tasks_mutex_);
const bool should_signal = tasks_.empty() && !tasks.empty();
tasks_.splice(tasks_.end(), std::move(tasks));
if (should_signal) {
tasks_condvar_.notify_one();
}
}
bool empty() const {
std::lock_guard lock(tasks_mutex_);
return tasks_.empty();
}
void clear() {
std::lock_guard lock(tasks_mutex_);
tasks_.clear();
}
// Run tasks on this task_queue instance, blocking until at least one task is available. Returns
// the number of tasks run.
template <typename... Args>
size_t run(Args&&... args) {
container_type tasks;
{
std::unique_lock lock(tasks_mutex_);
while (tasks_.empty()) {
tasks_condvar_.wait(lock);
}
tasks.splice(tasks.end(), std::move(tasks_));
}
size_t run_count = 0;
while (!tasks.empty()) {
std::invoke(tasks.front(), std::forward<Args>(args)...);
tasks.pop_front();
++run_count;
}
return run_count;
}
// Run tasks on this task_queue instance, or none if none are immediately available. Does not
// block. Returns the number of tasks run.
template <typename... Args>
size_t try_run(Args&&... args) {
container_type tasks;
{
std::lock_guard lock(tasks_mutex_);
tasks.splice(tasks.end(), std::move(tasks_));
}
size_t run_count = 0;
while (!tasks.empty()) {
std::invoke(tasks.front(), std::forward<Args>(args)...);
tasks.pop_front();
++run_count;
}
return run_count;
}
private:
container_type tasks_;
mutable std::mutex tasks_mutex_;
std::condition_variable tasks_condvar_;
};
} // namespace brcmfmac
} // namespace wlan
#endif // SRC_CONNECTIVITY_WLAN_DRIVERS_THIRD_PARTY_BROADCOM_BRCMFMAC_TASK_QUEUE_H_