Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ObjectLifeCycle for InetLayer #10522

Merged
merged 5 commits into from
Oct 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>(); }
andy31415 marked this conversation as resolved.
Show resolved Hide resolved
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