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

Refactor: Alternative implementations for dependencies from Thunder #220

Open
wants to merge 3 commits into
base: next
Choose a base branch
from
Open
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: 1 addition & 2 deletions languages/cpp/src/shared/src/Async/Async.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace FireboltSDK {

void Async::Clear()
{
_adminLock.Lock();
std::lock_guard<std::mutex> guard(_adminLock);
MethodMap::iterator index = _methodMap.begin();
while (index != _methodMap.end()) {
CallbackMap::iterator callbackIndex = index->second.begin();
Expand All @@ -72,7 +72,6 @@ namespace FireboltSDK {
}
index = _methodMap.erase(index);
}
_adminLock.Unlock();
}
}

88 changes: 51 additions & 37 deletions languages/cpp/src/shared/src/Async/Async.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

#pragma once

#include <mutex>
#include "Module.h"

namespace FireboltSDK {
Expand Down Expand Up @@ -86,47 +87,53 @@ namespace FireboltSDK {

public:
template <typename RESPONSE, typename PARAMETERS, typename CALLBACK>
Firebolt::Error Invoke(const string& method, const PARAMETERS& parameters, const CALLBACK& callback, void* usercb, uint32_t waitTime = DefaultWaitTime)
Firebolt::Error Invoke(const string &method, const PARAMETERS &parameters, const CALLBACK &callback, void *usercb, uint32_t waitTime = DefaultWaitTime)
{
Firebolt::Error status = Firebolt::Error::None;
if (_transport != nullptr) {
Transport<WPEFramework::Core::JSON::IElement>* transport = _transport;
std::function<void(void* usercb, void* response, Firebolt::Error status)> actualCallback = callback;
DispatchFunction lambda = [actualCallback, transport, method, parameters, waitTime](Async& parent, void* usercb) -> Firebolt::Error {
if (_transport != nullptr)
{
Transport<WPEFramework::Core::JSON::IElement> *transport = _transport;
std::function<void(void *usercb, void *response, Firebolt::Error status)> actualCallback = callback;
DispatchFunction lambda = [actualCallback, transport, method, parameters, waitTime](Async &parent, void *usercb) -> Firebolt::Error
{
RESPONSE response;
uint32_t id = DefaultId;
Firebolt::Error status = transport->InvokeAsync(method, parameters, id);
if (status == Firebolt::Error::None && parent.IsActive(method, usercb) == true) {
if (status == Firebolt::Error::None && parent.IsActive(method, usercb) == true)
{
parent.UpdateEntry(method, usercb, id);
status = transport->WaitForResponse(id, response, waitTime);
if (status == Firebolt::Error::None && parent.IsActive(method, usercb) == true) {
WPEFramework::Core::ProxyType<RESPONSE>* jsonResponse = new WPEFramework::Core::ProxyType<RESPONSE>();
if (status == Firebolt::Error::None && parent.IsActive(method, usercb) == true)
{
WPEFramework::Core::ProxyType<RESPONSE> *jsonResponse = new WPEFramework::Core::ProxyType<RESPONSE>();
*jsonResponse = WPEFramework::Core::ProxyType<RESPONSE>::Create();
(*jsonResponse)->FromString(response);
actualCallback(usercb, jsonResponse, status);
parent.RemoveEntry(method, usercb);
}

}
return (status);
};

_adminLock.Lock();
std::lock_guard<std::mutex> guard(_adminLock);
WPEFramework::Core::ProxyType<WPEFramework::Core::IDispatch> job = WPEFramework::Core::ProxyType<WPEFramework::Core::IDispatch>(WPEFramework::Core::ProxyType<Async::Job>::Create(*this, method, lambda, usercb));
CallbackData callbackData = {lambda, job, DefaultId};
MethodMap::iterator index = _methodMap.find(method);
if (index != _methodMap.end()) {
if (index != _methodMap.end())
{
CallbackMap::iterator callbackIndex = index->second.find(usercb);
if (callbackIndex == index->second.end()) {
if (callbackIndex == index->second.end())
{
index->second.emplace(std::piecewise_construct, std::forward_as_tuple(usercb), std::forward_as_tuple(callbackData));
}
} else {
}
else
{

CallbackMap callbackMap;
callbackMap.emplace(std::piecewise_construct, std::forward_as_tuple(usercb), std::forward_as_tuple(callbackData));
_methodMap.emplace(std::piecewise_construct, std::forward_as_tuple(method), std::forward_as_tuple(callbackMap));
}
_adminLock.Unlock();

WPEFramework::Core::IWorkerPool::Instance().Submit(job);
}
Expand All @@ -140,50 +147,57 @@ namespace FireboltSDK {
return (Firebolt::Error::None);
}

void UpdateEntry(const string& method, void* usercb, uint32_t id)
void UpdateEntry(const string &method, void *usercb, uint32_t id)
{
_adminLock.Lock();
std::lock_guard<std::mutex> guard(_adminLock);
MethodMap::iterator index = _methodMap.find(method);
if (index != _methodMap.end()) {
if (index != _methodMap.end())
{
CallbackMap::iterator callbackIndex = index->second.find(usercb);
if (callbackIndex != index->second.end()) {
if (callbackIndex != index->second.end())
{
callbackIndex->second.id = id;
}
}
_adminLock.Unlock();
}

void RemoveEntry(const string& method, void* usercb)
void RemoveEntry(const string &method, void *usercb)
{
_adminLock.Lock();
std::lock_guard<std::mutex> guard(_adminLock);
MethodMap::iterator index = _methodMap.find(method);
if (index != _methodMap.end()) {
if (index != _methodMap.end())
{
CallbackMap::iterator callbackIndex = index->second.find(usercb);
if (callbackIndex != index->second.end()) {
if (IsValidJob(callbackIndex->second)) {
if (callbackIndex != index->second.end())
{
if (IsValidJob(callbackIndex->second))
{
WPEFramework::Core::IWorkerPool::Instance().Revoke(callbackIndex->second.job);
}
index->second.erase(callbackIndex);
if (index->second.size() == 0) {
if (index->second.size() == 0)
{
_methodMap.erase(index);
}
}
}
_adminLock.Unlock();
}

bool IsActive(const string& method, void* usercb)
bool IsActive(const string &method, void *usercb)
{
bool valid = false;
_adminLock.Lock();
MethodMap::iterator index = _methodMap.find(method);
if (index != _methodMap.end()) {
CallbackMap::iterator callbackIndex = index->second.find(usercb);
if (callbackIndex != index->second.end()) {
valid = true;
{
std::lock_guard<std::mutex> guard(_adminLock);
MethodMap::iterator index = _methodMap.find(method);
if (index != _methodMap.end())
{
CallbackMap::iterator callbackIndex = index->second.find(usercb);
if (callbackIndex != index->second.end())
{
valid = true;
}
}
}
_adminLock.Unlock();
return valid;
}

Expand All @@ -195,9 +209,9 @@ namespace FireboltSDK {

private:
MethodMap _methodMap;
WPEFramework::Core::CriticalSection _adminLock;
Transport<WPEFramework::Core::JSON::IElement>* _transport;
std::mutex _adminLock;
Transport<WPEFramework::Core::JSON::IElement> *_transport;

static Async* _singleton;
static Async *_singleton;
};
}
79 changes: 48 additions & 31 deletions languages/cpp/src/shared/src/Event/Event.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* SPDX-License-Identifier: Apache-2.0
*/

#include <mutex>
#include "Transport/Transport.h"
#include "Event.h"

Expand Down Expand Up @@ -100,35 +101,43 @@ namespace FireboltSDK {
std::vector<EventMap*> eventMaps = {&_internalEventMap, &_externalEventMap};

// Combine both _internalEventMap and _externalEventMap into a single loop
for (auto eventMap : eventMaps) {
_adminLock.Lock();
for (auto eventMap : eventMaps)
{
std::lock_guard<std::mutex> guard(_adminLock);
EventMap::iterator eventIndex = eventMap->find(eventName);
if (eventIndex != eventMap->end()) {
CallbackMap& callbacks = eventIndex->second;
for (CallbackMap::iterator callbackIndex = callbacks.begin(); callbackIndex != callbacks.end();) {
if (eventIndex != eventMap->end())
{
CallbackMap &callbacks = eventIndex->second;
for (CallbackMap::iterator callbackIndex = callbacks.begin(); callbackIndex != callbacks.end();)
{
State state;
if (callbackIndex->second.state != State::REVOKED) {
if (callbackIndex->second.state != State::REVOKED)
{
callbackIndex->second.state = State::EXECUTING;
}
state = callbackIndex->second.state;
_adminLock.Unlock();
if (state == State::EXECUTING) {
_adminLock.unlock();
if (state == State::EXECUTING)
{
callbackIndex->second.lambda(callbackIndex->first, callbackIndex->second.userdata, response);
}
_adminLock.Lock();
if (callbackIndex->second.state == State::REVOKED) {
_adminLock.lock();
if (callbackIndex->second.state == State::REVOKED)
{
callbackIndex = callbacks.erase(callbackIndex);
if (callbacks.empty()) {
if (callbacks.empty())
{
eventMap->erase(eventIndex); // Erase from the correct eventMap
break; // No need to continue iterating if map is empty
break; // No need to continue iterating if map is empty
}
} else {
}
else
{
callbackIndex->second.state = State::IDLE;
++callbackIndex;
}
}
}
_adminLock.Unlock();
}
return Firebolt::Error::None;
}
Expand All @@ -141,34 +150,41 @@ namespace FireboltSDK {
// Combine both _internalEventMap and _externalEventMap into a single loop
std::vector<EventMap*> eventMaps = {&_internalEventMap, &_externalEventMap};

for (auto eventMap : eventMaps) {
_adminLock.Lock(); // Lock inside the loop
for (auto eventMap : eventMaps)
{
std::lock_guard<std::mutex> guard(_adminLock);

// Find the eventIndex for eventName in the current eventMap
EventMap::iterator eventIndex = eventMap->find(eventName);
if (eventIndex != eventMap->end()) {
if (eventIndex != eventMap->end())
{
// Find the callbackIndex for usercb in the current CallbackMap
CallbackMap::iterator callbackIndex = eventIndex->second.find(usercb);
if (callbackIndex != eventIndex->second.end()) {
if (callbackIndex != eventIndex->second.end())
{
// Check if callback is not executing, then erase it
if (callbackIndex->second.state != State::EXECUTING) {
if (callbackIndex->second.state != State::EXECUTING)
{
eventIndex->second.erase(callbackIndex);
} else {
}
else
{
// Mark the callback as revoked
callbackIndex->second.state = State::REVOKED;
}

// Check if the CallbackMap is empty after potential erasure
if (eventIndex->second.empty()) {
if (eventIndex->second.empty())
{
eventMap->erase(eventIndex);
} else {
}
else
{
// Set status to General error if CallbackMap is not empty
status = Firebolt::Error::General;
}
}
}

_adminLock.Unlock(); // Unlock after processing each eventMap
}

return status;
Expand All @@ -179,20 +195,21 @@ namespace FireboltSDK {
// Clear both _internalEventMap and _externalEventMap
std::vector<EventMap*> eventMaps = {&_internalEventMap, &_externalEventMap};

for (auto eventMap : eventMaps) {
_adminLock.Lock(); // Lock before clearing
for (auto eventMap : eventMaps)
{
std::lock_guard<std::mutex> guard(_adminLock);

EventMap::iterator eventIndex = eventMap->begin();
while (eventIndex != eventMap->end()) {
while (eventIndex != eventMap->end())
{
CallbackMap::iterator callbackIndex = eventIndex->second.begin();
while (callbackIndex != eventIndex->second.end()) {
while (callbackIndex != eventIndex->second.end())
{
callbackIndex = eventIndex->second.erase(callbackIndex);
}
eventIndex = eventMap->erase(eventIndex);
}

_adminLock.Unlock(); // Unlock after clearing
}
}

}
}
Loading
Loading