mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2025-06-07 16:55:23 +02:00
DCCQueue memory leak fix
This commit is contained in:
parent
4cb09e11a5
commit
f163e171e4
53
DCCQueue.cpp
53
DCCQueue.cpp
@ -62,6 +62,21 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
recycleList=p;
|
recycleList=p;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DCCQueue::remove(PendingSlot* premove) {
|
||||||
|
PendingSlot* previous=nullptr;
|
||||||
|
for (auto p=head;p;previous=p,p=p->next) {
|
||||||
|
if (p==premove) {
|
||||||
|
// remove this slot from the queue
|
||||||
|
if (previous) previous->next=p->next;
|
||||||
|
else head=p->next;
|
||||||
|
if (p==tail) tail=previous; // if last packet, update tail
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DIAG(F("DCCQueue::remove slot not found"));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// Packet joins end of low priority queue.
|
// Packet joins end of low priority queue.
|
||||||
void DCCQueue::scheduleDCCPacket(byte* packet, byte length, byte repeats, uint16_t loco) {
|
void DCCQueue::scheduleDCCPacket(byte* packet, byte length, byte repeats, uint16_t loco) {
|
||||||
lowPriorityQueue->addQueue(getSlot(NORMAL_PACKET,packet,length,repeats,loco));
|
lowPriorityQueue->addQueue(getSlot(NORMAL_PACKET,packet,length,repeats,loco));
|
||||||
@ -73,10 +88,6 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
for (auto p=highPriorityQueue->head;p;p=p->next) {
|
for (auto p=highPriorityQueue->head;p;p=p->next) {
|
||||||
if (p->locoId==loco) {
|
if (p->locoId==loco) {
|
||||||
// replace existing packet
|
// replace existing packet
|
||||||
if (length>sizeof(p->packet)) {
|
|
||||||
DIAG(F("DCC bad packet length=%d"),length);
|
|
||||||
length=sizeof(p->packet); // limit to size of packet
|
|
||||||
}
|
|
||||||
memcpy(p->packet,packet,length);
|
memcpy(p->packet,packet,length);
|
||||||
p->packetLength=length;
|
p->packetLength=length;
|
||||||
p->packetRepeat=repeats;
|
p->packetRepeat=repeats;
|
||||||
@ -98,22 +109,13 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
|
|
||||||
// kill any existing throttle packets for this loco (or all locos if broadcast)
|
// kill any existing throttle packets for this loco (or all locos if broadcast)
|
||||||
// this will also remove any estop packets for this loco (or all locos if broadcast) but they will be replaced
|
// this will also remove any estop packets for this loco (or all locos if broadcast) but they will be replaced
|
||||||
PendingSlot * previous=nullptr;
|
PendingSlot * pNext;
|
||||||
auto p=highPriorityQueue->head;
|
for (auto p=highPriorityQueue->head;p;p=pNext) {
|
||||||
while(p) {
|
auto pNext=p->next; // save next packet in case we recycle this one
|
||||||
if (p->type!=ACC_OFF_PACKET && (loco==0 || p->locoId==loco)) {
|
if (p->type!=ACC_OFF_PACKET && (loco==0 || p->locoId==loco)) {
|
||||||
// drop this packet from the highPriority queue
|
// remove this slot from the queue or it will interfere with our ESTOP
|
||||||
if (previous) previous->next=p->next;
|
highPriorityQueue->remove(p);
|
||||||
else highPriorityQueue->head=p->next;
|
|
||||||
|
|
||||||
recycle(p); // recycle this slot
|
recycle(p); // recycle this slot
|
||||||
|
|
||||||
// address next packet
|
|
||||||
p=previous?previous->next : highPriorityQueue->head;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
previous=p;
|
|
||||||
p=p->next;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add the estop packet to the start of the queue
|
// add the estop packet to the start of the queue
|
||||||
@ -149,8 +151,8 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DCCQueue::scheduleNextInternal() {
|
bool DCCQueue::scheduleNextInternal() {
|
||||||
PendingSlot* previous=nullptr;
|
|
||||||
for (auto p=head;p;previous=p,p=p->next) {
|
for (auto p=head;p;p=p->next) {
|
||||||
// skip over pending ACC_OFF packets which are still delayed
|
// skip over pending ACC_OFF packets which are still delayed
|
||||||
if (p->type == ACC_OFF_PACKET && millis()<p->startTime) continue;
|
if (p->type == ACC_OFF_PACKET && millis()<p->startTime) continue;
|
||||||
if (p->locoId) {
|
if (p->locoId) {
|
||||||
@ -171,9 +173,7 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
}
|
}
|
||||||
|
|
||||||
// remove this slot from the queue
|
// remove this slot from the queue
|
||||||
if (previous) previous->next=p->next;
|
remove(p);
|
||||||
else head=p->next;
|
|
||||||
if (!head) tail=nullptr;
|
|
||||||
|
|
||||||
// special cases handling
|
// special cases handling
|
||||||
if (p->type == ACC_ON_PACKET) {
|
if (p->type == ACC_ON_PACKET) {
|
||||||
@ -182,11 +182,8 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
p->packet[1] &= ~0x08; // set C to 0 (gate off)
|
p->packet[1] &= ~0x08; // set C to 0 (gate off)
|
||||||
p->startTime=millis()+p->delayOff;
|
p->startTime=millis()+p->delayOff;
|
||||||
highPriorityQueue->jumpQueue(p);
|
highPriorityQueue->jumpQueue(p);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
else recycle(p);
|
||||||
// Recycle packet just consumed
|
|
||||||
recycle(p);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -209,7 +206,7 @@ uint16_t DCCQueue::lastSentPacketLocoId=0; // used to prevent two packets to the
|
|||||||
for (auto p=lowPriorityQueue->head;p;p=p->next) q2++;
|
for (auto p=lowPriorityQueue->head;p;p=p->next) q2++;
|
||||||
bool leak=(q1+q2)!=created;
|
bool leak=(q1+q2)!=created;
|
||||||
DIAG(F("New DCC queue slot type=%d length=%d loco=%d q1=%d q2=%d created=%d"),
|
DIAG(F("New DCC queue slot type=%d length=%d loco=%d q1=%d q2=%d created=%d"),
|
||||||
type,length,loco,q1,q2, created);
|
(int16_t)type,length,loco,q1,q2, created);
|
||||||
if (leak) {
|
if (leak) {
|
||||||
for (auto p=highPriorityQueue->head;p;p=p->next) DIAG(F("q1 %d %d"),p->type,p->locoId);
|
for (auto p=highPriorityQueue->head;p;p=p->next) DIAG(F("q1 %d %d"),p->type,p->locoId);
|
||||||
for (auto p=lowPriorityQueue->head;p;p=p->next) DIAG(F("q2 %d %d"),p->type,p->locoId);
|
for (auto p=lowPriorityQueue->head;p;p=p->next) DIAG(F("q2 %d %d"),p->type,p->locoId);
|
||||||
|
@ -78,6 +78,6 @@ class DCCQueue {
|
|||||||
static void recycle(PendingSlot* p);
|
static void recycle(PendingSlot* p);
|
||||||
void addQueue(PendingSlot * p);
|
void addQueue(PendingSlot * p);
|
||||||
void jumpQueue(PendingSlot * p);
|
void jumpQueue(PendingSlot * p);
|
||||||
|
void remove(PendingSlot * p);
|
||||||
};
|
};
|
||||||
#endif
|
#endif // DCCQueue_h
|
||||||
|
@ -3,7 +3,8 @@
|
|||||||
|
|
||||||
#include "StringFormatter.h"
|
#include "StringFormatter.h"
|
||||||
|
|
||||||
#define VERSION "5.5.27"
|
#define VERSION "5.5.28"
|
||||||
|
// 5.5.28 - DCC Queue memory leak fix
|
||||||
// 5.5.27 - PCF8574 output pin initialization parameter
|
// 5.5.27 - PCF8574 output pin initialization parameter
|
||||||
// 5.5.26 - PCA9554 and TCA9554/9534 I2C 8-bit GPIO expander drivers
|
// 5.5.26 - PCA9554 and TCA9554/9534 I2C 8-bit GPIO expander drivers
|
||||||
// 5.2.25 - IO_Bitmap and assicated Exrail macros
|
// 5.2.25 - IO_Bitmap and assicated Exrail macros
|
||||||
|
Loading…
x
Reference in New Issue
Block a user