-
-
Notifications
You must be signed in to change notification settings - Fork 324
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Threadsafe connection #1395
base: dev
Are you sure you want to change the base?
Threadsafe connection #1395
Conversation
The connection holder should be performant in all variants: 1. single-threaded use 2. opened once (open forever) 3. concurrent open/close Hence, a light-weight binary semaphore is used to synchronize opening and closing a database connection.
A user-provided 'on open' handler and connection control options can now be specified in a declarative way when making the 'storage' object.
564025d
to
14a2aa0
Compare
} | ||
|
||
void release() { | ||
// last one closes the connection. | ||
// we assume that this might happen by any thread, therefore the counter must serve as a synchronization point. | ||
if (this->_retain_count.fetch_sub(1, std::memory_order_acq_rel) == 1) { | ||
if (_retainCount.fetch_sub(1, std::memory_order_acq_rel) == 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why did you remove this
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have code that omits this
if the member variable starts with an underscore, so I removed it here as well.
What do you think? I find it easier to read and it's clear enough.
|
||
#ifdef SQLITE_ORM_CTAD_SUPPORTED | ||
template<template<typename...> class R, class Tpl, size_t... Idx, class Projection = polyfill::identity> | ||
constexpr auto create_from_tuple(Tpl&& tpl, std::index_sequence<Idx...>, Projection project = {}) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would be nice to have it covered with unit tests
@@ -4,6 +4,26 @@ | |||
|
|||
using namespace sqlite_orm; | |||
|
|||
#ifdef SQLITE_ORM_CTAD_SUPPORTED | |||
TEST_CASE("connection control") { | |||
const auto openForever = GENERATE(false, true); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is GENERATE
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A Catch2 data generator.
const auto openForever = GENERATE(false, true); | ||
SECTION("") { | ||
SECTION("empty") { | ||
auto storage = make_storage("", connection_control{openForever}, on_open([](sqlite3*) {})); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably we may add also on_open
call counter increment inside on_open
and checking that is was or wasn't called
#ifdef SQLITE_ORM_CTAD_SUPPORTED | ||
TEST_CASE("connection control") { | ||
const auto openForever = GENERATE(false, true); | ||
SECTION("") { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what is the purpose of empty single session?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GENERATE
repeats the SECTION
following it.
With C++20 a more light-weight binary semaphore can be conditionally used to synchronize opening and closing a database connection.
Therefore, the connection holder should be minimally invasive and performant in all variants:
Note: One important change is that things involved around setting up a database connection - like creating application-defined functions, setting pragma or limit values - must be done under the same synchronization point right after opening the database.
Caveat: Currently the connection cannot yet be recursively retained; think: user-provided 'on open' handlers.