home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Libraries / GUSI 1.4.1 / GUSI / GUSIBuffer.cp < prev    next >
Encoding:
Text File  |  1994-02-25  |  4.8 KB  |  292 lines  |  [TEXT/MPS ]

  1. /*********************************************************************
  2. Project    :    GUSI                -    Grand Unified Socket Interface
  3. File        :    GUSIBuffer.cp    -    Circular buffers and Scatter/Gather
  4. Author    :    Matthias Neeracher
  5. Language    :    MPW C/C++
  6.  
  7. $Log: GUSIBuffer.cp,v $
  8. Revision 1.1  1994/02/25  02:28:25  neeri
  9. Initial revision
  10.  
  11. Revision 0.4  1993/07/17  00:00:00  neeri
  12. proc -> defproc
  13.  
  14. Revision 0.3  1993/02/10  00:00:00  neeri
  15. The above was incorrect, next attempt
  16.  
  17. Revision 0.2  1992/08/23  00:00:00  neeri
  18. Optimize buffer size for empty buffers
  19.  
  20. Revision 0.1  1992/08/02  00:00:00  neeri
  21. Deferred procedures
  22.  
  23. *********************************************************************/
  24.  
  25. #ifndef GUSI_BUFFER_DEBUG
  26. #define NDEBUG
  27. #endif
  28.  
  29. #include "GUSI_P.h"
  30.  
  31. /**************************** RingBuffer ****************************/
  32.  
  33. #ifndef NDEBUG
  34. int RingDist(Ptr start, Ptr end, Ptr from, Ptr to)
  35. {
  36.     if (from > to)
  37.         return RingDist(start, end, from, end)+RingDist(start, end, start, to);
  38.     else
  39.         return to-from;
  40. }
  41.  
  42. #define RINGEQ(from, to, val)    \
  43.     (RingDist(buffer, endbuf, (from), (to)) == ((val)%(endbuf-buffer)))
  44. #define INVAR                                    \
  45.     (    (free >= 0)                             \
  46.     && (valid >= 0)                             \
  47.     &&    RINGEQ(consume, produce, valid+spare) \
  48.     &&    RINGEQ(produce, consume, free))
  49. #endif
  50.  
  51. RingBuffer::RingBuffer(u_short bufsiz)
  52. {
  53.     buffer    =    NewPtr(bufsiz);
  54.     endbuf    =    buffer+bufsiz;
  55.     consume    =    buffer;
  56.     produce    =    buffer;
  57.     free        =    bufsiz;
  58.     valid        =    0;
  59.     spare        =    0;
  60.     lock        =    false;
  61.     defproc    =    nil;
  62.     
  63.     assert(INVAR);
  64.     assert(endbuf - buffer == bufsiz);
  65. }
  66.  
  67. RingBuffer::~RingBuffer()
  68. {
  69.     Defer();
  70.     if (buffer)
  71.         DisposPtr(buffer);
  72. }
  73.  
  74. Ptr RingBuffer::Producer(long & len)
  75. {
  76.     Defer();
  77.     
  78. #ifndef NDEBUG
  79.     long    oldlen    =    len;
  80. #endif
  81.  
  82.     if (!valid) {
  83.         produce = buffer;
  84.         consume = buffer;
  85.         spare   = 0;
  86.     }
  87.     
  88.     u_short    streak    =    endbuf - produce;
  89.     Ptr        res        =    produce;
  90.     
  91.     if (streak >= free)
  92.         streak = free;
  93.     else if (streak < (free >> 1) && streak < len) {
  94.         spare     =  streak;
  95.         produce    =    buffer;
  96.         free        -=    spare;
  97.         streak    =    free;
  98.         res         =    produce;
  99.     }
  100.     
  101.     if (len > streak)
  102.         len    =    streak;
  103.     
  104.     assert(INVAR);
  105.     assert(len <= oldlen);
  106.     
  107.     Undefer();
  108.     
  109.     return res;
  110. }
  111.  
  112. Ptr RingBuffer::Consumer(long & len)
  113. {
  114.     Defer();
  115.     
  116. #ifndef NDEBUG
  117.     long    oldlen    =    len;
  118. #endif
  119.  
  120.     u_short    streak    =    endbuf - consume - spare;
  121.     Ptr        res        =    consume;
  122.     
  123.     if (streak > valid)
  124.         streak = valid;
  125.     if (len > streak)
  126.         len    =    streak;
  127.     
  128.     assert(INVAR);
  129.     assert(len <= oldlen);
  130.     
  131.     Undefer();
  132.     
  133.     return res;
  134. }
  135.  
  136. void RingBuffer::Validate(long len)
  137. {
  138.     Defer();
  139.     
  140.     valid     += (unsigned short) len;
  141.     free        -=    (unsigned short) len;
  142.     produce    +=    len;
  143.     
  144.     if (produce == endbuf)
  145.         produce    =    buffer;
  146.     
  147.     assert(INVAR);
  148.     
  149.     Undefer();
  150. }
  151.  
  152. void RingBuffer::Invalidate(long len)
  153. {
  154.     Defer();
  155.     
  156.     free         += (unsigned short) len;
  157.     valid        -=    (unsigned short) len;
  158.     consume    +=    len;
  159.     
  160.     if (consume == endbuf-spare) {
  161.         consume    =    buffer;
  162.         spare        =    0;
  163.     } else if (!valid && free == len)    {        // Maximize streak for empty buffer
  164.         consume    =    buffer;
  165.         produce    =    buffer;
  166.     }
  167.     
  168.     assert(INVAR);
  169.     
  170.     Undefer();
  171. }
  172.  
  173. void RingBuffer::Consume(Ptr to, long & len)
  174. {
  175. #ifndef NDEBUG
  176.     Ptr    oldto        =    to;
  177.     long    oldlen    =    len;
  178. #endif
  179.  
  180.     long    part;
  181.     long    rest;
  182.     Ptr    buf;
  183.     
  184.     for (rest = len; (part = rest) && valid; rest -= part)    {
  185.         buf    =    Consumer(part);
  186.         BlockMove(buf, to, part);
  187.         Invalidate(part);
  188.         to        += part;
  189.     }
  190.     
  191.     len    -=    rest;
  192.     
  193.     assert(INVAR);
  194.     assert(len <= oldlen);
  195.     assert(to-oldto == len);
  196. }
  197.  
  198. void RingBuffer::Produce(Ptr from, long & len)
  199. {
  200. #ifndef NDEBUG
  201.     Ptr    oldfrom    =    from;
  202.     long    oldlen    =    len;
  203. #endif
  204.  
  205.     long    part;
  206.     long    rest;
  207.     Ptr    buf;
  208.     
  209.     for (rest = len; (part = rest) && free; rest -= part)    {
  210.         buf    =    Producer(part);
  211.         BlockMove(from, buf, part);
  212.         Validate(part);
  213.         
  214.         from    += part;
  215.     }
  216.     
  217.     len    -=    rest;
  218.     
  219.     assert(INVAR);
  220.     assert(len <= oldlen);
  221.     assert(from-oldfrom == len);
  222. }
  223.  
  224. /************************** Scatter/Gather **************************/
  225.  
  226. ScattGath::ScattGath(const struct iovec *iov, int cnt)    {
  227.     io        =    iov;
  228.     count    =    cnt;
  229.  
  230.     if (count < 1)    {
  231.         buf        =    nil;
  232.         len        =    0;
  233.         scratch    =    nil;
  234.     } else if (count == 1)    {    
  235.         buf        =    (void *) iov->iov_base;
  236.         len        =    (int)    iov->iov_len;
  237.         scratch    =    nil;
  238.     } else {
  239.         for (len = 0; count--; ++iov)
  240.             len += (int) iov->iov_len;
  241.         
  242.         scratch = NewHandle(len);
  243.         
  244.         if (scratch)    {
  245.             HLock(scratch);
  246.             buf    =    (void *) *scratch;
  247.         } else
  248.             buf     =    nil;
  249.     }
  250. }
  251.  
  252. ScattGath::~ScattGath()
  253. {
  254.     if (scratch)
  255.         DisposHandle(scratch);
  256. }
  257.  
  258. Scatterer::Scatterer(const struct iovec *iov, int count) 
  259.     : ScattGath(iov, count)
  260. {
  261. }
  262.  
  263. Scatterer::~Scatterer()
  264. {
  265.     int    sect;
  266.     
  267.     if (count > 1 && buf)
  268.         for (char * bptr = (char *) buf; count-- && len; ++io)    {
  269.             sect    =    min(len, io->iov_len);
  270.             
  271.             memcpy(io->iov_base, bptr, sect);
  272.             
  273.             bptr    +=    sect;
  274.             len     -=    sect;
  275.         }
  276. }
  277.  
  278. Gatherer::Gatherer(const struct iovec *iov, int count) 
  279.     : ScattGath(iov, count)
  280. {
  281.     if (count > 1 && buf)
  282.         for (char * bptr = (char *) buf; count--; ++iov)    {
  283.             memcpy(bptr, iov->iov_base, iov->iov_len);
  284.             
  285.             bptr    +=    iov->iov_len;
  286.         }
  287. }
  288.  
  289. Gatherer::~Gatherer()
  290. {
  291. }
  292.