Skip to content

Commit 34ac140

Browse files
authored
Merge pull request #1395 from fnc12/experimental/threadsafe_connection
Thread-safe connection
2 parents 8742640 + e9da7ef commit 34ac140

File tree

13 files changed

+1172
-456
lines changed

13 files changed

+1172
-456
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
# SQLite ORM
1515
SQLite ORM light header only library for modern C++. Please read the license precisely. The project has AGPL license for open source project and MIT license after purchasing it for 50$ (using [PayPal](https://paypal.me/fnc12) or any different way (contact using email [email protected])).
1616

17+
Documentation is found in [docs](docs/home.md).
18+
1719
# Status
1820
| Branch | Travis | Appveyor |
1921
| :----- | :----- | :------- |

dev/backup.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ namespace sqlite_orm {
2828
const std::string& zSourceName,
2929
std::unique_ptr<connection_holder> holder_) :
3030
handle(sqlite3_backup_init(to_.get(), zDestName.c_str(), from_.get(), zSourceName.c_str())),
31-
holder(std::move(holder_)), to(to_), from(from_) {
31+
holder(std::move(holder_)), to(std::move(to_)), from(std::move(from_)) {
3232
if (!this->handle) {
3333
throw std::system_error{orm_error_code::failed_to_init_a_backup};
3434
}
3535
}
3636

3737
backup_t(backup_t&& other) :
38-
handle(std::exchange(other.handle, nullptr)), holder(std::move(other.holder)), to(other.to),
39-
from(other.from) {}
38+
handle(std::exchange(other.handle, nullptr)), holder(std::move(other.holder)), to(std::move(other.to)),
39+
from(std::move(other.from)) {}
4040

4141
~backup_t() {
4242
if (this->handle) {

dev/connection_holder.h

Lines changed: 243 additions & 63 deletions
Large diffs are not rendered by default.

dev/functional/cxx_new.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#ifdef SQLITE_ORM_IMPORT_STD_MODULE
4+
#include <version>
5+
#else
6+
#include <new>
7+
#endif
8+
9+
namespace sqlite_orm {
10+
namespace internal {
11+
namespace polyfill {
12+
#if __cpp_lib_hardware_interference_size >= 201703L
13+
using std::hardware_constructive_interference_size;
14+
using std::hardware_destructive_interference_size;
15+
#else
16+
constexpr size_t hardware_constructive_interference_size = 64;
17+
constexpr size_t hardware_destructive_interference_size = 64;
18+
#endif
19+
}
20+
}
21+
22+
namespace polyfill = internal::polyfill;
23+
}

dev/functional/cxx_scope_guard.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#pragma once
2+
3+
#ifndef SQLITE_ORM_IMPORT_STD_MODULE
4+
#include <utility> // std::forward
5+
#endif
6+
7+
namespace sqlite_orm::internal {
8+
/*
9+
Poor-man's scope (exit) guard until C++29 finally comes with proper standard facilities [Draft D3610].
10+
*/
11+
template<class F>
12+
class scope_guard {
13+
public:
14+
explicit scope_guard(F&& exitFunction) : _exitFunction{std::forward<F>(exitFunction)} {}
15+
16+
~scope_guard() {
17+
_exitFunction();
18+
}
19+
20+
private:
21+
F _exitFunction;
22+
};
23+
}

dev/limit_accessor.h

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@
33
#include <sqlite3.h>
44
#ifndef SQLITE_ORM_IMPORT_STD_MODULE
55
#include <map> // std::map
6-
#include <functional> // std::function
7-
#include <memory> // std::shared_ptr
6+
#include <functional> // std::function, std::reference_wrapper
7+
#include <utility> // std::move
88
#endif
99

1010
#include "connection_holder.h"
@@ -14,9 +14,7 @@ namespace sqlite_orm {
1414
namespace internal {
1515

1616
struct limit_accessor {
17-
using get_connection_t = std::function<connection_ref()>;
18-
19-
limit_accessor(get_connection_t get_connection_) : get_connection(std::move(get_connection_)) {}
17+
limit_accessor(std::unique_ptr<connection_holder>& connection) : connection{connection} {}
2018

2119
int length() {
2220
return this->get(SQLITE_LIMIT_LENGTH);
@@ -117,7 +115,7 @@ namespace sqlite_orm {
117115
#endif
118116

119117
protected:
120-
get_connection_t get_connection;
118+
std::reference_wrapper<std::unique_ptr<connection_holder>> connection;
121119

122120
friend struct storage_base;
123121

@@ -127,14 +125,15 @@ namespace sqlite_orm {
127125
std::map<int, int> limits;
128126

129127
int get(int id) {
130-
auto connection = this->get_connection();
128+
connection_ref connection = *this->connection.get();
131129
return sqlite3_limit(connection.get(), id, -1);
132130
}
133131

134132
void set(int id, int newValue) {
135133
this->limits[id] = newValue;
136-
auto connection = this->get_connection();
137-
sqlite3_limit(connection.get(), id, newValue);
134+
if (connection_ptr maybeConnection = *this->connection.get()) {
135+
sqlite3_limit(maybeConnection.get(), id, newValue);
136+
}
138137
}
139138
};
140139
}

dev/statement_serializer.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
#include <memory>
1313
#include <array>
1414
#include <list> // std::list
15+
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
16+
#include <ranges> // std::views::transform
17+
#endif
1518
#endif
1619
#include "functional/cxx_string_view.h"
1720
#include "functional/cxx_optional.h"
@@ -1501,6 +1504,9 @@ namespace sqlite_orm {
15011504
const Ctx&) SQLITE_ORM_OR_CONST_CALLOP {
15021505
std::stringstream ss;
15031506
ss << "SET ";
1507+
#ifdef SQLITE_ORM_CPP20_RANGES_SUPPORTED
1508+
ss << streaming_serialized(statement | std::views::transform(&dynamic_set_entry::serialized_value));
1509+
#else
15041510
int index = 0;
15051511
for (const dynamic_set_entry& entry: statement) {
15061512
if (index > 0) {
@@ -1509,6 +1515,7 @@ namespace sqlite_orm {
15091515
ss << entry.serialized_value;
15101516
++index;
15111517
}
1518+
#endif
15121519
return ss.str();
15131520
}
15141521
};

dev/storage.h

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ namespace sqlite_orm {
146146
context_t context{this->db_objects};
147147
statement_serializer<Table, void> serializer;
148148
const std::string sql = serializer.serialize(table, context, tableName);
149-
this->executor.perform_void_exec(db, sql.data());
149+
this->executor.perform_void_exec(db, sql.c_str());
150150
}
151151

152152
/**
@@ -169,7 +169,7 @@ namespace sqlite_orm {
169169
<< streaming_identifier(columnName) << std::flush;
170170
sql = ss.str();
171171
}
172-
this->executor.perform_void_exec(db, sql.data());
172+
this->executor.perform_void_exec(db, sql.c_str());
173173
}
174174
#endif
175175

@@ -278,8 +278,8 @@ namespace sqlite_orm {
278278
mapped_view<O, self_type, Args...> iterate(Args&&... args) {
279279
this->assert_mapped_type<O>();
280280

281-
auto connection = this->get_connection();
282-
return {*this, std::move(connection), std::forward<Args>(args)...};
281+
auto conRef = this->get_connection();
282+
return {*this, std::move(conRef), std::forward<Args>(args)...};
283283
}
284284

285285
#ifdef SQLITE_ORM_WITH_CPP20_ALIASES
@@ -313,8 +313,8 @@ namespace sqlite_orm {
313313
if constexpr (is_select_v<Select>) {
314314
expression.highest_level = true;
315315
}
316-
auto con = this->get_connection();
317-
return {this->db_objects, std::move(con), std::move(expression)};
316+
auto conRef = this->get_connection();
317+
return {this->db_objects, std::move(conRef), std::move(expression)};
318318
}
319319

320320
#ifdef SQLITE_ORM_CPP23_GENERATOR_SUPPORTED
@@ -1235,7 +1235,7 @@ namespace sqlite_orm {
12351235
<< serialize(column, context) << std::flush;
12361236
sql = ss.str();
12371237
}
1238-
this->executor.perform_void_exec(db, sql.data());
1238+
this->executor.perform_void_exec(db, sql.c_str());
12391239
}
12401240

12411241
template<class ColResult, class S>
@@ -1286,10 +1286,10 @@ namespace sqlite_orm {
12861286
context.omit_table_name = false;
12871287
context.replace_bindable_with_question = true;
12881288

1289-
auto conection = this->get_connection();
12901289
const std::string sql = serialize(statement, context);
1291-
sqlite3_stmt* stmt = prepare_stmt(conection.get(), sql);
1292-
return prepared_statement_t<S>{std::forward<S>(statement), stmt, std::move(conection)};
1290+
auto conRef = this->get_connection();
1291+
sqlite3_stmt* stmt = prepare_stmt(conRef.get(), sql);
1292+
return prepared_statement_t<S>{std::forward<S>(statement), stmt, std::move(conRef)};
12931293
}
12941294

12951295
public:
@@ -1321,9 +1321,9 @@ namespace sqlite_orm {
13211321
* can be printed out on std::ostream with `operator<<`.
13221322
*/
13231323
std::map<std::string, sync_schema_result> sync_schema(bool preserve = false) {
1324-
auto con = this->get_connection();
1324+
auto conRef = this->get_connection();
13251325
std::map<std::string, sync_schema_result> result;
1326-
iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) {
1326+
iterate_tuple<true>(this->db_objects, [this, db = conRef.get(), preserve, &result](auto& schemaObject) {
13271327
sync_schema_result status = this->sync_dbo(schemaObject, db, preserve);
13281328
result.emplace(schemaObject.name, status);
13291329
});
@@ -1336,9 +1336,9 @@ namespace sqlite_orm {
13361336
* what will happen if you sync your schema.
13371337
*/
13381338
std::map<std::string, sync_schema_result> sync_schema_simulate(bool preserve = false) {
1339-
auto con = this->get_connection();
1339+
auto conRef = this->get_connection();
13401340
std::map<std::string, sync_schema_result> result;
1341-
iterate_tuple<true>(this->db_objects, [this, db = con.get(), preserve, &result](auto& schemaObject) {
1341+
iterate_tuple<true>(this->db_objects, [this, db = conRef.get(), preserve, &result](auto& schemaObject) {
13421342
sync_schema_result status = this->schema_status(schemaObject, db, preserve, nullptr);
13431343
result.emplace(schemaObject.name, status);
13441344
});

0 commit comments

Comments
 (0)