Skip to content

Commit e008b66

Browse files
Mutext handling (#90)
* 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]>
1 parent 5a9e6fe commit e008b66

File tree

3 files changed

+46
-7
lines changed

3 files changed

+46
-7
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* !! 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.
44
* !! Major breaking change !! Increased the compiler version required to compile the SDK. It's increased from version C++11 to C++14.
55
* 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.
6+
* When making network requests, the SDK will now unlock it's mutex.
67
* Fixed a bug that caused an exception on windows when encoding data that contains special characters.
78

89
22.02.0

include/countly.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,7 @@
1212
#include <string>
1313
#include <thread>
1414

15-
#ifndef COUNTLY_USE_SQLITE
1615
#include <deque>
17-
#endif
1816

1917
#include "nlohmann/json.hpp"
2018

@@ -203,6 +201,9 @@ class Countly : public cly::CountlyDelegates {
203201
* @return a vector object containing events.
204202
*/
205203
const std::vector<std::string> debugReturnStateOfEQ() {
204+
#ifdef COUNTLY_USE_SQLITE
205+
return {};
206+
#endif
206207
std::vector<std::string> v(event_queue.begin(), event_queue.end());
207208
return v;
208209
}
@@ -215,7 +216,7 @@ class Countly : public cly::CountlyDelegates {
215216
/**
216217
* Helper methods to fetch remote config from the server.
217218
*/
218-
#pragma region Remote_Config_Helper_Methods
219+
#pragma region Remote_Config_Helper_Methods
219220
void _fetchRemoteConfig(std::map<std::string, std::string> &data);
220221
void _updateRemoteConfigWithSpecificValues(std::map<std::string, std::string> &data);
221222
#pragma endregion Remote_Config_Helper_Methods
@@ -258,6 +259,8 @@ class Countly : public cly::CountlyDelegates {
258259
std::shared_ptr<cly::LoggerModule> logger;
259260

260261
std::mutex mutex;
262+
263+
bool is_queue_being_processed = false;
261264
bool enable_automatic_session = false;
262265
bool stop_thread = false;
263266
bool running = false;

src/countly.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -787,21 +787,56 @@ std::string Countly::calculateChecksum(const std::string &salt, const std::strin
787787
#endif
788788
}
789789

790+
/**
791+
* SDK central execution call for processing requests in the request queue.
792+
* Only one sender is active at a time. Requests are processed in order.
793+
*/
790794
void Countly::processRequestQueue() {
795+
mutex.lock();
796+
//making sure that no other thread is processing the queue
797+
if (is_queue_being_processed) {
798+
mutex.unlock();
799+
return;
800+
}
801+
802+
//if this is the only thread, mark that processing is happening
803+
is_queue_being_processed = true;
804+
mutex.unlock();
791805

792-
while (!request_queue.empty()) {
806+
while (true) {
793807
mutex.lock();
808+
if (request_queue.empty()) {
809+
//stop sending requests once the queue is empty
810+
mutex.unlock();
811+
break;
812+
}
813+
794814
std::string data = request_queue.front();
815+
mutex.unlock();
816+
795817
HTTPResponse response = sendHTTP("/i", data);
796818

819+
mutex.lock();
797820
if (!response.success) {
821+
//if the request was not a success, abort sending and try again in the future
798822
mutex.unlock();
799823
break;
800824
}
801825

802-
request_queue.pop_front();
826+
827+
if (request_queue.front() == data) {
828+
// we pop the front only if it is still the same request
829+
// the queue might have changed while we were sending the request
830+
request_queue.pop_front();
831+
}
832+
803833
mutex.unlock();
804834
}
835+
836+
mutex.lock();
837+
//mark that no thread is processing the request queue
838+
is_queue_being_processed = false;
839+
mutex.unlock();
805840
}
806841

807842
void Countly::addToRequestQueue(std::string &data) {
@@ -1029,8 +1064,8 @@ void Countly::enableRemoteConfig() {
10291064
}
10301065

10311066
void Countly::_fetchRemoteConfig(std::map<std::string, std::string> &data) {
1032-
mutex.lock();
10331067
HTTPResponse response = sendHTTP("/o/sdk", serializeForm(data));
1068+
mutex.lock();
10341069
if (response.success) {
10351070
remote_config = response.data;
10361071
}
@@ -1061,8 +1096,8 @@ nlohmann::json Countly::getRemoteConfigValue(const std::string &key) {
10611096
}
10621097

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

0 commit comments

Comments
 (0)