Skip to content

Commit

Permalink
Use ObjectLifeCycle for InetLayer (#10522)
Browse files Browse the repository at this point in the history
* Use ObjectLifeCycle for InetLayer

#### Problem

Working toward #7715 Virtualize System and Inet interfaces

#### Change overview

Revise ObjectLifeCycle and use it for InetLayer

#### Testing

CI; no changes to visibile functionality intended.

* change Reset() to expect Shutdown state
  • Loading branch information
kpschoedel authored and pull[bot] committed Dec 6, 2021
1 parent 06b6f98 commit 1365021
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 124 deletions.
53 changes: 24 additions & 29 deletions src/inet/InetLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,6 @@ void InetLayer::UpdateSnapshot(chip::System::Stats::Snapshot & aSnapshot)
*/
InetLayer::InetLayer()
{
State = kState_NotInitialized;

#if CHIP_SYSTEM_CONFIG_USE_LWIP
if (!sInetEventHandlerDelegate.IsInitialized())
sInetEventHandlerDelegate.Init(HandleInetLayerEvent);
Expand Down Expand Up @@ -237,9 +235,7 @@ void InetLayer::DroppableEventDequeued(void)
CHIP_ERROR InetLayer::Init(chip::System::Layer & aSystemLayer, void * aContext)
{
Inet::RegisterLayerErrorFormatter();

if (State != kState_NotInitialized)
return CHIP_ERROR_INCORRECT_STATE;
VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);

// Platform-specific initialization may elect to set this data
// member. Ensure it is set to a sane default value before
Expand All @@ -256,7 +252,7 @@ CHIP_ERROR InetLayer::Init(chip::System::Layer & aSystemLayer, void * aContext)
static_cast<System::LayerLwIP *>(mSystemLayer)->AddEventHandlerDelegate(sInetEventHandlerDelegate);
#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

State = kState_Initialized;
mLayerState.SetInitialized();

return CHIP_NO_ERROR;
}
Expand All @@ -271,35 +267,34 @@ CHIP_ERROR InetLayer::Init(chip::System::Layer & aSystemLayer, void * aContext)
*/
CHIP_ERROR InetLayer::Shutdown()
{
VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE);

CHIP_ERROR err = CHIP_NO_ERROR;

if (State == kState_Initialized)
{
#if INET_CONFIG_ENABLE_TCP_ENDPOINT
// Abort all TCP endpoints owned by this instance.
TCPEndPoint::sPool.ForEachActiveObject([&](TCPEndPoint * lEndPoint) {
if ((lEndPoint != nullptr) && lEndPoint->IsCreatedByInetLayer(*this))
{
lEndPoint->Abort();
}
return true;
});
// Abort all TCP endpoints owned by this instance.
TCPEndPoint::sPool.ForEachActiveObject([&](TCPEndPoint * lEndPoint) {
if ((lEndPoint != nullptr) && lEndPoint->IsCreatedByInetLayer(*this))
{
lEndPoint->Abort();
}
return true;
});
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT

#if INET_CONFIG_ENABLE_UDP_ENDPOINT
// Close all UDP endpoints owned by this instance.
UDPEndPoint::sPool.ForEachActiveObject([&](UDPEndPoint * lEndPoint) {
if ((lEndPoint != nullptr) && lEndPoint->IsCreatedByInetLayer(*this))
{
lEndPoint->Close();
}
return true;
});
// Close all UDP endpoints owned by this instance.
UDPEndPoint::sPool.ForEachActiveObject([&](UDPEndPoint * lEndPoint) {
if ((lEndPoint != nullptr) && lEndPoint->IsCreatedByInetLayer(*this))
{
lEndPoint->Close();
}
return true;
});
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT
}

State = kState_NotInitialized;

mLayerState.SetShutdown();
mLayerState.Reset(); // Return to uninitialized state to permit re-initialization.
return err;
}

Expand Down Expand Up @@ -455,7 +450,7 @@ CHIP_ERROR InetLayer::NewTCPEndPoint(TCPEndPoint ** retEndPoint)

*retEndPoint = nullptr;

VerifyOrReturnError(State == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

*retEndPoint = TCPEndPoint::sPool.TryCreate();
if (*retEndPoint == nullptr)
Expand Down Expand Up @@ -495,7 +490,7 @@ CHIP_ERROR InetLayer::NewUDPEndPoint(UDPEndPoint ** retEndPoint)

*retEndPoint = nullptr;

VerifyOrReturnError(State == kState_Initialized, CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

*retEndPoint = UDPEndPoint::sPool.TryCreate();
if (*retEndPoint == nullptr)
Expand Down
12 changes: 2 additions & 10 deletions src/inet/InetLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
#include <system/SystemStats.h>

#include <lib/support/DLLUtil.h>
#include <lib/support/ObjectLifeCycle.h>

#if INET_CONFIG_MAX_DROPPABLE_EVENTS

Expand Down Expand Up @@ -124,16 +125,6 @@ class DLL_EXPORT InetLayer
#endif // INET_CONFIG_ENABLE_UDP_ENDPOINT

public:
/**
* The current state of the InetLayer object.
*
*/
volatile enum {
kState_NotInitialized = 0, /**< Not initialized state. */
kState_Initialized = 1, /**< Initialized state. */
kState_ShutdownInProgress = 2, /**< State where Shutdown has been triggered. */
} State; /**< [READ-ONLY] Current state. */

InetLayer();

CHIP_ERROR Init(chip::System::Layer & aSystemLayer, void * aContext);
Expand Down Expand Up @@ -224,6 +215,7 @@ class DLL_EXPORT InetLayer
#endif // INET_CONFIG_ENABLE_TCP_ENDPOINT && INET_TCP_IDLE_CHECK_INTERVAL > 0

private:
ObjectLifeCycle mLayerState;
void * mContext;
void * mPlatformData;
chip::System::Layer * mSystemLayer;
Expand Down
122 changes: 51 additions & 71 deletions src/lib/support/ObjectLifeCycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,75 +26,55 @@ namespace chip {
* Track the life cycle of an object.
*
* <pre>
* ┌───────────────┐ Init ┌─────────────┐ Shutdown ┌──────────┐ Destroy ┌───────────┐
* Construction ───>│ Uninitialized ├───────>│ Initialized ├───────────>│ Shutdown ├──────────>│ Destroyed │
* └──────────┬────┘ └─────────────┘ └─────┬────┘ └───────────┘
* ^ │ Reset │
* └──────┴<─────────────────────────────────────────────┘
*
* Construction
* ↓
* Uninitialized ‹─┐
* ↓ │
* Initializing │
* ↓ │
* Initialized │
* ↓ │
* ShuttingDown │
* ↓ │
* Shutdown ───────┘
* ↓
* Destroyed
*
* </pre>
*/
struct ObjectLifeCycle
class ObjectLifeCycle
{
/**
* @returns true if and only if the object is in the Initialized state.
*/
bool IsInitialized() const { return mState == State::Initialized; }

/**
* Transition from Uninitialized to Initialized.
*
* Typical use is `VerifyOrReturnError(state.Init(), CHIP_ERROR_INCORRECT_STATE)`; this function returns `bool` rather than
* a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
*
* @return true if the state was Uninitialized and is now Initialized.
* @return false otherwise.
*/
bool Init()
public:
enum class State : uint8_t
{
if (mState == State::Uninitialized)
{
mState = State::Initialized;
return true;
}
return false;
}
Uninitialized = 0, ///< Pre-initialized state.
Initializing = 1, ///< State during intialization.
Initialized = 2, ///< Initialized (active) state.
ShuttingDown = 3, ///< State during shutdown.
Shutdown = 4, ///< Post-shutdown state.
Destroyed = 5, ///< Post-destructor state.
};

ObjectLifeCycle() : mState(State::Uninitialized) {}
~ObjectLifeCycle() { mState = State::Destroyed; }

/**
* Transition from Initialized to Shutdown.
*
* Typical use is `VerifyOrReturnError(state.Shutdown(), CHIP_ERROR_INCORRECT_STATE)`; this function returns `bool` rather than
* a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
*
* @return true if the state was Initialized and is now Shutdown.
* @return false otherwise.
* @returns true if and only if the object is in the Initialized state.
*/
bool Shutdown()
{
if (mState == State::Initialized)
{
mState = State::Shutdown;
return true;
}
return false;
}
bool IsInitialized() const { return mState == State::Initialized; }

/**
* Transition from Shutdown back to Uninitialized, or remain Uninitialized.
*
* Typical use is `VerifyOrReturnError(state.Reset(), CHIP_ERROR_INCORRECT_STATE)`; this function returns `bool` rather than
* a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
/*
* State transitions.
*
* @return true if the state was Uninitialized or Shutdown and is now Uninitialized.
* @return false otherwise.
* Typical use is `VerifyOrReturnError(state.SetInitializing(), CHIP_ERROR_INCORRECT_STATE)`; these functions return `bool`
* rather than a `CHIP_ERROR` so that error source tracking will record the call point rather than this function itself.
*/
bool Reset()
{
if (mState == State::Shutdown)
{
mState = State::Uninitialized;
}
return mState == State::Uninitialized;
}
bool SetInitializing() { return Transition<State::Uninitialized, State::Initializing>(); }
bool SetInitialized() { return Transition<State::Initializing, State::Initialized>(); }
bool SetShuttingDown() { return Transition<State::Initialized, State::ShuttingDown>(); }
bool SetShutdown() { return Transition<State::ShuttingDown, State::Shutdown>(); }
bool Reset() { return Transition<State::Shutdown, State::Uninitialized>(); }

/**
* Transition from Uninitialized or Shutdown to Destroyed.
Expand All @@ -115,21 +95,21 @@ struct ObjectLifeCycle
return false;
}

/**
* Return the current state as an integer. This is intended for troubleshooting or logging, since there is no code access to
* the meaning of the integer value.
*/
explicit operator int() const { return static_cast<int>(mState); }
State GetState() const { return mState; }

private:
enum class State : uint8_t
template <State FROM, State TO>
bool Transition()
{
Uninitialized = 0, /**< Pre-initialized state; */
Initialized = 1, /**< Initialized state. */
Shutdown = 2, /**< Post-Shutdown state. */
Destroyed = 3, /**< Post-destructor state. */
};
State mState = State::Uninitialized;
if (mState == FROM)
{
mState = TO;
return true;
}
return false;
}

State mState;
};

} // namespace chip
1 change: 0 additions & 1 deletion src/system/SystemLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@

#include <lib/support/CodeUtils.h>
#include <lib/support/DLLUtil.h>
#include <lib/support/ObjectLifeCycle.h>
#include <system/SystemError.h>
#include <system/SystemEvent.h>
#include <system/SystemObject.h>
Expand Down
7 changes: 4 additions & 3 deletions src/system/SystemLayerImplLibevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ System::SocketEvents SocketEventsFromLibeventFlags(short eventFlags)

CHIP_ERROR LayerImplLibevent::Init(System::Layer & systemLayer)
{
VerifyOrReturnError(!mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);

RegisterPOSIXErrorFormatter();

Expand Down Expand Up @@ -83,7 +83,7 @@ CHIP_ERROR LayerImplLibevent::Init(System::Layer & systemLayer)

Mutex::Init(mTimerListMutex);

VerifyOrReturnError(mLayerState.Init(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE);
return CHIP_NO_ERROR;
}

Expand Down Expand Up @@ -111,7 +111,7 @@ void LayerImplLibevent::MdnsTimeoutCallbackHandler()

CHIP_ERROR LayerImplLibevent::Shutdown()
{
VerifyOrReturnError(mLayerState.Shutdown(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE);

event_base_loopbreak(mEventBase);

Expand All @@ -133,6 +133,7 @@ CHIP_ERROR LayerImplLibevent::Shutdown()
mEventBase = nullptr;
mSystemLayer = nullptr;

mLayerState.SetShutdown();
mLayerState.Reset(); // Return to uninitialized state to permit re-initialization.
return CHIP_NO_ERROR;
}
Expand Down
2 changes: 1 addition & 1 deletion src/system/SystemLayerImplLibevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class LayerImplLibevent : public LayerSocketsLoop
{
public:
LayerImplLibevent() : mEventBase(nullptr), mMdnsTimeoutEvent(nullptr) {}
~LayerImplLibevent() { mLayerState.Destroy(); }
~LayerImplLibevent() = default;

// Layer overrides.
CHIP_ERROR Init() override;
Expand Down
7 changes: 4 additions & 3 deletions src/system/SystemLayerImplLwIP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,19 +34,20 @@ LayerImplLwIP::LayerImplLwIP() : mHandlingTimerComplete(false), mEventDelegateLi

CHIP_ERROR LayerImplLwIP::Init()
{
VerifyOrReturnError(!mLayerState.IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetInitializing(), CHIP_ERROR_INCORRECT_STATE);

RegisterLwIPErrorFormatter();

ReturnErrorOnFailure(mTimerList.Init());

VerifyOrReturnError(mLayerState.Init(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetInitialized(), CHIP_ERROR_INCORRECT_STATE);
return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplLwIP::Shutdown()
{
VerifyOrReturnError(mLayerState.Shutdown(), CHIP_ERROR_INCORRECT_STATE);
VerifyOrReturnError(mLayerState.SetShuttingDown(), CHIP_ERROR_INCORRECT_STATE);
mLayerState.SetShutdown();
mLayerState.Reset(); // Return to uninitialized state to permit re-initialization.
return CHIP_NO_ERROR;
}
Expand Down
2 changes: 1 addition & 1 deletion src/system/SystemLayerImplLwIP.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class LayerImplLwIP : public LayerLwIP
{
public:
LayerImplLwIP();
~LayerImplLwIP() { mLayerState.Destroy(); }
~LayerImplLwIP() = default;

// Layer overrides.
CHIP_ERROR Init() override;
Expand Down
Loading

0 comments on commit 1365021

Please sign in to comment.