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 
14 class Handle;
15 
16 // Observer base class for state maintained by StateTracker.
17 class StateObserver {
18 public:
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 
StateObserver()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.
OnCancelByKey(const Handle * handle,const void * port,uint64_t key)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.
OnRemoved()69     virtual void OnRemoved() {}
70 
71 protected:
~StateObserver()72     ~StateObserver() {}
73 
74 private:
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.)
84 struct StateObserverListTraits {
node_stateStateObserverListTraits85     inline static fbl::DoublyLinkedListNodeState<StateObserver*>& node_state(
86             StateObserver& obj) {
87         return obj.state_observer_list_node_state_;
88     }
89 };
90