FIFO

Andy Valencia dont at spam.me
Sat May 11 23:44:28 UTC 2024


I need a FIFO for a work scheduler, and nothing suitable jumped 
out at me.  I wrote the following, but as a newbie, would be 
happy to receive any suggestions or observations.  TIA!

/*
  * fifo.d
  *      FIFO data structure
  */
module tiny.fifo;
import std.exception : enforce;

const uint GROWBY = 16;

/*
  * This is a FIFO, with "hd" walking forward and "tl" trailing
  *  behind:
  *            tl              hd /Add here next
  *            v               v
  *  | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7
  *
  * Mildly complicated by a module-size indexing.
  */
struct FIFO(T) {
     T[] items;
     ulong hd, tl, length;

     void
     add(T t) {
         // Make more room when needed
         if (this.items.length == this.length) {
             assert(this.hd == this.tl);

             // Add room and shuffle current contents
             auto olen = this.items.length;
             auto newlen = olen + GROWBY;
             this.items.length = newlen;
             this.tl = (this.tl + GROWBY) % newlen;

             // Shuffle what we're butted up against to their
             //  new position at the top of this.items[]
             ulong moved = olen - this.hd;
             this.items[$ - moved .. $] =
                 this.items[this.hd .. this.hd + moved];
         }

         // Add item at next position
         this.items[hd] = t;
         this.hd = (this.hd + 1) % this.items.length;
         this.length += 1;
     }

     // Give back next
     T
     next() {
         enforce(this.length > 0, "next() from empty FIFO");
         this.length -= 1;
         auto res = this.items[this.tl];
         this.tl = (this.tl + 1) % this.items.length;
         return res;
     }
}

unittest {
     auto f = FIFO!uint();
     f.add(1);
     f.add(2);
     f.add(3);
     assert(f.next() == 1);
     assert(f.next() == 2);
     assert(f.next() == 3);
     assert(f.length == 0);

     // Now overflow several times
     f = FIFO!uint();
     foreach(x; 0 .. GROWBY * 3 + GROWBY/2) {
         f.add(x);
     }
     foreach(x; 0 .. GROWBY * 3 + GROWBY/2) {
         assert(f.next() == x);
     }
     assert(f.length == 0);
}

version(unittest) {
     void
     main()
     {
     }
}


More information about the Digitalmars-d-learn mailing list