我正在优化 C++ 代码,并且遇到析构函数调用需要花费大量时间的情况。
然后我为了好玩而编写了这个小类,只是为了看看我是否可以简单地将破坏转移到另一个线程,它实际上似乎有效。
我对此代码有一些疑问:
#pragma once
#include <queue>
#include <mutex>
#include <memory>
#include <functional>
namespace test {
class Cleaner {
struct State {
std::queue<std::shared_ptr<void>> queue;
std::mutex mtx;
std::condition_variable condition;
bool cancelled;
bool done;
};
public:
Cleaner()
:
_state(std::make_shared<State>()),
_thread(&runCleanerloop, _state)
{
}
~Cleaner() {
{
std::lock_guard<std::mutex> lock(_state->mtx);
_state->done = true;
}
_state->condition.notify_all();
_thread.join();
}
template <typename T>
void run(std::shared_ptr<T>& data) {
{
std::lock_guard<std::mutex> lock(_state->mtx);
// Push a copy to the queue to be released by the thread.
_state->queue.push(data);
// Reset the input in the caller's thread.
data.reset();
}
_state->condition.notify_all();
}
static void runCleanerloop(
const std::shared_ptr<State>& state
) {
std::shared_ptr<void> data;
bool done = false;
while (true) {
// Wait for data to appear in queue.
{
std::unique_lock<std::mutex> lock(state->mtx);
state->condition.wait(lock, [&state] {
return state->cancelled || state->queue.size() || state->done;
});
if (state->cancelled || (!state->queue.size() && state->done)) {
done = true;
}
else {
data = state->queue.front();
state->queue.pop();
}
}
state->condition.notify_all();
if (done) {
return;
}
// Release the data inside this thread.
data.reset();
}
}
private:
std::shared_ptr<State> _state;
std::thread _thread;
};
}
预期用途:
#include "cleaner.h"
void test() {
Cleaner cleaner;
std::shared_ptr<Data> current_data;
while (true) {
current_data = createData();
/* Do something */
// This will reset the current_data ptr, but the actual destructor-call
// will be done inside the Cleaner thread.
cleaner.run(current_data);
}
}
这不是对原帖中问题的回答,只是想提一下:
在考虑使用这些奇怪的模式来转移数据所有权之前,您应该首先考虑设计一个合适的内存管理系统,这样您就不需要在每个循环上重新分配数据。
此外,如果你有另一个shared_ptr保持数据活动,线程将不会破坏任何数据,因为引用计数没有达到0。