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

SystemLayer::PostEvent add API to post a lambda event #9678

Merged
merged 1 commit into from
Sep 17, 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
3 changes: 3 additions & 0 deletions src/include/platform/CHIPDeviceEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ enum InternalEventTypes
kEventTypeNotSet = kRange_Internal,
kNoOp,
kCallWorkFunct,
kChipLambdaEvent,
kChipSystemLayerEvent,
kCHIPoBLESubscribe,
kCHIPoBLEUnsubscribe,
Expand Down Expand Up @@ -302,6 +303,7 @@ typedef void (*AsyncWorkFunct)(intptr_t arg);
#include <ble/BleConfig.h>
#include <inet/InetLayer.h>
#include <system/SystemEvent.h>
#include <system/SystemLayer.h>
#include <system/SystemObject.h>
#include <system/SystemPacketBuffer.h>

Expand All @@ -318,6 +320,7 @@ struct ChipDeviceEvent final
union
{
ChipDevicePlatformEvent Platform;
System::LambdaBridge LambdaEvent;
struct
{
::chip::System::EventType Type;
Expand Down
4 changes: 4 additions & 0 deletions src/include/platform/internal/GenericPlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,10 @@ void GenericPlatformManagerImpl<ImplClass>::_DispatchEvent(const ChipDeviceEvent
Impl()->DispatchEventToSystemLayer(event);
break;

case DeviceEventType::kChipLambdaEvent:
event->LambdaEvent.LambdaProxy(static_cast<const void *>(event->LambdaEvent.LambdaBody));
break;

case DeviceEventType::kCallWorkFunct:
// If the event is a "call work function" event, call the specified function.
event->CallWorkFunct.WorkFunct(event->CallWorkFunct.Arg);
Expand Down
18 changes: 18 additions & 0 deletions src/lib/core/CHIPConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -2470,6 +2470,24 @@ extern const char CHIP_NON_PRODUCTION_MARKER[];
#define CHIP_DEVICE_CONTROLLER_SUBSCRIPTION_ATTRIBUTE_PATH_POOL_SIZE CHIP_IM_MAX_NUM_READ_CLIENT
#endif

/**
* @def CHIP_CONFIG_LAMBDA_EVENT_SIZE
*
* @brief The maximum size of the lambda which can be post into system event queue.
*/
#ifndef CHIP_CONFIG_LAMBDA_EVENT_SIZE
#define CHIP_CONFIG_LAMBDA_EVENT_SIZE (16)
#endif

/**
* @def CHIP_CONFIG_LAMBDA_EVENT_ALIGN
*
* @brief The maximum alignment of the lambda which can be post into system event queue.
*/
#ifndef CHIP_CONFIG_LAMBDA_EVENT_ALIGN
#define CHIP_CONFIG_LAMBDA_EVENT_ALIGN (sizeof(void *))
#endif

/**
* @}
*/
9 changes: 9 additions & 0 deletions src/platform/LwIPEventSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ namespace System {

using namespace ::chip::DeviceLayer;

CHIP_ERROR PlatformEventing::ScheduleLambdaBridge(System::Layer & aLayer, const LambdaBridge & bridge)
{
ChipDeviceEvent event;
event.Type = DeviceEventType::kChipLambdaEvent;
event.LambdaEvent = bridge;

return PlatformMgr().PostEvent(&event);
}

CHIP_ERROR PlatformEventing::PostEvent(System::Layer & aLayer, System::Object & aTarget, System::EventType aType,
uintptr_t aArgument)
{
Expand Down
2 changes: 2 additions & 0 deletions src/system/LwIPEventSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#include <lib/core/CHIPError.h>
#include <system/SystemEvent.h>
#include <system/SystemLayer.h>

namespace chip {
namespace System {
Expand All @@ -28,6 +29,7 @@ class Object;
class PlatformEventing
{
public:
static CHIP_ERROR ScheduleLambdaBridge(System::Layer & aLayer, const LambdaBridge & bridge);
static CHIP_ERROR PostEvent(System::Layer & aLayer, Object & aTarget, EventType aType, uintptr_t aArgument);
static CHIP_ERROR DispatchEvents(System::Layer & aLayer);
static CHIP_ERROR DispatchEvent(System::Layer & aLayer, Event aEvent);
Expand Down
10 changes: 0 additions & 10 deletions src/system/SystemEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,16 +56,6 @@ typedef CHIP_SYSTEM_CONFIG_EVENT_OBJECT_TYPE Event;

#if CHIP_SYSTEM_CONFIG_USE_LWIP

/**
* The Inet layer event type definitions.
*
*/
enum
{
kEvent_ReleaseObj = _CHIP_SYSTEM_CONFIG_LWIP_EVENT(0), /**< The event for the drop of a System::Layer object */
kEvent_ScheduleWork = _CHIP_SYSTEM_CONFIG_LWIP_EVENT(1), /**< The event for scheduling work on the System Layer's thread. */
};

#endif // CHIP_SYSTEM_CONFIG_USE_LWIP

} // namespace System
Expand Down
36 changes: 36 additions & 0 deletions src/system/SystemLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@
namespace chip {
namespace System {

struct LambdaBridge
{
void (*LambdaProxy)(const void * context);
alignas(CHIP_CONFIG_LAMBDA_EVENT_ALIGN) char LambdaBody[CHIP_CONFIG_LAMBDA_EVENT_SIZE];
};

class Layer;
using TimerCompleteCallback = void (*)(Layer * aLayer, void * appState);

Expand Down Expand Up @@ -195,6 +201,36 @@ class LayerLwIP : public Layer
*/
virtual CHIP_ERROR PostEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument) = 0;

/**
* This posts an event / message of the specified type with the provided argument to this instance's platform-specific event
* queue.
*
* @param[in] event A object encapsulate the context of a lambda
*
* @retval CHIP_NO_ERROR On success.
* @retval CHIP_ERROR_INCORRECT_STATE If the state of the Layer object is incorrect.
* @retval CHIP_ERROR_NO_MEMORY If the event queue is already full.
* @retval other Platform-specific errors generated indicating the reason for failure.
*/
virtual CHIP_ERROR ScheduleLambdaBridge(const LambdaBridge & event) = 0;

template <typename Lambda>
CHIP_ERROR ScheduleLambda(const Lambda & lambda)
{
LambdaBridge event;

// memcpy is used to move the lambda into the event queue, so it must be trivially copyable
static_assert(std::is_trivially_copyable<Lambda>::value);
static_assert(sizeof(Lambda) <= CHIP_CONFIG_LAMBDA_EVENT_SIZE);
static_assert(alignof(Lambda) <= CHIP_CONFIG_LAMBDA_EVENT_ALIGN);

// Implicit cast a capture-less lambda into a raw function pointer.
event.LambdaProxy = [](const void * body) { (*static_cast<const Lambda *>(body))(); };
memcpy(event.LambdaBody, &lambda, sizeof(Lambda));

return ScheduleLambdaBridge(event);
}

protected:
// Provide access to private members of EventHandlerDelegate.
struct LwIPEventHandlerDelegate : public EventHandlerDelegate
Expand Down
48 changes: 14 additions & 34 deletions src/system/SystemLayerImplLwIP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,14 @@
namespace chip {
namespace System {

LayerLwIP::EventHandlerDelegate LayerImplLwIP::sSystemEventHandlerDelegate;

LayerImplLwIP::LayerImplLwIP() : mHandlingTimerComplete(false), mEventDelegateList(nullptr)
{
if (!sSystemEventHandlerDelegate.IsInitialized())
sSystemEventHandlerDelegate.Init(HandleSystemLayerEvent);
}
LayerImplLwIP::LayerImplLwIP() : mHandlingTimerComplete(false), mEventDelegateList(nullptr) {}

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

RegisterLwIPErrorFormatter();

AddEventHandlerDelegate(sSystemEventHandlerDelegate);
ReturnErrorOnFailure(mTimerList.Init());

VerifyOrReturnError(mLayerState.Init(), CHIP_ERROR_INCORRECT_STATE);
Expand Down Expand Up @@ -100,7 +93,7 @@ CHIP_ERROR LayerImplLwIP::ScheduleWork(TimerCompleteCallback onComplete, void *
Timer * timer = Timer::New(*this, 0, onComplete, appState);
VerifyOrReturnError(timer != nullptr, CHIP_ERROR_NO_MEMORY);

return PostEvent(*timer, chip::System::kEvent_ScheduleWork, 0);
return ScheduleLambda([timer] { timer->HandleComplete(); });
}

bool LayerLwIP::EventHandlerDelegate::IsInitialized() const
Expand All @@ -120,31 +113,6 @@ void LayerLwIP::EventHandlerDelegate::Prepend(const LayerLwIP::EventHandlerDeleg
aDelegateList = this;
}

/**
* This is the dispatch handler for system layer events.
*
* @param[in,out] aTarget A pointer to the CHIP System Layer object making the post request.
* @param[in] aEventType The type of event to post.
* @param[in,out] aArgument The argument associated with the event to post.
*/
CHIP_ERROR LayerImplLwIP::HandleSystemLayerEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument)
{
// Dispatch logic specific to the event type
switch (aEventType)
{
case kEvent_ReleaseObj:
aTarget.Release();
return CHIP_NO_ERROR;

case kEvent_ScheduleWork:
static_cast<Timer &>(aTarget).HandleComplete();
return CHIP_NO_ERROR;

default:
return CHIP_ERROR_UNEXPECTED_EVENT;
}
}

CHIP_ERROR LayerImplLwIP::AddEventHandlerDelegate(EventHandlerDelegate & aDelegate)
{
LwIPEventHandlerDelegate & lDelegate = static_cast<LwIPEventHandlerDelegate &>(aDelegate);
Expand All @@ -153,6 +121,18 @@ CHIP_ERROR LayerImplLwIP::AddEventHandlerDelegate(EventHandlerDelegate & aDelega
return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplLwIP::ScheduleLambdaBridge(const LambdaBridge & bridge)
{
VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);

CHIP_ERROR lReturn = PlatformEventing::ScheduleLambdaBridge(*this, bridge);
if (lReturn != CHIP_NO_ERROR)
{
ChipLogError(chipSystemLayer, "Failed to queue CHIP System Layer lambda event: %s", ErrorStr(lReturn));
}
return lReturn;
}

CHIP_ERROR LayerImplLwIP::PostEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument)
{
VerifyOrReturnError(IsInitialized(), CHIP_ERROR_INCORRECT_STATE);
Expand Down
5 changes: 1 addition & 4 deletions src/system/SystemLayerImplLwIP.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class LayerImplLwIP : public LayerLwIP

// LayerLwIP overrides.
CHIP_ERROR AddEventHandlerDelegate(EventHandlerDelegate & aDelegate);
CHIP_ERROR ScheduleLambdaBridge(const LambdaBridge & bridge) override;
CHIP_ERROR PostEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument);

public:
Expand All @@ -55,13 +56,9 @@ class LayerImplLwIP : public LayerLwIP
private:
friend class PlatformEventing;

static CHIP_ERROR HandleSystemLayerEvent(Object & aTarget, EventType aEventType, uintptr_t aArgument);

CHIP_ERROR DispatchEvent(Event aEvent);
CHIP_ERROR StartPlatformTimer(uint32_t aDelayMilliseconds);

static EventHandlerDelegate sSystemEventHandlerDelegate;

Timer::MutexedList mTimerList;
bool mHandlingTimerComplete; // true while handling any timer completion
const EventHandlerDelegate * mEventDelegateList;
Expand Down
2 changes: 1 addition & 1 deletion src/system/SystemObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ void Object::DeferredRelease(LayerLwIP * aSystemLayer, Object::ReleaseDeferralEr
{
VerifyOrReturn(aSystemLayer != nullptr, ChipLogError(chipSystemLayer, "aSystemLayer is nullptr"));

CHIP_ERROR lError = aSystemLayer->PostEvent(*this, chip::System::kEvent_ReleaseObj, 0);
CHIP_ERROR lError = aSystemLayer->ScheduleLambda([this] { this->Release(); });

if (lError != CHIP_NO_ERROR)
{
Expand Down