@op-engineering/op-sqlite 2.0.0 → 2.0.2
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.
- package/README.md +82 -24
- package/android/CMakeLists.txt +4 -2
- package/cpp/DumbHostObject.cpp +32 -27
- package/cpp/DumbHostObject.h +16 -16
- package/cpp/PreparedStatementHostObject.cpp +88 -0
- package/cpp/PreparedStatementHostObject.h +36 -0
- package/cpp/SmartHostObject.cpp +33 -0
- package/cpp/SmartHostObject.h +26 -0
- package/cpp/ThreadPool.cpp +103 -116
- package/cpp/ThreadPool.h +27 -27
- package/cpp/bindings.cpp +525 -530
- package/cpp/bindings.h +6 -5
- package/cpp/bridge.cpp +713 -651
- package/cpp/bridge.h +41 -19
- package/cpp/logs.h +17 -17
- package/cpp/macros.h +1 -1
- package/cpp/sqlbatchexecutor.cpp +75 -77
- package/cpp/sqlbatchexecutor.h +9 -8
- package/cpp/sqlite3.h +1295 -1389
- package/cpp/types.h +5 -4
- package/cpp/utils.cpp +159 -191
- package/cpp/utils.h +28 -35
- package/ios/OPSQLite.mm +13 -5
- package/lib/commonjs/index.js +2 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/index.d.ts +6 -0
- package/package.json +2 -1
- package/src/index.ts +8 -0
- package/cpp/DynamicHostObject.cpp +0 -32
- package/cpp/DynamicHostObject.h +0 -26
package/cpp/ThreadPool.cpp
CHANGED
|
@@ -2,129 +2,116 @@
|
|
|
2
2
|
|
|
3
3
|
namespace opsqlite {
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
numberOfThreads = 1;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
for (unsigned i = 0; i < numberOfThreads; ++i)
|
|
17
|
-
{
|
|
18
|
-
// The threads will execute the private member `doWork`. Note that we need
|
|
19
|
-
// to pass a reference to the function (namespaced with the class name) as
|
|
20
|
-
// the first argument, and the current object as second argument
|
|
21
|
-
threads.push_back(std::thread(&ThreadPool::doWork, this));
|
|
22
|
-
}
|
|
23
|
-
}
|
|
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
|
+
}
|
|
24
13
|
|
|
25
|
-
|
|
26
|
-
//
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
// Wake up all the threads, so they can finish and be joined
|
|
33
|
-
workQueueConditionVariable.notify_all();
|
|
34
|
-
|
|
35
|
-
for (auto &thread : threads)
|
|
36
|
-
{
|
|
37
|
-
if (thread.joinable())
|
|
38
|
-
{
|
|
39
|
-
thread.join();
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
threads.clear();
|
|
44
|
-
}
|
|
14
|
+
for (unsigned i = 0; i < numberOfThreads; ++i) {
|
|
15
|
+
// The threads will execute the private member `doWork`. Note that we need
|
|
16
|
+
// to pass a reference to the function (namespaced with the class name) as
|
|
17
|
+
// the first argument, and the current object as second argument
|
|
18
|
+
threads.push_back(std::thread(&ThreadPool::doWork, this));
|
|
19
|
+
}
|
|
20
|
+
}
|
|
45
21
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
22
|
+
// The destructor joins all the threads so the program can exit gracefully.
|
|
23
|
+
// This will be executed if there is any exception (e.g. creating the threads)
|
|
24
|
+
ThreadPool::~ThreadPool() {
|
|
25
|
+
// So threads know it's time to shut down
|
|
26
|
+
done = true;
|
|
27
|
+
|
|
28
|
+
// Wake up all the threads, so they can finish and be joined
|
|
29
|
+
workQueueConditionVariable.notify_all();
|
|
30
|
+
|
|
31
|
+
for (auto &thread : threads) {
|
|
32
|
+
if (thread.joinable()) {
|
|
33
|
+
thread.join();
|
|
58
34
|
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
threads.clear();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// This function will be called by the server every time there is a request
|
|
41
|
+
// that needs to be processed by the thread pool
|
|
42
|
+
void ThreadPool::queueWork(std::function<void(void)> task) {
|
|
43
|
+
// Grab the mutex
|
|
44
|
+
std::lock_guard<std::mutex> g(workQueueMutex);
|
|
45
|
+
|
|
46
|
+
// Push the request to the queue
|
|
47
|
+
workQueue.push(task);
|
|
48
|
+
|
|
49
|
+
// Notify one thread that there are requests to process
|
|
50
|
+
workQueueConditionVariable.notify_one();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Function used by the threads to grab work from the queue
|
|
54
|
+
void ThreadPool::doWork() {
|
|
55
|
+
// Loop while the queue is not destructing
|
|
56
|
+
while (!done) {
|
|
57
|
+
std::function<void(void)> task;
|
|
59
58
|
|
|
60
|
-
//
|
|
61
|
-
void ThreadPool::doWork()
|
|
59
|
+
// Create a scope, so we don't lock the queue for longer than necessary
|
|
62
60
|
{
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
// shutting down
|
|
75
|
-
return !workQueue.empty() || done; });
|
|
76
|
-
|
|
77
|
-
// If we are shutting down exit witout trying to process more work
|
|
78
|
-
if (done)
|
|
79
|
-
{
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
task = workQueue.front();
|
|
84
|
-
workQueue.pop();
|
|
85
|
-
}
|
|
86
|
-
++busy;
|
|
87
|
-
task();
|
|
88
|
-
--busy;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
61
|
+
std::unique_lock<std::mutex> g(workQueueMutex);
|
|
62
|
+
workQueueConditionVariable.wait(g, [&] {
|
|
63
|
+
// Only wake up if there are elements in the queue or the program is
|
|
64
|
+
// shutting down
|
|
65
|
+
return !workQueue.empty() || done;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
// If we are shutting down exit witout trying to process more work
|
|
69
|
+
if (done) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
91
72
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
workQueueConditionVariable.wait(g, [&]{ return workQueue.empty() && (busy == 0); });
|
|
73
|
+
task = workQueue.front();
|
|
74
|
+
workQueue.pop();
|
|
95
75
|
}
|
|
76
|
+
++busy;
|
|
77
|
+
task();
|
|
78
|
+
--busy;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
void ThreadPool::waitFinished() {
|
|
83
|
+
std::unique_lock<std::mutex> g(workQueueMutex);
|
|
84
|
+
workQueueConditionVariable.wait(
|
|
85
|
+
g, [&] { return workQueue.empty() && (busy == 0); });
|
|
86
|
+
}
|
|
96
87
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
{
|
|
108
|
-
thread.join();
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
threads.clear();
|
|
113
|
-
|
|
114
|
-
auto numberOfThreads = std::thread::hardware_concurrency();
|
|
115
|
-
if (numberOfThreads == 0)
|
|
116
|
-
{
|
|
117
|
-
numberOfThreads = 1;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
for (unsigned i = 0; i < numberOfThreads; ++i)
|
|
121
|
-
{
|
|
122
|
-
// The threads will execute the private member `doWork`. Note that we need
|
|
123
|
-
// to pass a reference to the function (namespaced with the class name) as
|
|
124
|
-
// the first argument, and the current object as second argument
|
|
125
|
-
threads.push_back(std::thread(&ThreadPool::doWork, this));
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
done = false;
|
|
88
|
+
void ThreadPool::restartPool() {
|
|
89
|
+
// So threads know it's time to shut down
|
|
90
|
+
done = true;
|
|
91
|
+
|
|
92
|
+
// Wake up all the threads, so they can finish and be joined
|
|
93
|
+
workQueueConditionVariable.notify_all();
|
|
94
|
+
|
|
95
|
+
for (auto &thread : threads) {
|
|
96
|
+
if (thread.joinable()) {
|
|
97
|
+
thread.join();
|
|
129
98
|
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
threads.clear();
|
|
102
|
+
|
|
103
|
+
auto numberOfThreads = std::thread::hardware_concurrency();
|
|
104
|
+
if (numberOfThreads == 0) {
|
|
105
|
+
numberOfThreads = 1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (unsigned i = 0; i < numberOfThreads; ++i) {
|
|
109
|
+
// The threads will execute the private member `doWork`. Note that we need
|
|
110
|
+
// to pass a reference to the function (namespaced with the class name) as
|
|
111
|
+
// the first argument, and the current object as second argument
|
|
112
|
+
threads.push_back(std::thread(&ThreadPool::doWork, this));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
done = false;
|
|
130
116
|
}
|
|
117
|
+
} // namespace opsqlite
|
package/cpp/ThreadPool.h
CHANGED
|
@@ -13,35 +13,35 @@ namespace opsqlite {
|
|
|
13
13
|
|
|
14
14
|
class ThreadPool {
|
|
15
15
|
public:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
ThreadPool();
|
|
17
|
+
~ThreadPool();
|
|
18
|
+
void queueWork(std::function<void(void)> task);
|
|
19
|
+
void waitFinished();
|
|
20
|
+
void restartPool();
|
|
21
|
+
|
|
22
22
|
private:
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
23
|
+
unsigned int busy;
|
|
24
|
+
// This condition variable is used for the threads to wait until there is work
|
|
25
|
+
// to do
|
|
26
|
+
std::condition_variable_any workQueueConditionVariable;
|
|
27
|
+
|
|
28
|
+
// We store the threads in a vector, so we can later stop them gracefully
|
|
29
|
+
std::vector<std::thread> threads;
|
|
30
|
+
|
|
31
|
+
// Mutex to protect workQueue
|
|
32
|
+
std::mutex workQueueMutex;
|
|
33
|
+
|
|
34
|
+
// Queue of requests waiting to be processed
|
|
35
|
+
std::queue<std::function<void(void)>> workQueue;
|
|
36
|
+
|
|
37
|
+
// This will be set to true when the thread pool is shutting down. This tells
|
|
38
|
+
// the threads to stop looping and finish
|
|
39
|
+
bool done;
|
|
40
|
+
|
|
41
|
+
// Function used by the threads to grab work from the queue
|
|
42
|
+
void doWork();
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
}
|
|
45
|
+
} // namespace opsqlite
|
|
46
46
|
|
|
47
47
|
#endif /* ThreadPool_h */
|