Conveyor::Conveyor(){
gc_pending = queue.tail_i;
running = false;
+ flush = false;
+ halted= false;
}
void Conveyor::on_module_loaded(){
register_for_event(ON_IDLE);
register_for_event(ON_MAIN_LOOP);
+ register_for_event(ON_HALT);
on_config_reload(this);
}
+void Conveyor::on_halt(void* argument){
+ if(argument == nullptr) {
+ halted= true;
+ flush_queue();
+ }else{
+ halted= false;
+ }
+}
+
// Delete blocks here, because they can't be deleted in interrupt context ( see Block.cpp:release )
// note that blocks get cleaned as they come off the tail, so head ALWAYS points to a cleaned block.
void Conveyor::on_idle(void* argument){
if (queue.tail_i != gc_pending)
{
- if (queue.is_empty())
+ if (queue.is_empty()) {
__debugbreak();
- else
- {
+ }else{
// Cleanly delete block
Block* block = queue.tail_ref();
// block->debug();
void Conveyor::append_gcode(Gcode* gcode)
{
- gcode->mark_as_taken();
queue.head_ref()->append_gcode(gcode);
}
gc_pending = queue.next(gc_pending);
+ // mark entire queue for GC if flush flag is asserted
+ if (flush){
+ while (gc_pending != queue.head_i) {
+ gc_pending = queue.next(gc_pending);
+ }
+ }
+
// Return if queue is empty
if (gc_pending == queue.head_i)
{
// Wait for the queue to be empty
void Conveyor::wait_for_empty_queue()
{
- while (!queue.is_empty())
- {
+ while (!queue.is_empty()) {
ensure_running();
THEKERNEL->call_event(ON_IDLE, this);
}
*/
void Conveyor::queue_head_block()
{
- while (queue.is_full())
- {
+ // upstream caller will block on this until there is room in the queue
+ while (queue.is_full()) {
ensure_running();
THEKERNEL->call_event(ON_IDLE, this);
}
- queue.head_ref()->ready();
- queue.produce_head();
+ if(halted) {
+ // we do not want to stick more stuff on the queue if we are in halt state
+ // clear and release the block on the head
+ queue.head_ref()->clear();
+
+ }else{
+ queue.head_ref()->ready();
+ queue.produce_head();
+ }
}
void Conveyor::ensure_running()
}
}
+/*
+
+ In most cases this will not totally flush the queue, as when streaming
+ gcode there is one stalled waiting for space in the queue, in
+ queue_head_block() so after this flush, once main_loop runs again one more
+ gcode gets stuck in the queue, this is bad. Current work around is to call
+ this when the queue in not full and streaming has stopped
+
+*/
+
+void Conveyor::flush_queue()
+{
+ flush = true;
+ wait_for_empty_queue();
+ flush = false;
+}
+
// Debug function
void Conveyor::dump_queue()
{