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 1 commit
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
10 changes: 7 additions & 3 deletions src/inet/AsyncDNSResolverSockets.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ CHIP_ERROR AsyncDNSResolverSockets::Shutdown()

AsyncMutexLock();

mInet->State = InetLayer::kState_ShutdownInProgress;
if (mInet->mLayerState.GetState() != ObjectLifeCycle::State::ShuttingDown)
{
AsyncMutexUnlock();
return CHIP_ERROR_INCORRECT_STATE;
}

pthreadErr = pthread_cond_broadcast(&mAsyncDNSCondVar);
VerifyOrDie(pthreadErr == 0);
Expand Down Expand Up @@ -210,7 +214,7 @@ CHIP_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver ** outResolver)
AsyncMutexLock();

// block until there is work to do or we detect a shutdown
while ((mAsyncDNSQueueHead == nullptr) && (mInet->State == InetLayer::kState_Initialized))
while ((mAsyncDNSQueueHead == nullptr) && mInet->mLayerState.IsInitialized())
{
pthreadErr = pthread_cond_wait(&mAsyncDNSCondVar, &mAsyncDNSMutex);
VerifyOrDie(pthreadErr == 0);
Expand All @@ -219,7 +223,7 @@ CHIP_ERROR AsyncDNSResolverSockets::DequeueRequest(DNSResolver ** outResolver)
ChipLogDetail(Inet, "Async DNS worker thread woke up.");

// on shutdown, return NULL. Otherwise, pop the head of the DNS request queue
if (mInet->State != InetLayer::kState_Initialized)
if (!mInet->mLayerState.IsInitialized())
{
*outResolver = nullptr;
}
Expand Down
76 changes: 35 additions & 41 deletions src/inet/InetLayer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,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 @@ -241,9 +239,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 @@ -260,7 +256,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();

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_DNS_RESOLVER && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS
ReturnErrorOnFailure(mAsyncDNSResolver.Init(this));
Expand All @@ -279,52 +275,51 @@ 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_DNS_RESOLVER
// Cancel all DNS resolution requests owned by this instance.
DNSResolver::sPool.ForEachActiveObject([&](DNSResolver * lResolver) {
if ((lResolver != nullptr) && lResolver->IsCreatedByInetLayer(*this))
{
lResolver->Cancel();
}
return true;
});
// Cancel all DNS resolution requests owned by this instance.
DNSResolver::sPool.ForEachActiveObject([&](DNSResolver * lResolver) {
if ((lResolver != nullptr) && lResolver->IsCreatedByInetLayer(*this))
{
lResolver->Cancel();
}
return true;
});

#if CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS

err = mAsyncDNSResolver.Shutdown();
err = mAsyncDNSResolver.Shutdown();

#endif // CHIP_SYSTEM_CONFIG_USE_SOCKETS && INET_CONFIG_ENABLE_ASYNC_DNS_SOCKETS
#endif // INET_CONFIG_ENABLE_DNS_RESOLVER

#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 @@ -480,7 +475,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 @@ -520,7 +515,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 Expand Up @@ -689,7 +684,7 @@ CHIP_ERROR InetLayer::ResolveHostAddress(const char * hostName, uint16_t hostNam
CHIP_ERROR err = CHIP_NO_ERROR;
DNSResolver * resolver = nullptr;

VerifyOrExit(State == kState_Initialized, err = CHIP_ERROR_INCORRECT_STATE);
VerifyOrExit(mLayerState.IsInitialized(), err = CHIP_ERROR_INCORRECT_STATE);

INET_FAULT_INJECT(FaultInjection::kFault_DNSResolverNew, return CHIP_ERROR_NO_MEMORY);

Expand Down Expand Up @@ -778,8 +773,7 @@ void InetLayer::CancelResolveHostAddress(DNSResolveCompleteFunct onComplete, voi
{
assertChipStackLockedByCurrentThread();

if (State != kState_Initialized)
return;
VerifyOrReturn(mLayerState.IsInitialized());

DNSResolver::sPool.ForEachActiveObject([&](DNSResolver * lResolver) {
if (!lResolver->IsCreatedByInetLayer(*this))
Expand Down
12 changes: 2 additions & 10 deletions src/inet/InetLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,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 @@ -143,16 +144,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 @@ -257,6 +248,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
103 changes: 50 additions & 53 deletions src/lib/support/ObjectLifeCycle.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,57 +26,54 @@ 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
{
public:
enum class State : uint8_t
{
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; }

/**
* @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()
{
if (mState == State::Uninitialized)
{
mState = State::Initialized;
return true;
}
return false;
}

/**
* 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.
/*
* State transitions.
*
* @return true if the state was Initialized and is now Shutdown.
* @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 Shutdown()
{
if (mState == State::Initialized)
{
mState = State::Shutdown;
return true;
}
return false;
}
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

/**
* Transition from Shutdown back to Uninitialized, or remain Uninitialized.
Expand Down Expand Up @@ -115,21 +112,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
Loading