Я пытаюсь реализовать неблокирующую последовательную связь в моем приложении C ++ .Поток отвечает за последовательную связь, и я написал ThreadSafeClass
для обмена данными между последовательным потоком и основным потоком.Вот ядро моего кода:
main.cpp
#include "serial.hpp"
#include "tsqueue.hpp"
int main(int argc, char *argv[])
{
serial::init();
while (true)
{
fgets(s);
serial::outQueue.enqueue(std::string(s));
}
serial::shutdown();
return 0;
}
tsqueue.hpp
#include <mutex>
#include <queue>
namespace tsqueue
{
template <typename T>
class ThreadSafeQueue
{
private:
mutable std::mutex _mtx;
std::queue<T> _que;
public:
ThreadSafeQueue();
~ThreadSafeQueue();
void enqueue(const T &item);
T tryDequeue(const T &defaultValue, bool &done);
void clear();
bool isEmpty() const;
};
template <typename T>
ThreadSafeQueue<T>::ThreadSafeQueue() {}
template <typename T>
ThreadSafeQueue<T>::~ThreadSafeQueue() { clear(); }
template <typename T>
void tsqueue::ThreadSafeQueue<T>::enqueue(const T &item)
{
std::lock_guard<std::mutex> lock(_mtx);
_que.push(item);
}
template <typename T>
T tsqueue::ThreadSafeQueue<T>::tryDequeue(const T &defaultValue, bool &done)
{
std::lock_guard<std::mutex> lock(_mtx);
if (_que.empty())
{
done = false;
return defaultValue;
}
else
{
T item = _que.front();
_que.pop();
done = true;
return item;
}
}
} // namespace tsqueue
И серийное объявление / определение,
serial.hpp
#include <string>
#include "tsqueue.hpp"
namespace serial
{
static tsqueue::ThreadSafeQueue<std::string> inQueue;
static tsqueue::ThreadSafeQueue<std::string> outQueue;
void init();
void shutdown();
}
serial.cpp
#include <string>
#include "serial.hpp"
#include "tsqueue.hpp"
static std::thread _thread;
void run()
{
while (true)
{
std::string str = serial::outQueue.tryDequeue(emptyStr, dequeued);
if (dequeued) { /* Do send 'str' */ }
if (terminationRequested) { break; }
// Some sleep
}
}
void serial::init()
{
serial::inQueue.clear();
serial::outQueue.clear();
_thread = std::thread(run);
}
void serial::shutdown()
{
if (_thread.joinable()) { _thread.join(); }
}
Проблемаэто когда tryDequeue(...)
вызывается последовательным потоком run()
в serial.cpp , он всегда видит пустой outQueue
.Однако , в то время как цикл все еще видит outQueue
в main.cpp с предоставленными данными, даже в более поздние времена.Я узнал, что с помощью инструментов отладки vscode.Я новичок в C ++, но опыт работы на других языках.Что я делаю не так в приведенном выше коде?run()
и main()
видят разные объекты?
Компилятор: g ++ 7.3.0, Среда: Linux (Ubuntu 18.04)
Редактировать : Если я удаляю static
из определений inQueue
и outQueue
, я получаю multiple definition
ошибку компоновщика для обоих.Хотя у меня есть подходящие охранники.