#ifndef BASE_TASK_SEQUENCE_MANAGER_WORK_QUEUE_SETS_H_
#define BASE_TASK_SEQUENCE_MANAGER_WORK_QUEUE_SETS_H_
#include <functional>
#include <optional>
#include <vector>
#include "base/base_export.h"
#include "base/containers/intrusive_heap.h"
#include "base/dcheck_is_on.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/memory/stack_allocated.h"
#include "base/task/sequence_manager/sequence_manager.h"
#include "base/task/sequence_manager/task_order.h"
#include "base/task/sequence_manager/task_queue_impl.h"
#include "base/task/sequence_manager/work_queue.h"
namespace base {
namespace sequence_manager {
namespace internal {
struct WorkQueueAndTaskOrder {
STACK_ALLOCATED();
public:
WorkQueueAndTaskOrder(WorkQueue& work_queue, const TaskOrder& task_order)
: queue(&work_queue), order(task_order) {}
WorkQueue* queue = nullptr;
TaskOrder order;
};
class BASE_EXPORT WorkQueueSets {
public:
class Observer {
public:
virtual ~Observer() = default;
virtual void WorkQueueSetBecameEmpty(size_t set_index) = 0;
virtual void WorkQueueSetBecameNonEmpty(size_t set_index) = 0;
};
WorkQueueSets(const char* name,
Observer* observer,
const SequenceManager::Settings& settings);
WorkQueueSets(const WorkQueueSets&) = delete;
WorkQueueSets& operator=(const WorkQueueSets&) = delete;
~WorkQueueSets();
void AddQueue(WorkQueue* queue, size_t set_index);
void RemoveQueue(WorkQueue* work_queue);
void ChangeSetIndex(WorkQueue* queue, size_t set_index);
void OnQueuesFrontTaskChanged(WorkQueue* queue);
void OnTaskPushedToEmptyQueue(WorkQueue* work_queue);
void OnPopMinQueueInSet(WorkQueue* work_queue);
void OnQueueBlocked(WorkQueue* work_queue);
std::optional<WorkQueueAndTaskOrder> GetOldestQueueAndTaskOrderInSet(
size_t set_index) const;
#if DCHECK_IS_ON()
std::optional<WorkQueueAndTaskOrder> GetRandomQueueAndTaskOrderInSet(
size_t set_index) const;
#endif
bool IsSetEmpty(size_t set_index) const;
#if DCHECK_IS_ON() || !defined(NDEBUG)
bool ContainsWorkQueueForTest(const WorkQueue* queue) const;
#endif
const char* GetName() const { return name_; }
void CollectSkippedOverLowerPriorityTasks(
const internal::WorkQueue* selected_work_queue,
std::vector<const Task*>* result) const;
private:
struct OldestTaskOrder {
TaskOrder key;
RAW_PTR_EXCLUSION WorkQueue* value = nullptr;
bool operator>(const OldestTaskOrder& other) const {
return key > other.key;
}
void SetHeapHandle(HeapHandle handle) { value->set_heap_handle(handle); }
void ClearHeapHandle() { value->set_heap_handle(HeapHandle()); }
HeapHandle GetHeapHandle() const { return value->heap_handle(); }
};
const char* const name_;
std::vector<IntrusiveHeap<OldestTaskOrder, std::greater<>>> work_queue_heaps_;
#if DCHECK_IS_ON()
static inline uint64_t MurmurHash3(uint64_t value) {
value ^= value >> 33;
value *= uint64_t{0xFF51AFD7ED558CCD};
value ^= value >> 33;
value *= uint64_t{0xC4CEB9FE1A85EC53};
value ^= value >> 33;
return value;
}
uint64_t Random() const {
last_rand_ = MurmurHash3(last_rand_);
return last_rand_;
}
mutable uint64_t last_rand_;
#endif
const raw_ptr<Observer> observer_;
};
}
}
}
#endif