grpc 服务中连接的简单线程安全向量
simple thread safe vector for connections in grpc service
我正在尝试了解并发性,我正在 grpc 服务中实现一个小型连接池,该服务需要与 postgres 数据库建立许多连接。
我正在尝试实现一个基本的 connectionPool 以防止为每个请求创建一个新连接。首先,我尝试创建一个线程安全 std::vector
。当我 运行 grpc 服务器时,进行了单个事务,然后服务器阻塞,但我无法推断出发生了什么。任何帮助将不胜感激
class SafeVector {
std::vector<pqxx::connection*> pool_;
int size_;
int max_size_;
std::mutex m_;
std::condition_variable cv_;
public:
SafeVector(int size, int max_size) : size_(size), max_size_(max_size) {
assert(size_ <= max_size_);
for (size_t i = 0; i < size; ++i) {
pool_.push_back(new pqxx::connection("some conn string"));
}
}
SafeVector(SafeVector const&)=delete; // to be implemented
SafeVector& operator=(SafeVector const&)=delete; // no assignment keeps things simple
std::shared_ptr<pqxx::connection> borrow() {
std::unique_lock<std::mutex> l(m_);
cv_.wait(l, [this]{ return !pool_.empty(); });
std::shared_ptr<pqxx::connection> res(pool_.back());
pool_.pop_back();
return res;
}
void surrender(std::shared_ptr<pqxx::connection> connection) {
std::lock_guard<std::mutex> l(m_);
pool_.push_back(connection.get());
cv_.notify_all();
}
};
在 main 中,然后我将 SafeVector* s = new SafeVector(4, 10);
传递到我的服务中 ServiceA(s)
里面ServiceA
,我使用连接如下:
std::shared_ptr<pqxx::connection> c = safeVector_->borrow();
c->perform(SomeTransactorImpl);
safeVector_->surrender(c);
我到处放了一堆日志语句,我很确定我对 (1) shared_ptr 或 (2) 各种锁定结构的核心概念存在根本性的误解。
特别是,似乎在使用 4 个连接后(我机器上的最大硬件线程数),尝试 return [=] 中的连接时发生段错误(错误 11) 16=]方法。
如有任何帮助,我们将不胜感激。谢谢。
C++ 中的智能指针与对象所有权有关。
对象所有权是关于谁有权删除对象以及何时删除对象。
共享指针意味着谁可以删除以及何时删除是一个共同的问题。一旦说出"no one bit of code is permitted to delete this object",就无法收回
在您的代码中,您尝试获取一个具有共享所有权的对象并为您的 SafeVector
投降。这是不允许的。您无论如何都可以尝试调用 .get()
,但删除该对象的权利仍归共享指针所有。
他们继续删除它(也许马上,也许明天)并且您的容器有一个指向已删除对象的悬空指针。
将您的共享点数更改为唯一点数。根据需要添加移动以使其编译。
投降,断言提供的唯一指针非空。
当你在里面的时候,
cv_.notify_one();
我也会
std::vector<std::unique_ptr<pqxx::connection>> pool_;
并更改:
pool_.push_back(std::move(connection));
如果您不更新 pool_
的类型,而是将 .get()
更改为 .release()
。与shared ptr不同,unique ptr可以放弃所有权。
我正在尝试了解并发性,我正在 grpc 服务中实现一个小型连接池,该服务需要与 postgres 数据库建立许多连接。
我正在尝试实现一个基本的 connectionPool 以防止为每个请求创建一个新连接。首先,我尝试创建一个线程安全 std::vector
。当我 运行 grpc 服务器时,进行了单个事务,然后服务器阻塞,但我无法推断出发生了什么。任何帮助将不胜感激
class SafeVector {
std::vector<pqxx::connection*> pool_;
int size_;
int max_size_;
std::mutex m_;
std::condition_variable cv_;
public:
SafeVector(int size, int max_size) : size_(size), max_size_(max_size) {
assert(size_ <= max_size_);
for (size_t i = 0; i < size; ++i) {
pool_.push_back(new pqxx::connection("some conn string"));
}
}
SafeVector(SafeVector const&)=delete; // to be implemented
SafeVector& operator=(SafeVector const&)=delete; // no assignment keeps things simple
std::shared_ptr<pqxx::connection> borrow() {
std::unique_lock<std::mutex> l(m_);
cv_.wait(l, [this]{ return !pool_.empty(); });
std::shared_ptr<pqxx::connection> res(pool_.back());
pool_.pop_back();
return res;
}
void surrender(std::shared_ptr<pqxx::connection> connection) {
std::lock_guard<std::mutex> l(m_);
pool_.push_back(connection.get());
cv_.notify_all();
}
};
在 main 中,然后我将 SafeVector* s = new SafeVector(4, 10);
传递到我的服务中 ServiceA(s)
里面ServiceA
,我使用连接如下:
std::shared_ptr<pqxx::connection> c = safeVector_->borrow();
c->perform(SomeTransactorImpl);
safeVector_->surrender(c);
我到处放了一堆日志语句,我很确定我对 (1) shared_ptr 或 (2) 各种锁定结构的核心概念存在根本性的误解。
特别是,似乎在使用 4 个连接后(我机器上的最大硬件线程数),尝试 return [=] 中的连接时发生段错误(错误 11) 16=]方法。
如有任何帮助,我们将不胜感激。谢谢。
C++ 中的智能指针与对象所有权有关。
对象所有权是关于谁有权删除对象以及何时删除对象。
共享指针意味着谁可以删除以及何时删除是一个共同的问题。一旦说出"no one bit of code is permitted to delete this object",就无法收回
在您的代码中,您尝试获取一个具有共享所有权的对象并为您的 SafeVector
投降。这是不允许的。您无论如何都可以尝试调用 .get()
,但删除该对象的权利仍归共享指针所有。
他们继续删除它(也许马上,也许明天)并且您的容器有一个指向已删除对象的悬空指针。
将您的共享点数更改为唯一点数。根据需要添加移动以使其编译。
投降,断言提供的唯一指针非空。
当你在里面的时候,
cv_.notify_one();
我也会
std::vector<std::unique_ptr<pqxx::connection>> pool_;
并更改:
pool_.push_back(std::move(connection));
如果您不更新 pool_
的类型,而是将 .get()
更改为 .release()
。与shared ptr不同,unique ptr可以放弃所有权。