Reputation: 23
I'm trying to do a function that reads information from a file into a queue and then another function that reads the information from the queue to a file. Both functions are enabled by threads. The problem is that the first function does not store the information correctly and I do not know why? can anyone help me? This is the code:
void MessagesSender::saveMessages()
{
std::string line = "";
std::ifstream file(FILE_TO_READ);
if (file.is_open())
{
while (std::getline(file, line))
{
mutReadToFile.lock();
this->message.push(line);
mutReadToFile.unlock();
}
file.close();
}
else
{
std::cout << "Faild" << std::endl;
}
std::ofstream removeFile(FILE_TO_READ, std::ofstream::out | std::ofstream::trunc); //to delete the file
std::cout << "wait a minute..." << std::endl;
//std::this_thread::sleep_for(std::chrono::seconds(60));
}
and the other function:
void MessagesSender::sendMessages()
{
std::ofstream file;
std::vector<std::string> connectUsers;
connectUsers = this->getConnectUsers();
file.open(FILE_TO_WRITE, std::ios::app);
if (file.is_open())
{
while (!this->message.empty())
{
for (int i = 0; i < connectUsers.size(); i++)
{
file << connectUsers[i] << ": " << this->message.front() << std::endl;
}
mutReadToFile.lock();
this->message.pop();
mutReadToFile.unlock();
}
file.close();
std::cout << "Copy successfully" << std::endl;
}
else //If the file doesn't open
{
std::cout << "faild :(" << std::endl;;
}
}
this is the menu:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
read.join();
write.join();
system("pause");
return 0;
}
Upvotes: 1
Views: 55
Reputation: 392863
Your threads use copies of the MessagesSender.
std::thread read(&MessagesSender::saveMessages, mess);
std::thread write(&MessagesSender::sendMessages, mess);
These bind by value. Use std::ref
to prevent copying mess
:
std::thread read(&MessagesSender::saveMessages, std::ref(mess));
std::thread write(&MessagesSender::sendMessages, std::ref(mess));
Alternatively, use pointers:
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
As always, let me add a live demo.
It also
std::remove
it?)There are "bigger" functional issues:
I might be forgetting some
#include <fstream>
#include <iostream>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
static const std::string FILE_TO_READ = "input.txt";
static const std::string FILE_TO_WRITE = "output.txt";
struct MessagesSender {
std::mutex _queueMutex;
std::vector<std::string> getConnectUsers() {
return { "john", "alice", "bob" };
}
void printMenu() { std::cout << "I don't know what's for dinner\n"; }
void sendMessages();
void saveMessages();
std::queue<std::string> _messages;
};
void MessagesSender::saveMessages()
{
std::string line;
{
std::ifstream file(FILE_TO_READ);
while (std::getline(file, line)) {
std::lock_guard lock(_queueMutex);
_messages.push(line);
}
if (!file.good() && !file.eof()) {
std::cout << "Faild" << std::endl;
}
} // closes file
{
std::ofstream removeFile(FILE_TO_READ, std::ios::trunc); // to empty the file
}
std::cout << "Input closed" << std::endl;
}
// and the other function:
void MessagesSender::sendMessages()
{
std::ofstream file(FILE_TO_WRITE, std::ios::app);
if (!file) {
std::cout << "faild :(" << std::endl;
return;
}
auto const connectUsers = MessagesSender::getConnectUsers();
std::unique_lock<std::mutex> lock(_queueMutex);
while (!_messages.empty())
{
auto current = _messages.front();
_messages.pop();
lock.unlock();
for (const auto& user : connectUsers) {
file << user << ": " << current << std::endl;
}
lock.lock();
}
std::cout << "Copy successfully" << std::endl;
}
// this is the menu:
int main()
{
MessagesSender mess;
mess.printMenu();
std::thread read(&MessagesSender::saveMessages, &mess);
std::thread write(&MessagesSender::sendMessages, &mess);
read.join();
write.join();
}
Upvotes: 1