diff --git a/xs/src/libslic3r/GCodeSender.cpp b/xs/src/libslic3r/GCodeSender.cpp index bbeaf836d..c3530e00f 100644 --- a/xs/src/libslic3r/GCodeSender.cpp +++ b/xs/src/libslic3r/GCodeSender.cpp @@ -41,6 +41,7 @@ struct termios2 { //#define DEBUG_SERIAL #ifdef DEBUG_SERIAL +#include <cstdlib> #include <fstream> std::fstream fs; #endif @@ -52,7 +53,11 @@ namespace Slic3r { GCodeSender::GCodeSender() : io(), serial(io), can_send(false), sent(0), open(false), error(false), connected(false), queue_paused(false) -{} +{ +#ifdef DEBUG_SERIAL + std::srand(std::time(nullptr)); +#endif +} GCodeSender::~GCodeSender() { @@ -358,15 +363,23 @@ GCodeSender::on_read(const boost::system::error_code& error, // extract the first number from line boost::algorithm::trim_left_if(line, !boost::algorithm::is_digit()); size_t toresend = boost::lexical_cast<size_t>(line.substr(0, line.find_first_not_of("0123456789"))); - ++ toresend; // N is 0-based - if (toresend >= this->sent - this->last_sent.size() && toresend < this->last_sent.size()) { + +#ifdef DEBUG_SERIAL + fs << "!! line num out of sync: toresend = " << toresend << ", sent = " << sent << ", last_sent.size = " << last_sent.size() << std::endl; +#endif + + if (toresend > this->sent - this->last_sent.size() && toresend <= this->sent) { { boost::lock_guard<boost::mutex> l(this->queue_mutex); + const auto lines_to_resend = this->sent - toresend + 1; +#ifdef DEBUG_SERIAL + fs << "!! resending " << lines_to_resend << " lines" << std::endl; +#endif // move the unsent lines to priqueue this->priqueue.insert( this->priqueue.begin(), // insert at the beginning - this->last_sent.begin() + toresend - (this->sent - this->last_sent.size()) - 1, + this->last_sent.begin() + this->last_sent.size() - lines_to_resend, this->last_sent.end() ); @@ -477,8 +490,14 @@ GCodeSender::do_send() if (line.empty()) return; // compute full line - std::string full_line = "N" + boost::lexical_cast<std::string>(this->sent) + " " + line; ++ this->sent; +#ifndef DEBUG_SERIAL + const auto line_num = this->sent; +#else + // In DEBUG_SERIAL mode, test line re-synchronization by sending bad line number 1/4 of the time + const auto line_num = std::rand() < RAND_MAX/4 ? 0 : this->sent; +#endif + std::string full_line = "N" + boost::lexical_cast<std::string>(line_num) + " " + line; // calculate checksum int cs = 0; @@ -497,8 +516,9 @@ GCodeSender::do_send() this->last_sent.push_back(line); this->can_send = false; - if (this->last_sent.size() > KEEP_SENT) - this->last_sent.erase(this->last_sent.begin(), this->last_sent.end() - KEEP_SENT); + while (this->last_sent.size() > KEEP_SENT) { + this->last_sent.pop_front(); + } // we can't supply boost::asio::buffer(full_line) to async_write() because full_line is on the // stack and the buffer would lose its underlying storage causing memory corruption diff --git a/xs/src/libslic3r/GCodeSender.hpp b/xs/src/libslic3r/GCodeSender.hpp index 3022993cb..d7663ca55 100644 --- a/xs/src/libslic3r/GCodeSender.hpp +++ b/xs/src/libslic3r/GCodeSender.hpp @@ -51,7 +51,7 @@ class GCodeSender : private boost::noncopyable { bool can_send; bool queue_paused; size_t sent; - std::vector<std::string> last_sent; + std::deque<std::string> last_sent; // this mutex guards log, T, B mutable boost::mutex log_mutex;