c++ - 带有可变参数模板的 std::lock_guard
问题描述
[无需点击链接即可理解问题]。
我在这个答案中结合了单例模式的实现,以及另一个答案的同步文件写入。
然后我想看看 的接口是否SynchronizedFile
可以提供可变参数模板化write
方法,但我不知道如何将其与std::lock_guard
.
下面是一个非工作示例。在这种情况下,它不起作用,因为(我认为)两个线程设法以i_buf
非同步方式将内容泵入缓冲区,从而导致LOGFILE.txt
.
如果我把std::lock_guard
通用模板放在里面,write
那么程序就不会停止。
#include <iostream>
#include <mutex>
#include <sstream>
#include <fstream>
#include <string>
#include <memory>
#include <thread>
static const int N_LOOP_LENGTH{10};
// This class manages a log file and provides write method(s)
// that allow passing a variable number of parameters of different
// types to be written to the file in a line and separated by commas.
class SynchronizedFile {
public:
static SynchronizedFile& getInstance()
{
static SynchronizedFile instance;
return instance;
}
private:
std::ostringstream i_buf;
std::ofstream i_fout;
std::mutex _writerMutex;
SynchronizedFile () {
i_fout.open("LOGFILE.txt", std::ofstream::out);
}
public:
SynchronizedFile(SynchronizedFile const&) = delete;
void operator=(SynchronizedFile const&) = delete;
template<typename First, typename... Rest>
void write(First param1, Rest...param)
{
i_buf << param1 << ", ";
write(param...);
}
void write()
{
std::lock_guard<std::mutex> lock(_writerMutex);
i_fout << i_buf.str() << std::endl;
i_buf.str("");
i_buf.clear();
}
};
// This is just some class that is using the SynchronizedFile class
// to write stuff to the log file.
class Writer {
public:
Writer (SynchronizedFile& sf, const std::string& prefix)
: syncedFile(sf), prefix(prefix) {}
void someFunctionThatWritesToFile () {
syncedFile.write(prefix, "AAAAA", 4343, "BBBBB", 0.2345435, "GGGGGG");
}
private:
SynchronizedFile& syncedFile;
std::string prefix;
};
void thread_method()
{
SynchronizedFile &my_file1 = SynchronizedFile::getInstance();
Writer writer1(my_file1, "Writer 1:");
for (int i = 0; i < N_LOOP_LENGTH; ++ i)
writer1.someFunctionThatWritesToFile();
}
int main()
{
std::thread t(thread_method);
SynchronizedFile &my_file2 = SynchronizedFile::getInstance();
Writer writer2(my_file2, "Writer 2:");
for (int i = 0; i < N_LOOP_LENGTH; ++i)
writer2.someFunctionThatWritesToFile();
t.join();
std::cout << "Done" << std::endl;
return 0;
}
我怎样才能成功地将这三个想法结合起来?
解决方案
程序死锁是因为write
在持有锁的同时递归调用自身。
在写出数据之后但在调用. E:解锁不起作用,我没有考虑到这一点......std::recursive_mutex
write
E:或者锁定一次,然后使用另一个私有方法进行写入。
template<typename... Args>
void write(Args&&... args)
{
std::unique_lock<std::mutex> lock(_writerMutex);
_write(std::forward<Args>(args)...);
}
template<typename First, typename... Rest>
void _write(First&& param1, Rest&&... param) // private method
{
i_buf << std::forward<First>(param1) << ", ";
_write(std::forward<Rest>(param)...);
}
void _write()
{
i_fout << i_buf.str() << std::endl;
i_buf.clear();
}
推荐阅读
- php - 为所有模型定义禁止的全局 slug
- javascript - 如何解决 Open Api Swagger 中的 TypeError?
- json - Angular 9将json响应映射到数组
- javascript - Javascript:将所有数组合并为一个
- xml - 如何使用 python-docx 在文档中插入 xml?
- reactjs - 尽管使用了所有默认的 create-react-app 配置,Heroku “不是来自 webpack 的内容是从 /app/public 提供的”
- yaml - YAML::TypedBadConversion
NTRTsim 上的 yaml-cpp - c++ - 如何在 VSCode 中查看希腊字母?
- javascript - JS 表单验证,以确保如果没有输入名称,则会出现弹出窗口
- wpf - 如何在操作系统级别更改系统参数?