Skip to content

Commit

Permalink
Tizen Platform: Using LambdaBridge to safely invoke functions in GLib…
Browse files Browse the repository at this point in the history
… Matter context
  • Loading branch information
Alami-Amine committed Sep 26, 2024
1 parent f5ba9a5 commit 4601183
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 14 deletions.
15 changes: 5 additions & 10 deletions src/platform/Tizen/PlatformManagerImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ namespace {

struct GLibMatterContextInvokeData
{
CHIP_ERROR (*mFunc)(void *);
void * mFuncUserData;
CHIP_ERROR mFuncResult;
LambdaBridge bridge;
// Sync primitives to wait for the function to be executed
std::mutex mDoneMutex;
std::condition_variable mDoneCond;
Expand Down Expand Up @@ -144,18 +142,17 @@ void PlatformManagerImpl::_Shutdown()
mGLibMainLoop = nullptr;
}

CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData)
void PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData)
{
GLibMatterContextInvokeData invokeData{ func, userData };
GLibMatterContextInvokeData invokeData{ std::move(bridge) };

g_main_context_invoke_full(
g_main_loop_get_context(mGLibMainLoop), G_PRIORITY_HIGH_IDLE,
[](void * userData_) {
auto * data = reinterpret_cast<GLibMatterContextInvokeData *>(userData_);
VerifyOrExit(g_main_context_get_thread_default() != nullptr,
ChipLogError(DeviceLayer, "GLib thread default main context is not set");
data->mFuncResult = CHIP_ERROR_INCORRECT_STATE);
data->mFuncResult = data->mFunc(data->mFuncUserData);
ChipLogError(DeviceLayer, "GLib thread default main context is not set"););
// data->mFuncResult = CHIP_ERROR_INCORRECT_STATE);
exit:
data->mDoneMutex.lock();
data->mDone = true;
Expand All @@ -167,8 +164,6 @@ CHIP_ERROR PlatformManagerImpl::_GLibMatterContextInvokeSync(CHIP_ERROR (*func)(

std::unique_lock<std::mutex> lock(invokeData.mDoneMutex);
invokeData.mDoneCond.wait(lock, [&invokeData]() { return invokeData.mDone; });

return invokeData.mFuncResult;
}

} // namespace DeviceLayer
Expand Down
20 changes: 16 additions & 4 deletions src/platform/Tizen/PlatformManagerImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,16 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener
template <typename T>
CHIP_ERROR GLibMatterContextInvokeSync(CHIP_ERROR (*func)(T *), T * userData)
{
return _GLibMatterContextInvokeSync((CHIP_ERROR(*)(void *)) func, (void *) userData);
CHIP_ERROR LambdaErrorReturn;

// wrapping the function pointer and userData into a Lambda, to be stored and passed as a LambdaBridge
auto lambda = [func, userData](CHIP_ERROR * apErrorReturn) { *apErrorReturn = func(userData); };

LambdaBridge bridge;
bridge.Initialize(lambda, &LambdaErrorReturn);
_GLibMatterContextInvokeSync(std::move(bridge));

return LambdaErrorReturn;
}
System::Clock::Timestamp GetStartTime() { return mStartTime; }

Expand All @@ -87,10 +96,13 @@ class PlatformManagerImpl final : public PlatformManager, public Internal::Gener
/**
* @brief Invoke a function on the Matter GLib context.
*
* @note This function does not provide type safety for the user data. Please,
* use the GLibMatterContextInvokeSync() template function instead.
* @param[in] bridge a LambdaBridge object that holds the lambda to be invoked within the GLib context.
*
* @note This function moves the LambdaBridge into the GLib context for invocation.
* The LambdaBridge is created and initialised in GLibMatterContextInvokeSync().
* use the GLibMatterContextInvokeSync() template function instead of this one.
*/
CHIP_ERROR _GLibMatterContextInvokeSync(CHIP_ERROR (*func)(void *), void * userData);
void _GLibMatterContextInvokeSync(LambdaBridge && bridge);

GMainLoop * mGLibMainLoop;
GThread * mGLibMainLoopThread;
Expand Down

0 comments on commit 4601183

Please sign in to comment.