Skip to content

Commit

Permalink
Mutext handling (#90)
Browse files Browse the repository at this point in the history
* namespace added on countly classes

* - queue processing flag added
- mutext unlock while attempting http requests

* compilation issue fixed!

* code reverted

* change log entry added
code formating

* adding comments

Co-authored-by: ArtursK <[email protected]>
  • Loading branch information
ZahidZafar and ArtursKadikis authored Sep 9, 2022
1 parent 5a9e6fe commit e008b66
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 7 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* !! Major breaking change !! We are extracting the 'Event' class out of the 'Countly' class which will change how that class can be referenced. 'Countly::Event' will not work, you will have to use 'cly::Event' instead.
* !! Major breaking change !! Increased the compiler version required to compile the SDK. It's increased from version C++11 to C++14.
* Making network requests has been reworked. They will now be sent on a separate thread. Requests will also be added in an internal queue and will be sent one at a time.
* When making network requests, the SDK will now unlock it's mutex.
* Fixed a bug that caused an exception on windows when encoding data that contains special characters.

22.02.0
Expand Down
9 changes: 6 additions & 3 deletions include/countly.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@
#include <string>
#include <thread>

#ifndef COUNTLY_USE_SQLITE
#include <deque>
#endif

#include "nlohmann/json.hpp"

Expand Down Expand Up @@ -203,6 +201,9 @@ class Countly : public cly::CountlyDelegates {
* @return a vector object containing events.
*/
const std::vector<std::string> debugReturnStateOfEQ() {
#ifdef COUNTLY_USE_SQLITE
return {};
#endif
std::vector<std::string> v(event_queue.begin(), event_queue.end());
return v;
}
Expand All @@ -215,7 +216,7 @@ class Countly : public cly::CountlyDelegates {
/**
* Helper methods to fetch remote config from the server.
*/
#pragma region Remote_Config_Helper_Methods
#pragma region Remote_Config_Helper_Methods
void _fetchRemoteConfig(std::map<std::string, std::string> &data);
void _updateRemoteConfigWithSpecificValues(std::map<std::string, std::string> &data);
#pragma endregion Remote_Config_Helper_Methods
Expand Down Expand Up @@ -258,6 +259,8 @@ class Countly : public cly::CountlyDelegates {
std::shared_ptr<cly::LoggerModule> logger;

std::mutex mutex;

bool is_queue_being_processed = false;
bool enable_automatic_session = false;
bool stop_thread = false;
bool running = false;
Expand Down
43 changes: 39 additions & 4 deletions src/countly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -787,21 +787,56 @@ std::string Countly::calculateChecksum(const std::string &salt, const std::strin
#endif
}

/**
* SDK central execution call for processing requests in the request queue.
* Only one sender is active at a time. Requests are processed in order.
*/
void Countly::processRequestQueue() {
mutex.lock();
//making sure that no other thread is processing the queue
if (is_queue_being_processed) {
mutex.unlock();
return;
}

//if this is the only thread, mark that processing is happening
is_queue_being_processed = true;
mutex.unlock();

while (!request_queue.empty()) {
while (true) {
mutex.lock();
if (request_queue.empty()) {
//stop sending requests once the queue is empty
mutex.unlock();
break;
}

std::string data = request_queue.front();
mutex.unlock();

HTTPResponse response = sendHTTP("/i", data);

mutex.lock();
if (!response.success) {
//if the request was not a success, abort sending and try again in the future
mutex.unlock();
break;
}

request_queue.pop_front();

if (request_queue.front() == data) {
// we pop the front only if it is still the same request
// the queue might have changed while we were sending the request
request_queue.pop_front();
}

mutex.unlock();
}

mutex.lock();
//mark that no thread is processing the request queue
is_queue_being_processed = false;
mutex.unlock();
}

void Countly::addToRequestQueue(std::string &data) {
Expand Down Expand Up @@ -1029,8 +1064,8 @@ void Countly::enableRemoteConfig() {
}

void Countly::_fetchRemoteConfig(std::map<std::string, std::string> &data) {
mutex.lock();
HTTPResponse response = sendHTTP("/o/sdk", serializeForm(data));
mutex.lock();
if (response.success) {
remote_config = response.data;
}
Expand Down Expand Up @@ -1061,8 +1096,8 @@ nlohmann::json Countly::getRemoteConfigValue(const std::string &key) {
}

void Countly::_updateRemoteConfigWithSpecificValues(std::map<std::string, std::string> &data) {
mutex.lock();
HTTPResponse response = sendHTTP("/o/sdk", serializeForm(data));
mutex.lock();
if (response.success) {
for (auto it = response.data.begin(); it != response.data.end(); ++it) {
remote_config[it.key()] = it.value();
Expand Down

0 comments on commit e008b66

Please sign in to comment.