Line data Source code
1 : /*
2 : *
3 : * Copyright (c) 2021 Project CHIP Authors
4 : * All rights reserved.
5 : *
6 : * Licensed under the Apache License, Version 2.0 (the "License");
7 : * you may not use this file except in compliance with the License.
8 : * You may obtain a copy of the License at
9 : *
10 : * http://www.apache.org/licenses/LICENSE-2.0
11 : *
12 : * Unless required by applicable law or agreed to in writing, software
13 : * distributed under the License is distributed on an "AS IS" BASIS,
14 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 : * See the License for the specific language governing permissions and
16 : * limitations under the License.
17 : */
18 :
19 : #pragma once
20 :
21 : #include <cstdint>
22 :
23 : namespace chip {
24 :
25 : /**
26 : * Track the life cycle of an object.
27 : *
28 : * <pre>
29 : *
30 : * Construction
31 : * ↓
32 : * Uninitialized ‹─┐
33 : * ↓ │
34 : * Initializing │
35 : * ↓ │
36 : * Initialized │
37 : * ↓ │
38 : * ShuttingDown │
39 : * ↓ │
40 : * Shutdown ───────┘
41 : * ↓
42 : * Destroyed
43 : *
44 : * </pre>
45 : */
46 : class ObjectLifeCycle
47 : {
48 : public:
49 : enum class State : uint8_t
50 : {
51 : Uninitialized = 0, ///< Pre-initialized state.
52 : Initializing = 1, ///< State during intialization.
53 : Initialized = 2, ///< Initialized (active) state.
54 : ShuttingDown = 3, ///< State during shutdown.
55 : Shutdown = 4, ///< Post-shutdown state.
56 : Destroyed = 5, ///< Post-destructor state.
57 : };
58 :
59 : ObjectLifeCycle() : mState(State::Uninitialized) {}
60 0 : ~ObjectLifeCycle() { mState = State::Destroyed; }
61 :
62 : /**
63 : * @returns true if and only if the object is in the Initialized state.
64 : */
65 13308500 : bool IsInitialized() const { return mState == State::Initialized; }
66 :
67 : /*
68 : * State transitions.
69 : *
70 : * Typical use is `VerifyOrReturnError(state.SetInitializing(), CHIP_ERROR_INCORRECT_STATE)`; these functions return `bool`
71 : * rather than a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
72 : */
73 34 : bool SetInitializing() { return Transition(State::Uninitialized, State::Initializing); }
74 34 : bool SetInitialized() { return Transition(State::Initializing, State::Initialized); }
75 100 : bool SetShuttingDown() { return Transition(State::Initialized, State::ShuttingDown); }
76 : bool SetShutdown() { return Transition(State::ShuttingDown, State::Shutdown); }
77 : bool Reset() { return Transition(State::Shutdown, State::Uninitialized); }
78 :
79 : // Skip steps when a class's shutdown code has nothing useful to do in between.
80 100 : bool ResetFromShuttingDown() { return Transition(State::ShuttingDown, State::Uninitialized); }
81 : bool ResetFromInitialized() { return Transition(State::Initialized, State::Uninitialized); }
82 :
83 : /**
84 : * Transition from Uninitialized or Shutdown to Destroyed.
85 : *
86 : * Typical use is `VerifyOrReturnError(state.Destroy(), CHIP_ERROR_INCORRECT_STATE)`; this function returns `bool` rather than
87 : * a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
88 : *
89 : * @return true if the state was Uninitialized or Shutdown and is now Destroyed.
90 : * @return false otherwise.
91 : */
92 0 : bool Destroy()
93 : {
94 0 : if (mState == State::Uninitialized || mState == State::Shutdown)
95 : {
96 0 : mState = State::Destroyed;
97 0 : return true;
98 : }
99 0 : return false;
100 : }
101 :
102 : State GetState() const { return mState; }
103 :
104 : private:
105 118 : bool Transition(State from, State to)
106 : {
107 118 : if (mState == from)
108 : {
109 118 : mState = to;
110 118 : return true;
111 : }
112 0 : return false;
113 : }
114 :
115 : State mState;
116 : };
117 :
118 : } // namespace chip
|