#include "services/webnn/resource_task.h"
#include "services/webnn/queueable_resource_state_base.h"
namespace webnn {
ResourceTask::ResourceTask(
std::vector<scoped_refptr<QueueableResourceStateBase>> shared_resources,
std::vector<scoped_refptr<QueueableResourceStateBase>> exclusive_resources,
base::OnceCallback<void(base::OnceClosure)> task)
: shared_resources_(std::move(shared_resources)),
exclusive_resources_(std::move(exclusive_resources)),
task_(std::move(task)) {}
void ResourceTask::Enqueue() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (CanExecute()) {
Execute(false);
return;
}
for (const auto& resource : shared_resources_) {
resource->EnqueueTask(this);
}
for (const auto& resource : exclusive_resources_) {
resource->EnqueueTask(this);
}
}
ResourceTask::~ResourceTask() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(task_.is_null());
}
bool ResourceTask::CanExecute() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& resource : shared_resources_) {
if (!resource->CanLock(false)) {
return false;
}
ResourceTask* task = resource->PeekTask();
if (task && task != this) {
return false;
}
}
for (const auto& resource : exclusive_resources_) {
if (!resource->CanLock(true)) {
return false;
}
ResourceTask* task = resource->PeekTask();
if (task && task != this) {
return false;
}
}
return true;
}
void ResourceTask::Execute(bool dequeue) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
scoped_refptr<ResourceTask> self;
for (const auto& resource : shared_resources_) {
if (dequeue) {
self = resource->PopTask();
CHECK_EQ(this, self.get());
}
resource->Lock(false);
}
for (const auto& resource : exclusive_resources_) {
if (dequeue) {
self = resource->PopTask();
CHECK_EQ(this, self.get());
}
resource->Lock(true);
}
std::move(task_).Run(base::BindOnce(&ResourceTask::Complete, this));
}
void ResourceTask::Complete() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
for (const auto& resource : shared_resources_) {
resource->Unlock();
}
for (const auto& resource : exclusive_resources_) {
resource->Unlock();
}
for (const auto& resource : shared_resources_) {
ResourceTask* task = resource->PeekTask();
if (task && task->CanExecute()) {
task->Execute(true);
}
}
for (const auto& resource : exclusive_resources_) {
while (ResourceTask* task = resource->PeekTask()) {
if (task->CanExecute()) {
task->Execute(true);
} else {
break;
}
}
}
}
}