blob: 8b0c51a68aa23d51486a401007ac2881a3c81672 [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 <fbl/macros.h>
#include <fbl/unique_ptr.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 TimerDispatcher {
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;
// TimerDispatcher operation implementation.
void FireTimer() 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:
// Moves due tasks from |task_list_| to |due_list_|.
void ExtractDueTasks();
// Dispatches the next due task.
void DispatchNextDueTask();
// Dequeues from |port_| the next due packet. Must not be called if
// |due_packet_| is already non-null.
void ExtractNextDuePacket();
// 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 and
// and timers.
TimeKeeper* const time_keeper_;
// Port on which waits and timer expirations from |time_keeper_| are
// signaled.
zx::port port_;
// The most recent packet dequeued from |port_|.
fbl::unique_ptr<zx_port_packet_t> due_packet_;
// Pending tasks, earliest deadline first.
list_node_t task_list_;
// Due tasks, earliest deadlines first.
list_node_t due_list_;
// Pending waits, most recently added first.
list_node_t wait_list_;
};
} // namespace async