diff --git a/native/android/app/src/cpp/GlobalDBSingleton.cpp b/native/android/app/src/cpp/GlobalDBSingleton.cpp index b60cc59bd..757938989 100644 --- a/native/android/app/src/cpp/GlobalDBSingleton.cpp +++ b/native/android/app/src/cpp/GlobalDBSingleton.cpp @@ -1,53 +1,60 @@ #include #include namespace comm { GlobalDBSingleton GlobalDBSingleton::instance; GlobalDBSingleton::GlobalDBSingleton() : multithreadingEnabled(true), databaseThread(std::make_unique("database")), tasksCancelled(false) { } void GlobalDBSingleton::scheduleOrRun(const taskType task) { this->scheduleOrRunCommonImpl(task); } void GlobalDBSingleton::scheduleOrRunCancellable(const taskType task) { this->scheduleOrRunCancellableCommonImpl(task); } +void GlobalDBSingleton::scheduleOrRunCancellable( + const taskType task, + const std::shared_ptr promise, + const std::shared_ptr jsInvoker) { + this->scheduleOrRunCancellableCommonImpl(task, promise, jsInvoker); +} + void GlobalDBSingleton::enableMultithreading() { this->enableMultithreadingCommonImpl(); } void GlobalDBSingletonJNIHelper::scheduleOrRun( facebook::jni::alias_ref jThis, facebook::jni::alias_ref task) { auto globalTaskRef = facebook::jni::make_global(task); GlobalDBSingleton::instance.scheduleOrRun( [globalTaskRef = std::move(globalTaskRef)]() mutable { auto runTask = [globalTaskRef = std::move(globalTaskRef)]() mutable { globalTaskRef->run(); globalTaskRef.release(); }; facebook::jni::ThreadScope::WithClassLoader(std::move(runTask)); }); } void GlobalDBSingletonJNIHelper::enableMultithreading( facebook::jni::alias_ref jThis) { GlobalDBSingleton::instance.enableMultithreading(); } void GlobalDBSingletonJNIHelper::registerNatives() { javaClassStatic()->registerNatives({ makeNativeMethod( "scheduleOrRun", GlobalDBSingletonJNIHelper::scheduleOrRun), makeNativeMethod( "enableMultithreading", GlobalDBSingletonJNIHelper::enableMultithreading), }); } } // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h index c3a3f45b8..c30274b4d 100644 --- a/native/cpp/CommonCpp/NativeModules/CommCoreModule.h +++ b/native/cpp/CommonCpp/NativeModules/CommCoreModule.h @@ -1,78 +1,79 @@ #pragma once #include "../CryptoTools/CryptoModule.h" #include "../Tools/CommSecureStore.h" #include "../Tools/WorkerThread.h" #include "../_generated/NativeModules.h" #include "../grpc/Client.h" +#include #include #include namespace comm { namespace jsi = facebook::jsi; class CommCoreModule : public facebook::react::CommCoreModuleSchemaCxxSpecJSI { const int codeVersion{154}; std::unique_ptr cryptoThread; CommSecureStore secureStore; const std::string secureStoreAccountDataKey = "cryptoAccountDataKey"; std::unique_ptr cryptoModule; std::unique_ptr networkClient; template T runSyncOrThrowJSError(jsi::Runtime &rt, std::function task); jsi::Value getDraft(jsi::Runtime &rt, const jsi::String &key) override; jsi::Value updateDraft(jsi::Runtime &rt, const jsi::Object &draft) override; jsi::Value moveDraft( jsi::Runtime &rt, const jsi::String &oldKey, const jsi::String &newKey) override; jsi::Value getAllDrafts(jsi::Runtime &rt) override; jsi::Value removeAllDrafts(jsi::Runtime &rt) override; jsi::Value getAllMessages(jsi::Runtime &rt) override; jsi::Array getAllMessagesSync(jsi::Runtime &rt) override; jsi::Value processMessageStoreOperations( jsi::Runtime &rt, const jsi::Array &operations) override; void processMessageStoreOperationsSync( jsi::Runtime &rt, const jsi::Array &operations) override; jsi::Value getAllThreads(jsi::Runtime &rt) override; jsi::Array getAllThreadsSync(jsi::Runtime &rt) override; jsi::Value processThreadStoreOperations( jsi::Runtime &rt, const jsi::Array &operations) override; void processThreadStoreOperationsSync( jsi::Runtime &rt, const jsi::Array &operations) override; jsi::Value initializeCryptoAccount(jsi::Runtime &rt, const jsi::String &userId) override; jsi::Value getUserPublicKey(jsi::Runtime &rt) override; jsi::Value getUserOneTimeKeys(jsi::Runtime &rt) override; jsi::Object openSocket(jsi::Runtime &rt, const jsi::String &endpoint) override; double getCodeVersion(jsi::Runtime &rt) override; jsi::Value setNotifyToken(jsi::Runtime &rt, const jsi::String &token) override; jsi::Value clearNotifyToken(jsi::Runtime &rt) override; jsi::Value setCurrentUserID(jsi::Runtime &rt, const jsi::String &userID) override; jsi::Value getCurrentUserID(jsi::Runtime &rt) override; jsi::Value setDeviceID(jsi::Runtime &rt, const jsi::String &deviceType) override; jsi::Value getDeviceID(jsi::Runtime &rt) override; jsi::Value clearSensitiveData(jsi::Runtime &rt) override; public: CommCoreModule(std::shared_ptr jsInvoker); void initializeNetworkModule( const std::string &userId, const std::string &deviceToken, const std::string &hostname = ""); }; } // namespace comm diff --git a/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h index b68a83ce2..f33d482b2 100644 --- a/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h +++ b/native/cpp/CommonCpp/NativeModules/InternalModules/GlobalDBSingleton.h @@ -1,55 +1,80 @@ #pragma once #include "../../Tools/WorkerThread.h" +#include #include namespace comm { const std::string TASK_CANCELLED_FLAG{"TASK_CANCELLED"}; class GlobalDBSingleton { std::atomic multithreadingEnabled; std::unique_ptr databaseThread; std::atomic tasksCancelled; GlobalDBSingleton(); void scheduleOrRunCommonImpl(const taskType task) { if (this->databaseThread != nullptr) { this->databaseThread->scheduleTask(task); return; } task(); } void scheduleOrRunCancellableCommonImpl(const taskType task) { if (this->tasksCancelled.load()) { throw std::runtime_error(TASK_CANCELLED_FLAG); } this->scheduleOrRunCommonImpl([this, task]() { if (this->tasksCancelled.load()) { throw std::runtime_error(TASK_CANCELLED_FLAG); } task(); }); } + void scheduleOrRunCancellableCommonImpl( + const taskType task, + const std::shared_ptr promise, + const std::shared_ptr jsInvoker) { + if (this->tasksCancelled.load()) { + jsInvoker->invokeAsync( + [promise]() { promise->reject(TASK_CANCELLED_FLAG); }); + return; + } + + scheduleOrRunCommonImpl([this, task, promise, jsInvoker]() { + if (this->tasksCancelled.load()) { + jsInvoker->invokeAsync( + [promise]() { promise->reject(TASK_CANCELLED_FLAG); }); + return; + } + task(); + }); + } + void enableMultithreadingCommonImpl() { if (this->databaseThread == nullptr) { this->databaseThread = std::make_unique("database"); this->multithreadingEnabled.store(true); } } public: static GlobalDBSingleton instance; void scheduleOrRun(const taskType task); void scheduleOrRunCancellable(const taskType task); + void scheduleOrRunCancellable( + const taskType task, + const std::shared_ptr promise, + const std::shared_ptr jsInvoker); void enableMultithreading(); void setTasksCancelled(bool tasksCancelled) { this->tasksCancelled.store(tasksCancelled); } }; } // namespace comm diff --git a/native/ios/Comm/GlobalDBSingleton.mm b/native/ios/Comm/GlobalDBSingleton.mm index d2e135243..23c9360d5 100644 --- a/native/ios/Comm/GlobalDBSingleton.mm +++ b/native/ios/Comm/GlobalDBSingleton.mm @@ -1,45 +1,60 @@ #import "GlobalDBSingleton.h" #import +#include namespace comm { GlobalDBSingleton GlobalDBSingleton::instance; GlobalDBSingleton::GlobalDBSingleton() : multithreadingEnabled(false), databaseThread(nullptr), tasksCancelled(false) { } void GlobalDBSingleton::scheduleOrRun(const taskType task) { if (NSThread.isMainThread || this->multithreadingEnabled.load()) { this->scheduleOrRunCommonImpl(task); return; } dispatch_async(dispatch_get_main_queue(), ^{ this->scheduleOrRunCommonImpl(task); }); } void GlobalDBSingleton::scheduleOrRunCancellable(const taskType task) { if (NSThread.isMainThread || this->multithreadingEnabled.load()) { this->scheduleOrRunCancellableCommonImpl(task); return; } dispatch_async(dispatch_get_main_queue(), ^{ this->scheduleOrRunCancellableCommonImpl(task); }); } +void GlobalDBSingleton::scheduleOrRunCancellable( + const taskType task, + const std::shared_ptr promise, + const std::shared_ptr jsInvoker) { + if (NSThread.isMainThread || this->multithreadingEnabled.load()) { + this->scheduleOrRunCancellableCommonImpl(task, promise, jsInvoker); + return; + } + + dispatch_async(dispatch_get_main_queue(), ^{ + this->scheduleOrRunCancellableCommonImpl(task, promise, jsInvoker); + }); +} + void GlobalDBSingleton::enableMultithreading() { if (NSThread.isMainThread) { this->enableMultithreadingCommonImpl(); return; } dispatch_async(dispatch_get_main_queue(), ^{ this->enableMultithreadingCommonImpl(); }); } } // namespace comm