Skip to content

Commit

Permalink
Pull up LayerLwIP::ScheduleLambda to SystemLayer
Browse files Browse the repository at this point in the history
  • Loading branch information
kghost committed Oct 29, 2021
1 parent 1e27d92 commit c8586ec
Show file tree
Hide file tree
Showing 10 changed files with 96 additions and 39 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ void GenericPlatformManagerImpl<ImplClass>::_DispatchEvent(const ChipDeviceEvent
break;

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

case DeviceEventType::kCallWorkFunct:
Expand Down
4 changes: 2 additions & 2 deletions src/platform/LwIPEventSupport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ namespace System {

using namespace ::chip::DeviceLayer;

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

return PlatformMgr().PostEvent(&event);
}
Expand Down
2 changes: 1 addition & 1 deletion src/system/LwIPEventSupport.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class Object;
class PlatformEventing
{
public:
static CHIP_ERROR ScheduleLambdaBridge(System::Layer & aLayer, const LambdaBridge & bridge);
static CHIP_ERROR ScheduleLambdaBridge(System::Layer & aLayer, LambdaBridge && bridge);
static CHIP_ERROR PostEvent(System::Layer & aLayer, Object & aTarget, EventType aType, uintptr_t aArgument);
static CHIP_ERROR StartTimer(System::Layer & aLayer, System::Clock::Timeout aTimeout);
};
Expand Down
68 changes: 36 additions & 32 deletions src/system/SystemLayer.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@

#pragma once

#include <type_traits>

// Include configuration headers
#include <system/SystemConfig.h>

Expand Down Expand Up @@ -52,8 +54,8 @@ namespace System {

struct LambdaBridge
{
void (*LambdaProxy)(const void * context);
alignas(CHIP_CONFIG_LAMBDA_EVENT_ALIGN) char LambdaBody[CHIP_CONFIG_LAMBDA_EVENT_SIZE];
void (*LambdaProxy)(const std::aligned_storage<CHIP_CONFIG_LAMBDA_EVENT_SIZE, CHIP_CONFIG_LAMBDA_EVENT_ALIGN> & body);
std::aligned_storage<CHIP_CONFIG_LAMBDA_EVENT_SIZE, CHIP_CONFIG_LAMBDA_EVENT_ALIGN> LambdaBody;
};

class Layer;
Expand Down Expand Up @@ -148,6 +150,38 @@ class DLL_EXPORT Layer
*/
virtual CHIP_ERROR ScheduleWork(TimerCompleteCallback aComplete, void * aAppState) = 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(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, "lambda must be trivially copyable");
static_assert(sizeof(Lambda) <= CHIP_CONFIG_LAMBDA_EVENT_SIZE, "lambda too large");
static_assert(CHIP_CONFIG_LAMBDA_EVENT_ALIGN % alignof(Lambda) == 0, "lambda align too large");

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

return ScheduleLambdaBridge(std::move(event));
}

private:
// Copy and assignment NOT DEFINED
Layer(const Layer &) = delete;
Expand Down Expand Up @@ -202,36 +236,6 @@ 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
22 changes: 22 additions & 0 deletions src/system/SystemLayerImplLibevent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,28 @@ CHIP_ERROR LayerImplLibevent::ScheduleWork(TimerCompleteCallback onComplete, voi
return StartTimer(Clock::Zero, onComplete, appState);
}

CHIP_ERROR LayerImplLibevent::ScheduleLambdaBridge(LambdaBridge && event)
{
mScheduledLambdas.emplace_back(std::move(event));
CHIP_ERROR err = ScheduleWork(RunScheduledLambda, this);
if (err != CHIP_NO_ERROR)
{
mScheduledLambdas.pop_back();
}
return err;
}

void LayerImplLibevent::RunScheduledLambda(Layer * aLayer, void * appState)
{
LayerImplLibevent * me = static_cast<LayerImplLibevent *>(appState);
while (!me->mScheduledLambdas.empty())
{
auto & event = me->mScheduledLambdas.front();
event.LambdaProxy(event.LambdaBody);
me->mScheduledLambdas.pop_front();
}
}

// static
void LayerImplLibevent::TimerCallbackHandler(evutil_socket_t fd, short eventFlags, void * data)
{
Expand Down
4 changes: 4 additions & 0 deletions src/system/SystemLayerImplLibevent.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class LayerImplLibevent : public LayerSocketsLoop
CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override;
void CancelTimer(TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ScheduleLambdaBridge(LambdaBridge && event) override;

// LayerSocket overrides.
CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) override;
Expand Down Expand Up @@ -109,6 +110,8 @@ class LayerImplLibevent : public LayerSocketsLoop
CHIP_ERROR UpdateWatch(SocketWatch * watch, short eventFlags);
static void SocketCallbackHandler(evutil_socket_t fd, short eventFlags, void * data);

static void RunScheduledLambda(Layer * aLayer, void * appState);

event_base * mEventBase; ///< libevent shared state.

std::list<std::unique_ptr<LibeventTimer>> mTimers;
Expand All @@ -117,6 +120,7 @@ class LayerImplLibevent : public LayerSocketsLoop

std::list<std::unique_ptr<SocketWatch>> mSocketWatches;
std::list<SocketWatch *> mActiveSocketWatches;
std::list<LambdaBridge> mScheduledLambdas;

ObjectLifeCycle mLayerState;
WakeEvent mWakeEvent;
Expand Down
4 changes: 2 additions & 2 deletions src/system/SystemLayerImplLwIP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,11 +122,11 @@ CHIP_ERROR LayerImplLwIP::AddEventHandlerDelegate(EventHandlerDelegate & aDelega
return CHIP_NO_ERROR;
}

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

CHIP_ERROR lReturn = PlatformEventing::ScheduleLambdaBridge(*this, bridge);
CHIP_ERROR lReturn = PlatformEventing::ScheduleLambdaBridge(*this, std::move(bridge));
if (lReturn != CHIP_NO_ERROR)
{
ChipLogError(chipSystemLayer, "Failed to queue CHIP System Layer lambda event: %s", ErrorStr(lReturn));
Expand Down
2 changes: 1 addition & 1 deletion src/system/SystemLayerImplLwIP.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class LayerImplLwIP : public LayerLwIP

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

public:
Expand Down
22 changes: 22 additions & 0 deletions src/system/SystemLayerImplSelect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,28 @@ CHIP_ERROR LayerImplSelect::ScheduleWork(TimerCompleteCallback onComplete, void
return CHIP_NO_ERROR;
}

CHIP_ERROR LayerImplSelect::ScheduleLambdaBridge(LambdaBridge && event)
{
mScheduledLambdas.emplace_back(std::move(event));
CHIP_ERROR err = ScheduleWork(RunScheduledLambda, this);
if (err != CHIP_NO_ERROR)
{
mScheduledLambdas.pop_back();
}
return err;
}

void LayerImplSelect::RunScheduledLambda(Layer * aLayer, void * appState)
{
LayerImplSelect * me = static_cast<LayerImplSelect *>(appState);
while (!me->mScheduledLambdas.empty())
{
auto & event = me->mScheduledLambdas.front();
event.LambdaProxy(event.LambdaBody);
me->mScheduledLambdas.pop_front();
}
}

CHIP_ERROR LayerImplSelect::StartWatchingSocket(int fd, SocketWatchToken * tokenOut)
{
// Find a free slot.
Expand Down
5 changes: 5 additions & 0 deletions src/system/SystemLayerImplSelect.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <atomic>
#include <pthread.h>
#endif // CHIP_SYSTEM_CONFIG_POSIX_LOCKING
#include <list>

#include <lib/support/ObjectLifeCycle.h>
#include <system/SystemLayer.h>
Expand All @@ -49,6 +50,7 @@ class LayerImplSelect : public LayerSocketsLoop
CHIP_ERROR StartTimer(Clock::Timeout delay, TimerCompleteCallback onComplete, void * appState) override;
void CancelTimer(TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ScheduleWork(TimerCompleteCallback onComplete, void * appState) override;
CHIP_ERROR ScheduleLambdaBridge(LambdaBridge && event) override;

// LayerSocket overrides.
CHIP_ERROR StartWatchingSocket(int fd, SocketWatchToken * tokenOut) override;
Expand All @@ -75,6 +77,8 @@ class LayerImplSelect : public LayerSocketsLoop
#endif // CHIP_SYSTEM_CONFIG_USE_DISPATCH

protected:
static void RunScheduledLambda(Layer * aLayer, void * appState);

static SocketEvents SocketEventsFromFDs(int socket, const fd_set & readfds, const fd_set & writefds, const fd_set & exceptfds);

static constexpr int kSocketWatchMax = (INET_CONFIG_ENABLE_TCP_ENDPOINT ? INET_CONFIG_NUM_TCP_ENDPOINTS : 0) +
Expand All @@ -89,6 +93,7 @@ class LayerImplSelect : public LayerSocketsLoop
intptr_t mCallbackData;
};
SocketWatch mSocketWatchPool[kSocketWatchMax];
std::list<LambdaBridge> mScheduledLambdas;

Timer::MutexedList mTimerList;
timeval mNextTimeout;
Expand Down

0 comments on commit c8586ec

Please sign in to comment.