我正在用C ++编程,目的是在虚幻引擎4和我的服务器之间提供一些客户端/服务器通信。
我需要一个日志记录系统,但当前系统消息会泛滥。 所以我创建了一个带有ofstream对象的Logger类,我将其文件<< “写信息。” << ENDL。
问题是每个对象都会生成ofstream的另一个实例,并且对文件的几次更长时间的写入会被更新的写入切断。
我正在寻找一种排队写入文件的方法,这个系统/功能/流很容易包含和调用。
奖励积分:每当我尝试编写std :: string和Fstring时,ofstream似乎都会抱怨:|
答案 0 :(得分:1)
答案 1 :(得分:0)
ofstream不能跨多个线程使用。它需要使用互斥锁或类似对象进行同步。请查看以下主题以获取详细信息:ofstream shared by mutiple threads - crashes after awhile
答案 2 :(得分:0)
我写了一个快速的例子,说明如何实现这样的东西。请记住,这可能不是最终解决方案,仍然需要额外的错误检查等等......
#include <concurrent_queue.h>
#include <string>
#include <thread>
#include <fstream>
#include <future>
class Message
{
public:
Message() : text_(), sender_(), quit_(true)
{}
Message(std::string text, std::thread::id sender)
: text_(std::move(text)), sender_(sender), quit_(false)
{}
bool isQuit() const { return quit_; }
std::string getText() const { return text_; }
std::thread::id getSender() const { return sender_; }
private:
bool quit_;
std::string text_;
std::thread::id sender_;
};
class Log
{
public:
Log(const std::string& fileName)
: workerThread_(&Log::threadFn, this, fileName)
{}
~Log()
{
queue_.push(Message()); // push quit message
workerThread_.join();
}
void write(std::string text)
{
queue_.push(Message(std::move(text), std::this_thread::get_id()));
}
private:
static void threadFn(Log* log, std::string fileName)
{
std::ofstream out;
out.open(fileName, std::ios::out);
assert(out.is_open());
// Todo: ... some error checking here
Message msg;
while(true)
{
if(log->queue_.try_pop(msg))
{
if(msg.isQuit())
break;
out << msg.getText() << std::endl;
}
else
{
std::this_thread::yield();
}
}
}
concurrency::concurrent_queue<Message> queue_;
std::thread workerThread_;
};
int main(int argc, char* argv[])
{
Log log("test.txt");
Log* pLog = &log;
auto fun = [pLog]()
{
for(int i = 0; i < 100; ++i)
pLog->write(std::to_string(i));
};
// start some test threads
auto f0 = std::async(fun);
auto f1 = std::async(fun);
auto f2 = std::async(fun);
auto f3 = std::async(fun);
// wait for all
f0.get();
f1.get();
f2.get();
f3.get();
return 0;
}
主要思想是使用一个具有线程安全write()方法的Log类,该方法可以同时从多个线程调用。 Log类使用工作线程将所有文件访问权限放到另一个线程。它使用线程安全(可能是无锁)数据结构将所有消息从发送线程传输到工作线程(我在这里使用concurrent_queue - 但也有其他消息)。使用一个小的Message包装器,告诉工作线程关闭非常简单。然后加入它,一切都很好。 只要可能写入的任何线程仍在运行,就必须确保不销毁日志。