forked from audacity/audacity
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Adds a way to work with SQLite in a thread safe manner
- Loading branch information
Showing
5 changed files
with
218 additions
and
18 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
/* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
* SPDX-FileName: SafeConnection.cpp | ||
* SPDX-FileContributor: Dmitry Vedenko | ||
*/ | ||
|
||
#include "SafeConnection.h" | ||
|
||
namespace sqlite | ||
{ | ||
SafeConnection::SafeConnection(Tag, Connection connection) | ||
: mConnection(std::move(connection)) | ||
{ | ||
} | ||
|
||
std::shared_ptr<SafeConnection> SafeConnection::Open( | ||
std::string_view path, OpenMode mode, ThreadMode threadMode, | ||
Error* openError) | ||
{ | ||
auto connection = Connection::Open(path, mode, threadMode); | ||
|
||
if (!connection) | ||
{ | ||
if (openError) | ||
*openError = connection.GetError(); | ||
|
||
return {}; | ||
} | ||
|
||
return std::make_shared<SafeConnection>(Tag {}, std::move(*connection)); | ||
} | ||
|
||
std::shared_ptr<SafeConnection> SafeConnection::Reopen( | ||
const Connection& prevConnection, OpenMode mode, ThreadMode threadMode, | ||
Error* openError) | ||
{ | ||
auto connection = Connection::Reopen(prevConnection, mode, threadMode); | ||
|
||
if (!connection) | ||
{ | ||
if (openError) | ||
*openError = connection.GetError(); | ||
|
||
return {}; | ||
} | ||
|
||
return std::make_shared<SafeConnection>(Tag {}, std::move(*connection)); | ||
} | ||
|
||
std::shared_ptr<SafeConnection> SafeConnection::Reopen( | ||
sqlite3* prevConnection, OpenMode mode, ThreadMode threadMode, | ||
Error* openError) | ||
{ | ||
auto connection = Connection::Reopen(prevConnection, mode, threadMode); | ||
|
||
if (!connection) | ||
{ | ||
if (openError) | ||
*openError = connection.GetError(); | ||
|
||
return {}; | ||
} | ||
|
||
return std::make_shared<SafeConnection>(Tag {}, std::move(*connection)); | ||
} | ||
|
||
std::shared_ptr<SafeConnection> SafeConnection::Reopen( | ||
SafeConnection& prevConnection, OpenMode mode, ThreadMode threadMode, | ||
Error* openError) | ||
{ | ||
auto connection = | ||
Connection::Reopen(prevConnection.mConnection, mode, threadMode); | ||
|
||
if (!connection) | ||
{ | ||
if (openError) | ||
*openError = connection.GetError(); | ||
|
||
return {}; | ||
} | ||
|
||
return std::make_shared<SafeConnection>(Tag {}, std::move(*connection)); | ||
} | ||
|
||
SafeConnection::Lock SafeConnection::Acquire() noexcept | ||
{ | ||
return Lock { shared_from_this() }; | ||
} | ||
|
||
SafeConnection::Lock::Lock(std::shared_ptr<SafeConnection> connection) | ||
: mSafeConnection(std::move(connection)) | ||
{ | ||
if (mSafeConnection) | ||
mLock = std::unique_lock { mSafeConnection->mConnectionMutex }; | ||
} | ||
|
||
Connection* SafeConnection::Lock::operator->() noexcept | ||
{ | ||
return &mSafeConnection->mConnection; | ||
} | ||
|
||
const Connection* SafeConnection::Lock::operator->() const noexcept | ||
{ | ||
return &mSafeConnection->mConnection; | ||
} | ||
|
||
Connection& SafeConnection::Lock::operator*() noexcept | ||
{ | ||
return mSafeConnection->mConnection; | ||
} | ||
|
||
const Connection& SafeConnection::Lock::operator*() const noexcept | ||
{ | ||
return mSafeConnection->mConnection; | ||
} | ||
|
||
SafeConnection::Lock::operator bool() const noexcept | ||
{ | ||
return IsValid(); | ||
} | ||
|
||
bool SafeConnection::Lock::IsValid() const noexcept | ||
{ | ||
return mSafeConnection != nullptr; | ||
} | ||
|
||
} // namespace sqlite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
/* | ||
* SPDX-License-Identifier: GPL-2.0-or-later | ||
* SPDX-FileName: SafeConnection.h | ||
* SPDX-FileContributor: Dmitry Vedenko | ||
*/ | ||
|
||
#pragma once | ||
|
||
#include <memory> | ||
#include <mutex> | ||
|
||
#include "Connection.h" | ||
|
||
namespace sqlite | ||
{ | ||
class SQLITE_HELPERS_API SafeConnection final : | ||
public std::enable_shared_from_this<SafeConnection> | ||
{ | ||
struct Tag final | ||
{ | ||
}; | ||
|
||
using MutexType = std::recursive_mutex; | ||
|
||
public: | ||
SafeConnection(Tag, Connection connection); | ||
|
||
static std::shared_ptr<SafeConnection> Open( | ||
std::string_view path, OpenMode mode = OpenMode::ReadWriteCreate, | ||
ThreadMode threadMode = ThreadMode::Serialized, | ||
Error* openError = nullptr); | ||
|
||
static std::shared_ptr<SafeConnection> Reopen( | ||
const Connection& connection, OpenMode mode = OpenMode::ReadWriteCreate, | ||
ThreadMode threadMode = ThreadMode::Serialized, | ||
Error* openError = nullptr); | ||
|
||
static std::shared_ptr<SafeConnection> Reopen( | ||
sqlite3* connection, OpenMode mode = OpenMode::ReadWriteCreate, | ||
ThreadMode threadMode = ThreadMode::Serialized, | ||
Error* openError = nullptr); | ||
|
||
static std::shared_ptr<SafeConnection> Reopen( | ||
SafeConnection& connection, OpenMode mode = OpenMode::ReadWriteCreate, | ||
ThreadMode threadMode = ThreadMode::Serialized, | ||
Error* openError = nullptr); | ||
|
||
struct SQLITE_HELPERS_API Lock final | ||
{ | ||
explicit Lock(std::shared_ptr<SafeConnection> connection); | ||
~Lock() = default; | ||
|
||
Lock(const Lock&) = delete; | ||
Lock& operator=(const Lock&) = delete; | ||
Lock(Lock&&) = default; | ||
Lock& operator=(Lock&&) = default; | ||
|
||
Connection* operator->() noexcept; | ||
const Connection* operator->() const noexcept; | ||
|
||
Connection& operator*() noexcept; | ||
const Connection& operator*() const noexcept; | ||
|
||
explicit operator bool() const noexcept; | ||
bool IsValid() const noexcept; | ||
|
||
private: | ||
std::shared_ptr<SafeConnection> mSafeConnection; | ||
std::unique_lock<MutexType> mLock; | ||
}; | ||
|
||
Lock Acquire() noexcept; | ||
|
||
private: | ||
Connection mConnection; | ||
MutexType mConnectionMutex; | ||
}; | ||
} // namespace sqlite |