reorder.cpp

Sometimes you get a packet that you'd rather deal with later. This can happen for a number of reasons; an example could be if you are expecting an ordered sequence of packets, but (for whatever reason) occasionally packets arrive out of order. If the out-of-order packet could just be stored temporarily, until the missing packets ahead of it had arrived, then everything could be handled smoothly.

The Memory object and the SFBMemory::remember(const u8*) function provide such an ability, as illustrated here. If room is available, Memory.remember(packet) makes a copy of its packet argument, stores that copy internally, and arranges for reflexes to be triggered on the copy some time in the future (between loop() calls, typically). (Like one's own unconscious memory, perhaps) there's no particular timing or ordering guarantees about when remembered packets will be recalled.

As an illustration, this sketch sends out packets containing steadily increasing counts, but occasionally sends packets out of order. When the reflex handler detects a jump in the sequence, it simply remembers the out-of-order packet(s), and reacts to them again later (when hopefully all the missing prior pieces have arrived.

In this output sequence, the sketch has been running a while, and is now outputting sequence numbers in the 90's, when another board is detected, at its sequence 4:

s91
Ln 68.000 (Re)starting at 4
Ln 68.001 Sequence 4
s92
Ln 69.001 Sequence 5
s93
Ln 70.002 Sequence 6
s94
Ln 71.005 Sequence 7
Ln 71.021 Sequence 8
Ln 71.041 Sequence 9
s95
Ln 72.004 Sequence 10
s96
Ln 73.008 Sequence 11
Ln 73.061 Sequence 12
s97
Ln 73.121 Sequence 13
Ln 73.141 Sequence 14
Ln 73.161 Sequence 15
Ln 74.006 Sequence 16
s98
Ln 75.007 Sequence 17
s99
Ln 76.008 Sequence 18
s100
Ln 77.009 Sequence 19
s103
s102
s101
Ln 78.012 Sequence 20

This output and timing suggests that several runs of 's' packets (7-9, 11-12, 13-16) arrived out of order and were temporarily remembered, so the sequence outputs continue in order. (And note our 's103'-'s101' being sent out of order, as well.)

// Use Memory.remember(u8*) to reorder out-of-sequence packets

u32 lastSequence = 0;           // Last sequence# received in order
void handleS(u8 * packet) {
  u32 sequence;
  if (packetScanf(packet,"s%d\n",&sequence) != 3) return; // Analyze input, ignore bad packets

  if (lastSequence == 0 || sequence-lastSequence > 5) {   // If just starting, or we're way off
    lastSequence = sequence-1;                            // Reset
    logNormal("(Re)starting at %d\n",sequence);           // and announce that
  }

  if (lastSequence+1 < sequence)     // If packet is out of order,
    Memory.remember(packet);         // just remember it for later..
  else {                             // Else it's what we want..
    lastSequence = sequence;         // So advance
    logNormal("Sequence %d\n",lastSequence); // and report it
  }
}

void setup() {
  Body.reflex('s',handleS);     // Set up reflex
}

u32 loops = 0;            // Last sequence# we sent out
void loop() {
  if (random(10)!=0)      // 90% of the time, just issue next sequence #
    pprintf("s%d\n",++loops);
  else {                  // but 10% of the time, issue a few backwards..
    u32 incr = random(4)+2;     // incr=2..5
    loops += incr;
    for (u32 i = 0; i < incr; ++i)
      pprintf("s%d\n",loops-i);
  }
  ledToggle(BODY_RGB_RED_PIN);  // Show a heartbeat.
  delay(1000);            // Wait a second
}

Generated on Fri Apr 22 06:54:11 2011 for SFB by doxygen 1.5.9