blob: 53e7bf750006ab85a17afc393fa05342dfc17cff [file] [log] [blame]
// Copyright 2018 The Chromium 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 CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_TASK_QUEUE_H_
#define CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_TASK_QUEUE_H_
#include "base/callback.h"
#include "base/containers/queue.h"
#include "chromeos/dbus/smb_provider_client.h"
namespace chromeos {
namespace smb_client {
// An SmbTask is a call to SmbProviderClient with a bound SmbFileSystem callback
// that runs when SmbProviderClient receives a D-Bus message response.
using SmbTask = base::OnceClosure;
using OperationId = uint32_t;
// SmbTaskQueue handles the queuing of SmbTasks. Tasks are 'pending' while
// SmbProviderClient awaits a D-Bus Message Response. Tasks are added to
// the queue via SmbTaskQueue::AddTask. Upon the SmbFileSystem callback in the
// task running, the caller must call SmbTaskQueue::TaskFinished to allow the
// next task to run.
//
// Example:
//
// AbortCallback CreateDirectory(FilePath directory_path, bool recursive,
// StatusCallback callback) {
// auto reply = base::BindOnce(&SmbFileSystem::HandleStatusCallback,
// AsWeakPtr(), callback);
//
// SmbTask task = base::BindOnce(&SmbProviderClient::CreateDirectory,
// base::Unretained(GetSmbProviderClient()),
// GetMountId(),
// directory_path,
// recursive,
// std::move(reply));
// OperationId operation_id = 1;
// tq_.AddTask(std::move(task));
//
// return CreateAbortCallbackForOperationId(operation_id);
// }
//
// void HandleStatusCallback(StatusCallback callback, ErrorType error) {
// tq_.TaskFinished();
// callback.Run(error);
// }
class SmbTaskQueue {
public:
// Provides the caller with a new OperationId to associate new tasks with.
OperationId GetNextOperationId();
// Adds the sub-task |task| for the Operation |operation_id| to the task
// queue. If fewer that max_pending_ tasks are outstanding, |task| will run
// immediately. Otherwise, it will be added to operations_ and run in FIFO
// order.
void AddTask(SmbTask task, OperationId operation_id);
// Attempts to abort any outstanding tasks associated with the operation
// |operation_id|. Any subtasks that have not been sent over to D-Bus to the
// Smb Daemon will be cancelled, and OperationId will be removed from
// operation_map_.
void AbortOperation(OperationId operation_id);
// Must be called by the owner of this class to indicate that a response to a
// task was received.
void TaskFinished();
explicit SmbTaskQueue(size_t max_pending);
~SmbTaskQueue();
private:
using TaskList = base::queue<SmbTask>;
// This runs the next task in operations_ if there is capacity to run an
// additional task, and a task remaing to run.
void RunTaskIfNeccessary();
// Helper method that returns the next task to run.
SmbTask GetNextTask();
// Helper method that runs the next task.
void RunNextTask();
// Prunes operations_ by removing OperationIds from the front of the queue if
// there are no tasks associated with them.
void PruneOperationQueue();
// Helper method that returns whether operations_ has been pruned.
bool IsPruned() const;
// Helper method that returns whether there are tasks in operations_ to run.
// operations_ must be pruned (i.e. the top Operation in operations_ must have
// atleast 1 task associated with it).
bool IsTaskToRun() const;
// Helper method that returns whether there are fewer than max_pending tasks
// outstanding.
bool IsCapacityToRunTask() const;
// Helper method that returns whether |operation_id| is valid.
bool IsValidOperationId(OperationId operation_id) const;
const size_t max_pending_;
size_t num_pending_ = 0;
OperationId next_operation_id = 0;
base::queue<OperationId> operations_;
std::map<OperationId, TaskList> operation_map_;
DISALLOW_COPY_AND_ASSIGN(SmbTaskQueue);
};
} // namespace smb_client
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_SMB_CLIENT_SMB_TASK_QUEUE_H_