1// Copyright 2016 The Fuchsia Authors
2//
3// Use of this source code is governed by a MIT-style
4// license that can be found in the LICENSE file or at
5// https://opensource.org/licenses/MIT
6
7#pragma once
8
9#include <zircon/types.h>
10
11#include <fbl/canary.h>
12#include <fbl/intrusive_double_list.h>
13
14class Handle;
15
16// Observer base class for state maintained by StateTracker.
17class StateObserver {
18public:
19    // Optional initial counts. Each object might have a different idea of them
20    // and currently we assume at most two. The state observers will iterate on
21    // the entries and might fire if |signal| matches one of their trigger signals
22    // so each entry should be associated with a unique signal or with 0 if not
23    // applicable.
24    struct CountInfo {
25        struct {
26            uint64_t count;
27            zx_signals_t signal;
28        } entry[2];
29    };
30
31    StateObserver() { }
32
33    typedef unsigned Flags;
34
35    // Bitmask of return values for On...() methods
36    static constexpr Flags kNeedRemoval = 1;
37    static constexpr Flags kHandled = 2;
38
39    // Called when this object is added to a StateTracker, to give it the initial state.
40    // Note that |cinfo| might be null.
41    // May return flags: kNeedRemoval
42    // WARNING: This is called under StateTracker's mutex.
43    virtual Flags OnInitialize(zx_signals_t initial_state, const CountInfo* cinfo) = 0;
44
45    // Called whenever the state changes, to give it the new state.
46    // May return flags: kNeedRemoval
47    // WARNING: This is called under StateTracker's mutex
48    virtual Flags OnStateChange(zx_signals_t new_state) = 0;
49
50    // Called when |handle| (which refers to a handle to the object that owns the StateTracker) is
51    // being destroyed/"closed"/transferred. (The object itself, and thus the StateTracker too, may
52    // also be destroyed shortly afterwards.)
53    // Returns flag kHandled if |this| observer handled the call which normally
54    // means it was bound to |handle|.
55    // May also return flags: kNeedRemoval
56    // WARNING: This is called under StateTracker's mutex.
57    virtual Flags OnCancel(const Handle* handle) = 0;
58
59    // Called when the client wants to cancel an outstanding object_wait_aysnc(..key..). In this
60    // case the object might not be destroyed.
61    // Returns flag kHandled if |this| observer handled the call which normally
62    // means it was bound to |handle| and |key|.
63    // May also return flags: kNeedRemoval
64    // WARNING: This is called under StateTracker's mutex.
65    virtual Flags OnCancelByKey(const Handle* handle, const void* port, uint64_t key) { return 0; }
66
67    // Called after this observer has been removed from the state tracker list. In this callback
68    // is safe to delete the observer.
69    virtual void OnRemoved() {}
70
71protected:
72    ~StateObserver() {}
73
74private:
75    fbl::Canary<fbl::magic("SOBS")> canary_;
76
77    friend struct StateObserverListTraits;
78    fbl::DoublyLinkedListNodeState<StateObserver*> state_observer_list_node_state_;
79};
80
81// For use by StateTracker to maintain a list of StateObservers. (We don't use the default traits so
82// that implementations of StateObserver can themselves use the default traits if they need to be on
83// a different list.)
84struct StateObserverListTraits {
85    inline static fbl::DoublyLinkedListNodeState<StateObserver*>& node_state(
86            StateObserver& obj) {
87        return obj.state_observer_list_node_state_;
88    }
89};
90