Fix deadlock with Driver::write
Use a spin lock to recheck the queue size until it has room to push.pull/25/head
parent
afda617894
commit
4cd897badd
|
|
@ -45,9 +45,9 @@ bool Driver::write(const std::vector<uint8_t>& bytes) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(writeBlocks) {
|
if(writeBlocks) {
|
||||||
std::unique_lock<std::mutex> lk(writeMutex);
|
|
||||||
if(writeQueue.size_approx() > writeQueueSize)
|
if(writeQueue.size_approx() > writeQueueSize)
|
||||||
writeCV.wait(lk);
|
while(writeQueue.size_approx() > (writeQueueSize * 3 / 4))
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
} else {
|
} else {
|
||||||
if(writeQueue.size_approx() > writeQueueSize) {
|
if(writeQueue.size_approx() > writeQueueSize) {
|
||||||
report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error);
|
report(APIEvent::Type::TransmitBufferFull, APIEvent::Severity::Error);
|
||||||
|
|
|
||||||
|
|
@ -22,10 +22,6 @@ public:
|
||||||
virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0);
|
virtual bool read(std::vector<uint8_t>& bytes, size_t limit = 0);
|
||||||
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
|
virtual bool readWait(std::vector<uint8_t>& bytes, std::chrono::milliseconds timeout = std::chrono::milliseconds(100), size_t limit = 0);
|
||||||
virtual bool write(const std::vector<uint8_t>& bytes);
|
virtual bool write(const std::vector<uint8_t>& bytes);
|
||||||
inline void onWrite() {
|
|
||||||
if(writeQueue.size_approx() < (writeQueueSize * 3/4))
|
|
||||||
writeCV.notify_one();
|
|
||||||
}
|
|
||||||
|
|
||||||
device_eventhandler_t report;
|
device_eventhandler_t report;
|
||||||
|
|
||||||
|
|
@ -47,8 +43,6 @@ protected:
|
||||||
virtual void writeTask() = 0;
|
virtual void writeTask() = 0;
|
||||||
moodycamel::BlockingConcurrentQueue<uint8_t> readQueue;
|
moodycamel::BlockingConcurrentQueue<uint8_t> readQueue;
|
||||||
moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue;
|
moodycamel::BlockingConcurrentQueue<WriteOperation> writeQueue;
|
||||||
std::mutex writeMutex;
|
|
||||||
std::condition_variable writeCV;
|
|
||||||
std::thread readThread, writeThread;
|
std::thread readThread, writeThread;
|
||||||
std::atomic<bool> closing{false};
|
std::atomic<bool> closing{false};
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -199,6 +199,5 @@ void FTDI::writeTask() {
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
ftdi.write(writeOp.bytes.data(), (int)writeOp.bytes.size());
|
ftdi.write(writeOp.bytes.data(), (int)writeOp.bytes.size());
|
||||||
onWrite();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -134,6 +134,5 @@ void STM32::writeTask() {
|
||||||
ssize_t actualWritten = ::write(fd, writeOp.bytes.data(), writeSize);
|
ssize_t actualWritten = ::write(fd, writeOp.bytes.data(), writeSize);
|
||||||
if(actualWritten != writeSize)
|
if(actualWritten != writeSize)
|
||||||
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
report(APIEvent::Type::FailedToWrite, APIEvent::Severity::Error);
|
||||||
onWrite();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -297,7 +297,6 @@ void PCAP::writeTask() {
|
||||||
auto bs = sendPacket.getBytestream();
|
auto bs = sendPacket.getBytestream();
|
||||||
if(!closing)
|
if(!closing)
|
||||||
pcap.sendpacket(interface.fp, bs.data(), (int)bs.size());
|
pcap.sendpacket(interface.fp, bs.data(), (int)bs.size());
|
||||||
onWrite();
|
|
||||||
// TODO Handle packet send errors
|
// TODO Handle packet send errors
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -401,8 +401,6 @@ void VCP::writeTask() {
|
||||||
bytesWritten = 0;
|
bytesWritten = 0;
|
||||||
if(WriteFile(handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &overlappedWrite))
|
if(WriteFile(handle, writeOp.bytes.data(), (DWORD)writeOp.bytes.size(), nullptr, &overlappedWrite))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
onWrite();
|
|
||||||
|
|
||||||
auto winerr = GetLastError();
|
auto winerr = GetLastError();
|
||||||
if(winerr == ERROR_IO_PENDING) {
|
if(winerr == ERROR_IO_PENDING) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue