Я делаю программу, используя потоки и общий буфер. Два потока бесконечно работают в фоновом режиме, один поток заполняет общий буфер данными, а другой поток записывает содержимое общего буфера в файл.
Пользователь может запустить или остановить заполнение данных, в результате чего поток переходит в состояние ожидания до тех пор, пока пользователь снова не запустит поток. В каждом цикле буфер заполняется 50 поплавками.
Это код:
#include <iostream>
#include <vector>
#include <iterator>
#include <utility>
#include <fstream>
#include <condition_variable>
#include <mutex>
#include <thread>
using namespace std;
std::mutex m;
std::condition_variable cv;
std::vector<std::vector<float>> datas;
bool keep_running = true, start_running = false;
void writing_thread()
{
ofstream myfile;
bool opn = false;
while(1)
{
while(keep_running)
{
// Open the file only once
if(!opn)
{
myfile.open("IQ_Datas.txt");
opn = true;
}
// Wait until main() sends data
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] {return !datas.empty();});
auto d = std::move(datas);
lk.unlock();
for(auto &entry : d)
{
for(auto &e : entry)
myfile << e << endl;
}
}
if(opn)
{
myfile.close();
opn = false;
}
}
}
void sending_thread()
{
std::vector<float> m_buffer;
int cpt=0;
//Fill the buffer with 50 floats
for(float i=0; i<50; i++)
m_buffer.push_back(i);
while(1)
{
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, [] {return keep_running && start_running;});
}
while(keep_running)
{
//Each loop d is containing 50 floats
std::vector<float> d = m_buffer;
cout << "in3" << endl; //Commenting this line makes the program crash
{
std::lock_guard<std::mutex> lk(m);
if (!keep_running)break;
datas.push_back(std::move(d));
}
cv.notify_one();
cpt++;
}
cout << "Total data: " << cpt*50 << endl;
cpt = 0;
}
}
void start()
{
{
std::unique_lock<std::mutex> lk(m);
start_running = true;
}
cv.notify_all();
}
void stop()
{
{
std::unique_lock<std::mutex> lk(m);
start_running = false;
}
cv.notify_all();
}
int main()
{
int go = 0;
thread t1(sending_thread);
thread t2(writing_thread);
t1.detach();
t2.detach();
while(1)
{
std::cin >> go;
if(go == 1)
{
start();
keep_running = true;
}
else if(go == 0)
{
stop();
keep_running = false;
}
}
return 0;
}
У меня есть 2 проблемы с этим кодом:
При комментировании строки
cout << "in3" << endl;
программа вылетает через ~20-40 секунд с сообщением об ошибке: вызывается завершение после создания экземпляра 'std::bad_alloc' what(): std::bad_alloc. Если я позволю cout, программа будет работать без проблем.Когда программа работает, после остановки
sending_thread
я отображаю общий объем данных, которые были скопированы с помощьюcout << "Total data: " << cpt*50 << endl;
. При небольшом объеме данных все они правильно записываются в файл, но при большом объеме данные отсутствуют. Отсутствуют/правильные данные (Общее количество строк в файле не соответствуетtotal data
)
Почему с cout программа работает правильно? И что является причиной отсутствия данных? Это потому, что sending_thread
слишком быстро заполняет буфер, а writing_thread
занимает слишком много времени для записи в файл?
EDIT: некоторые уточнения, добавление большего количества cout в sending_thread
seems, чтобы исправить все проблемы. Первый поток произвел 21 миллион чисел с плавающей запятой, а второй поток успешно записал в файл 21 миллион чисел с плавающей запятой. Кажется, что без cout потоки-производители работают слишком быстро, чтобы поток-потребитель мог продолжать извлекать данные из общего буфера при записи их в файл.