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 8288074 : 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 14 : bool SetInitializing() { return Transition(State::Uninitialized, State::Initializing); } 74 14 : bool SetInitialized() { return Transition(State::Initializing, State::Initialized); } 75 80 : 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 80 : 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 50 : bool Transition(State from, State to) 106 : { 107 50 : if (mState == from) 108 : { 109 50 : mState = to; 110 50 : return true; 111 : } 112 0 : return false; 113 : } 114 : 115 : State mState; 116 : }; 117 : 118 : } // namespace chip