blob: d470c293c4a029e34c8681eb0ba4d3e3d5ae2213 [file] [log] [blame]
// Copyright 2018 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.
#pragma once
#include <list>
#include <memory>
#include <set>
#include <fbl/macros.h>
#include <lib/async-testutils/dispatcher_stub.h>
#include <lib/async-testutils/time-keeper.h>
#include <lib/async/dispatcher.h>
#include <lib/async/task.h>
#include <lib/async/wait.h>
#include <lib/zx/port.h>
#include <lib/zx/time.h>
#include <zircon/listnode.h>
namespace async {
// An asynchronous dispatcher with an abstracted sense of time, controlled by an
// external time-keeping object, for use in testing.
class TestLoopDispatcher : public DispatcherStub {
public:
TestLoopDispatcher(TimeKeeper* time_keeper);
~TestLoopDispatcher();
DISALLOW_COPY_ASSIGN_AND_MOVE(TestLoopDispatcher);
// async_dispatcher_t operation implementations.
zx::time Now() override;
zx_status_t BeginWait(async_wait_t* wait) override;
zx_status_t CancelWait(async_wait_t* wait) override;
zx_status_t PostTask(async_task_t* task) override;
zx_status_t CancelTask(async_task_t* task) override;
// Dispatches the next due task or wait. Returns true iff a message was
// dispatched.
bool DispatchNextDueMessage();
// Whether there are any due tasks or waits.
bool HasPendingWork();
// Returns the deadline of the next posted task if one is pending; else
// returns zx::time::infinite().
zx::time GetNextTaskDueTime();
private:
class Activated;
class TaskActivated;
class WaitActivated;
class AsyncTaskComparator {
public:
bool operator()(async_task_t* t1, async_task_t* t2) const { return t1->deadline < t2->deadline; }
};
// Extracts activated tasks and waits to |activated_|.
void ExtractActivated();
// Removes the given task or wait from |activables_| and |activated_|.
zx_status_t CancelActivatedTaskOrWait(void* task_or_wait);
// Dispatches all remaining posted waits and tasks, invoking their handlers
// with status ZX_ERR_CANCELED.
void Shutdown();
// A reference to an external object that manages the current time.
TimeKeeper* const time_keeper_;
// Whether the loop is shutting down.
bool in_shutdown_ = false;
// Pending tasks activable in the future.
// The ordering of the set is based on the task timeline. Multiple tasks
// with the same deadline will be equivalent, and be ordered by order of
// insertion.
std::multiset<async_task_t*, AsyncTaskComparator> future_tasks_;
// Pending waits.
std::set<async_wait_t*> pending_waits_;
// Activated elements, ready to be dispatched.
std::list<std::unique_ptr<Activated>> activated_;
// Port used to register waits.
zx::port port_;
};
} // namespace async