@op-engineering/op-sqlite 11.2.14 → 11.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -3,116 +3,118 @@
3
3
  namespace opsqlite {
4
4
 
5
5
  ThreadPool::ThreadPool() : done(false) {
6
- // This returns the number of threads supported by the system. If the
7
- // function can't figure out this information, it returns 0. 0 is not good,
8
- // so we create at least 1
9
- // auto numberOfThreads = std::thread::hardware_concurrency();
10
- // if (numberOfThreads == 0) {
11
- // numberOfThreads = 1;
12
- // }
13
-
14
- auto numberOfThreads = 1;
15
- for (unsigned i = 0; i < numberOfThreads; ++i) {
16
- // The threads will execute the private member `doWork`. Note that we need
17
- // to pass a reference to the function (namespaced with the class name) as
18
- // the first argument, and the current object as second argument
19
- threads.emplace_back(&ThreadPool::doWork, this);
20
- }
6
+ // This returns the number of threads supported by the system. If the
7
+ // function can't figure out this information, it returns 0. 0 is not good,
8
+ // so we create at least 1
9
+ // auto numberOfThreads = std::thread::hardware_concurrency();
10
+ // if (numberOfThreads == 0) {
11
+ // numberOfThreads = 1;
12
+ // }
13
+
14
+ auto numberOfThreads = 1;
15
+ for (unsigned i = 0; i < numberOfThreads; ++i) {
16
+ // The threads will execute the private member `doWork`. Note that we
17
+ // need to pass a reference to the function (namespaced with the class
18
+ // name) as the first argument, and the current object as second
19
+ // argument
20
+ threads.emplace_back(&ThreadPool::doWork, this);
21
+ }
21
22
  }
22
23
 
23
24
  // The destructor joins all the threads so the program can exit gracefully.
24
25
  // This will be executed if there is any exception (e.g. creating the threads)
25
26
  ThreadPool::~ThreadPool() {
26
- // So threads know it's time to shut down
27
- done = true;
27
+ // So threads know it's time to shut down
28
+ done = true;
28
29
 
29
- // Wake up all the threads, so they can finish and be joined
30
- workQueueConditionVariable.notify_all();
30
+ // Wake up all the threads, so they can finish and be joined
31
+ workQueueConditionVariable.notify_all();
31
32
 
32
- for (auto &thread : threads) {
33
- if (thread.joinable()) {
34
- thread.join();
33
+ for (auto &thread : threads) {
34
+ if (thread.joinable()) {
35
+ thread.join();
36
+ }
35
37
  }
36
- }
37
38
 
38
- threads.clear();
39
+ threads.clear();
39
40
  }
40
41
 
41
42
  // This function will be called by the server every time there is a request
42
43
  // that needs to be processed by the thread pool
43
- void ThreadPool::queueWork(const std::function<void(void)>& task) {
44
- // Grab the mutex
45
- std::lock_guard<std::mutex> g(workQueueMutex);
44
+ void ThreadPool::queueWork(const std::function<void(void)> &task) {
45
+ // Grab the mutex
46
+ std::lock_guard<std::mutex> g(workQueueMutex);
46
47
 
47
- // Push the request to the queue
48
- workQueue.push(task);
48
+ // Push the request to the queue
49
+ workQueue.push(task);
49
50
 
50
- // Notify one thread that there are requests to process
51
- workQueueConditionVariable.notify_one();
51
+ // Notify one thread that there are requests to process
52
+ workQueueConditionVariable.notify_one();
52
53
  }
53
54
 
54
55
  // Function used by the threads to grab work from the queue
55
56
  void ThreadPool::doWork() {
56
- // Loop while the queue is not destructing
57
- while (!done) {
58
- std::function<void(void)> task;
59
-
60
- // Create a scope, so we don't lock the queue for longer than necessary
61
- {
62
- std::unique_lock<std::mutex> g(workQueueMutex);
63
- workQueueConditionVariable.wait(g, [&] {
64
- // Only wake up if there are elements in the queue or the program is
65
- // shutting down
66
- return !workQueue.empty() || done;
67
- });
68
-
69
- // If we are shutting down exit without trying to process more work
70
- if (done) {
71
- break;
72
- }
73
-
74
- task = workQueue.front();
75
- workQueue.pop();
57
+ // Loop while the queue is not destructing
58
+ while (!done) {
59
+ std::function<void(void)> task;
60
+
61
+ // Create a scope, so we don't lock the queue for longer than necessary
62
+ {
63
+ std::unique_lock<std::mutex> g(workQueueMutex);
64
+ workQueueConditionVariable.wait(g, [&] {
65
+ // Only wake up if there are elements in the queue or the
66
+ // program is shutting down
67
+ return !workQueue.empty() || done;
68
+ });
69
+
70
+ // If we are shutting down exit without trying to process more work
71
+ if (done) {
72
+ break;
73
+ }
74
+
75
+ task = workQueue.front();
76
+ workQueue.pop();
77
+ }
78
+ ++busy;
79
+ task();
80
+ --busy;
76
81
  }
77
- ++busy;
78
- task();
79
- --busy;
80
- }
81
82
  }
82
83
 
83
84
  void ThreadPool::waitFinished() {
84
- std::unique_lock<std::mutex> g(workQueueMutex);
85
- workQueueConditionVariable.wait(
86
- g, [&] { return workQueue.empty() && (busy == 0); });
85
+ std::unique_lock<std::mutex> g(workQueueMutex);
86
+ workQueueConditionVariable.wait(
87
+ g, [&] { return workQueue.empty() && (busy == 0); });
87
88
  }
88
89
 
89
90
  void ThreadPool::restartPool() {
90
- // So threads know it's time to shut down
91
- done = true;
91
+ // So threads know it's time to shut down
92
+ done = true;
92
93
 
93
- // Wake up all the threads, so they can finish and be joined
94
- workQueueConditionVariable.notify_all();
94
+ // Wake up all the threads, so they can finish and be joined
95
+ workQueueConditionVariable.notify_all();
95
96
 
96
- for (auto &thread : threads) {
97
- if (thread.joinable()) {
98
- thread.join();
97
+ for (auto &thread : threads) {
98
+ if (thread.joinable()) {
99
+ thread.join();
100
+ }
99
101
  }
100
- }
101
102
 
102
- threads.clear();
103
+ threads.clear();
103
104
 
104
- auto numberOfThreads = std::thread::hardware_concurrency();
105
- if (numberOfThreads == 0) {
106
- numberOfThreads = 1;
107
- }
105
+ auto numberOfThreads = std::thread::hardware_concurrency();
106
+ if (numberOfThreads == 0) {
107
+ numberOfThreads = 1;
108
+ }
108
109
 
109
- for (unsigned i = 0; i < numberOfThreads; ++i) {
110
- // The threads will execute the private member `doWork`. Note that we need
111
- // to pass a reference to the function (namespaced with the class name) as
112
- // the first argument, and the current object as second argument
113
- threads.emplace_back(&ThreadPool::doWork, this);
114
- }
110
+ for (unsigned i = 0; i < numberOfThreads; ++i) {
111
+ // The threads will execute the private member `doWork`. Note that we
112
+ // need to pass a reference to the function (namespaced with the class
113
+ // name) as the first argument, and the current object as second
114
+ // argument
115
+ threads.emplace_back(&ThreadPool::doWork, this);
116
+ }
115
117
 
116
- done = false;
118
+ done = false;
117
119
  }
118
120
  } // namespace opsqlite
package/cpp/ThreadPool.h CHANGED
@@ -11,34 +11,34 @@
11
11
  namespace opsqlite {
12
12
 
13
13
  class ThreadPool {
14
- public:
15
- ThreadPool();
16
- ~ThreadPool();
17
- void queueWork(const std::function<void(void)>& task);
18
- void waitFinished();
19
- void restartPool();
20
-
21
- private:
22
- unsigned int busy{};
23
- // This condition variable is used for the threads to wait until there is work
24
- // to do
25
- std::condition_variable_any workQueueConditionVariable;
26
-
27
- // We store the threads in a vector, so we can later stop them gracefully
28
- std::vector<std::thread> threads;
29
-
30
- // Mutex to protect workQueue
31
- std::mutex workQueueMutex;
32
-
33
- // Queue of requests waiting to be processed
34
- std::queue<std::function<void(void)>> workQueue;
35
-
36
- // This will be set to true when the thread pool is shutting down. This tells
37
- // the threads to stop looping and finish
38
- bool done;
39
-
40
- // Function used by the threads to grab work from the queue
41
- void doWork();
14
+ public:
15
+ ThreadPool();
16
+ ~ThreadPool();
17
+ void queueWork(const std::function<void(void)> &task);
18
+ void waitFinished();
19
+ void restartPool();
20
+
21
+ private:
22
+ unsigned int busy{};
23
+ // This condition variable is used for the threads to wait until there is
24
+ // work to do
25
+ std::condition_variable_any workQueueConditionVariable;
26
+
27
+ // We store the threads in a vector, so we can later stop them gracefully
28
+ std::vector<std::thread> threads;
29
+
30
+ // Mutex to protect workQueue
31
+ std::mutex workQueueMutex;
32
+
33
+ // Queue of requests waiting to be processed
34
+ std::queue<std::function<void(void)>> workQueue;
35
+
36
+ // This will be set to true when the thread pool is shutting down. This
37
+ // tells the threads to stop looping and finish
38
+ bool done;
39
+
40
+ // Function used by the threads to grab work from the queue
41
+ void doWork();
42
42
  };
43
43
 
44
44
  } // namespace opsqlite
package/cpp/bindings.cpp CHANGED
@@ -27,143 +27,147 @@ std::vector<std::shared_ptr<DBHostObject>> dbs;
27
27
  // React native will try to clean the module on JS context invalidation
28
28
  // (CodePush/Hot Reload) The clearState function is called
29
29
  void invalidate() {
30
- for (const auto &db : dbs) {
31
- db->invalidate();
32
- }
30
+ for (const auto &db : dbs) {
31
+ db->invalidate();
32
+ }
33
33
 
34
- // Clear our existing vector of shared pointers so they can be garbage
35
- // collected
36
- dbs.clear();
34
+ // Clear our existing vector of shared pointers so they can be garbage
35
+ // collected
36
+ dbs.clear();
37
37
  }
38
38
 
39
39
  void install(jsi::Runtime &rt,
40
40
  const std::shared_ptr<react::CallInvoker> &invoker,
41
41
  const char *base_path, const char *crsqlite_path,
42
42
  const char *sqlite_vec_path) {
43
- _base_path = std::string(base_path);
44
- _crsqlite_path = std::string(crsqlite_path);
45
- _sqlite_vec_path = std::string(sqlite_vec_path);
46
-
47
- auto open = HOST_STATIC_FN("open") {
48
- jsi::Object options = args[0].asObject(rt);
49
- std::string name = options.getProperty(rt, "name").asString(rt).utf8(rt);
50
- std::string path = std::string(_base_path);
51
- std::string location;
52
- std::string encryption_key;
53
-
54
- if (options.hasProperty(rt, "location")) {
55
- location = options.getProperty(rt, "location").asString(rt).utf8(rt);
56
- }
57
-
58
- if (options.hasProperty(rt, "encryptionKey")) {
59
- encryption_key =
60
- options.getProperty(rt, "encryptionKey").asString(rt).utf8(rt);
61
- }
43
+ _base_path = std::string(base_path);
44
+ _crsqlite_path = std::string(crsqlite_path);
45
+ _sqlite_vec_path = std::string(sqlite_vec_path);
46
+
47
+ auto open = HOST_STATIC_FN("open") {
48
+ jsi::Object options = args[0].asObject(rt);
49
+ std::string name =
50
+ options.getProperty(rt, "name").asString(rt).utf8(rt);
51
+ std::string path = std::string(_base_path);
52
+ std::string location;
53
+ std::string encryption_key;
54
+
55
+ if (options.hasProperty(rt, "location")) {
56
+ location =
57
+ options.getProperty(rt, "location").asString(rt).utf8(rt);
58
+ }
59
+
60
+ if (options.hasProperty(rt, "encryptionKey")) {
61
+ encryption_key =
62
+ options.getProperty(rt, "encryptionKey").asString(rt).utf8(rt);
63
+ }
62
64
 
63
65
  #ifdef OP_SQLITE_USE_SQLCIPHER
64
- if (encryption_key.empty()) {
65
- log_to_console(rt, "Encryption key is missing for SQLCipher");
66
- }
66
+ if (encryption_key.empty()) {
67
+ log_to_console(rt, "Encryption key is missing for SQLCipher");
68
+ }
67
69
  #endif
68
70
 
69
- if (!location.empty()) {
70
- if (location == ":memory:") {
71
- path = ":memory:";
72
- } else if (location.rfind('/', 0) == 0) {
73
- path = location;
74
- } else {
75
- path = path + "/" + location;
76
- }
77
- }
78
-
79
- std::shared_ptr<DBHostObject> db = std::make_shared<DBHostObject>(
80
- rt, path, invoker, name, path, _crsqlite_path, _sqlite_vec_path,
81
- encryption_key);
82
- dbs.emplace_back(db);
83
- return jsi::Object::createFromHostObject(rt, db);
84
- });
85
-
86
- auto is_sqlcipher = HOST_STATIC_FN("isSQLCipher") {
71
+ if (!location.empty()) {
72
+ if (location == ":memory:") {
73
+ path = ":memory:";
74
+ } else if (location.rfind('/', 0) == 0) {
75
+ path = location;
76
+ } else {
77
+ path = path + "/" + location;
78
+ }
79
+ }
80
+
81
+ std::shared_ptr<DBHostObject> db = std::make_shared<DBHostObject>(
82
+ rt, path, invoker, name, path, _crsqlite_path, _sqlite_vec_path,
83
+ encryption_key);
84
+ dbs.emplace_back(db);
85
+ return jsi::Object::createFromHostObject(rt, db);
86
+ });
87
+
88
+ auto is_sqlcipher = HOST_STATIC_FN("isSQLCipher") {
87
89
  #ifdef OP_SQLITE_USE_SQLCIPHER
88
- return true;
90
+ return true;
89
91
  #else
90
- return false;
92
+ return false;
91
93
  #endif
92
- });
94
+ });
93
95
 
94
- auto is_ios_embedded = HOST_STATIC_FN("isIOSEmbedded") {
96
+ auto is_ios_embedded = HOST_STATIC_FN("isIOSEmbedded") {
95
97
  #ifdef OP_SQLITE_USE_PHONE_VERSION
96
- return true;
98
+ return true;
97
99
  #else
98
- return false;
100
+ return false;
99
101
  #endif
100
- });
102
+ });
101
103
 
102
- auto is_libsql = HOST_STATIC_FN("isLibsql") {
104
+ auto is_libsql = HOST_STATIC_FN("isLibsql") {
103
105
  #ifdef OP_SQLITE_USE_LIBSQL
104
- return true;
106
+ return true;
105
107
  #else
106
- return false;
108
+ return false;
107
109
  #endif
108
- });
110
+ });
109
111
 
110
112
  #ifdef OP_SQLITE_USE_LIBSQL
111
- auto open_remote = HOST_STATIC_FN("openRemote") {
112
- jsi::Object options = args[0].asObject(rt);
113
- std::string url = options.getProperty(rt, "url").asString(rt).utf8(rt);
114
- std::string auth_token =
115
- options.getProperty(rt, "authToken").asString(rt).utf8(rt);
116
-
117
- std::shared_ptr<DBHostObject> db =
118
- std::make_shared<DBHostObject>(rt, url, auth_token, invoker);
119
- return jsi::Object::createFromHostObject(rt, db);
120
- });
121
-
122
- auto open_sync = HOST_STATIC_FN("openSync") {
123
- jsi::Object options = args[0].asObject(rt);
124
- std::string name = options.getProperty(rt, "name").asString(rt).utf8(rt);
125
- std::string path = std::string(_base_path);
126
- std::string url = options.getProperty(rt, "url").asString(rt).utf8(rt);
127
- std::string auth_token =
128
- options.getProperty(rt, "authToken").asString(rt).utf8(rt);
129
- int sync_interval = 0;
130
- if (options.hasProperty(rt, "syncInterval")) {
131
- sync_interval =
132
- static_cast<int>(options.getProperty(rt, "syncInterval").asNumber());
133
- }
134
- std::string location;
135
-
136
- if (options.hasProperty(rt, "location")) {
137
- location = options.getProperty(rt, "location").asString(rt).utf8(rt);
138
- }
139
-
140
- if (!location.empty()) {
141
- if (location == ":memory:") {
142
- path = ":memory:";
143
- } else if (location.rfind("/", 0) == 0) {
144
- path = location;
145
- } else {
146
- path = path + "/" + location;
147
- }
148
- }
149
-
150
- std::shared_ptr<DBHostObject> db = std::make_shared<DBHostObject>(
151
- rt, invoker, name, path, url, auth_token, sync_interval);
152
- return jsi::Object::createFromHostObject(rt, db);
153
- });
113
+ auto open_remote = HOST_STATIC_FN("openRemote") {
114
+ jsi::Object options = args[0].asObject(rt);
115
+ std::string url = options.getProperty(rt, "url").asString(rt).utf8(rt);
116
+ std::string auth_token =
117
+ options.getProperty(rt, "authToken").asString(rt).utf8(rt);
118
+
119
+ std::shared_ptr<DBHostObject> db =
120
+ std::make_shared<DBHostObject>(rt, url, auth_token, invoker);
121
+ return jsi::Object::createFromHostObject(rt, db);
122
+ });
123
+
124
+ auto open_sync = HOST_STATIC_FN("openSync") {
125
+ jsi::Object options = args[0].asObject(rt);
126
+ std::string name =
127
+ options.getProperty(rt, "name").asString(rt).utf8(rt);
128
+ std::string path = std::string(_base_path);
129
+ std::string url = options.getProperty(rt, "url").asString(rt).utf8(rt);
130
+ std::string auth_token =
131
+ options.getProperty(rt, "authToken").asString(rt).utf8(rt);
132
+ int sync_interval = 0;
133
+ if (options.hasProperty(rt, "syncInterval")) {
134
+ sync_interval = static_cast<int>(
135
+ options.getProperty(rt, "syncInterval").asNumber());
136
+ }
137
+ std::string location;
138
+
139
+ if (options.hasProperty(rt, "location")) {
140
+ location =
141
+ options.getProperty(rt, "location").asString(rt).utf8(rt);
142
+ }
143
+
144
+ if (!location.empty()) {
145
+ if (location == ":memory:") {
146
+ path = ":memory:";
147
+ } else if (location.rfind("/", 0) == 0) {
148
+ path = location;
149
+ } else {
150
+ path = path + "/" + location;
151
+ }
152
+ }
153
+
154
+ std::shared_ptr<DBHostObject> db = std::make_shared<DBHostObject>(
155
+ rt, invoker, name, path, url, auth_token, sync_interval);
156
+ return jsi::Object::createFromHostObject(rt, db);
157
+ });
154
158
  #endif
155
159
 
156
- jsi::Object module = jsi::Object(rt);
157
- module.setProperty(rt, "open", std::move(open));
158
- module.setProperty(rt, "isSQLCipher", std::move(is_sqlcipher));
159
- module.setProperty(rt, "isLibsql", std::move(is_libsql));
160
- module.setProperty(rt, "isIOSEmbedded", std::move(is_ios_embedded));
160
+ jsi::Object module = jsi::Object(rt);
161
+ module.setProperty(rt, "open", std::move(open));
162
+ module.setProperty(rt, "isSQLCipher", std::move(is_sqlcipher));
163
+ module.setProperty(rt, "isLibsql", std::move(is_libsql));
164
+ module.setProperty(rt, "isIOSEmbedded", std::move(is_ios_embedded));
161
165
  #ifdef OP_SQLITE_USE_LIBSQL
162
- module.setProperty(rt, "openRemote", std::move(open_remote));
163
- module.setProperty(rt, "openSync", std::move(open_sync));
166
+ module.setProperty(rt, "openRemote", std::move(open_remote));
167
+ module.setProperty(rt, "openSync", std::move(open_sync));
164
168
  #endif
165
169
 
166
- rt.global().setProperty(rt, "__OPSQLiteProxy", std::move(module));
170
+ rt.global().setProperty(rt, "__OPSQLiteProxy", std::move(module));
167
171
  }
168
172
 
169
173
  } // namespace opsqlite