home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / h / vd2 / system / VDRingBuffer.h < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  6.8 KB  |  302 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    System library component
  3. //    Copyright (C) 1998-2004 Avery Lee, All Rights Reserved.
  4. //
  5. //    Beginning with 1.6.0, the VirtualDub system library is licensed
  6. //    differently than the remainder of VirtualDub.  This particular file is
  7. //    thus licensed as follows (the "zlib" license):
  8. //
  9. //    This software is provided 'as-is', without any express or implied
  10. //    warranty.  In no event will the authors be held liable for any
  11. //    damages arising from the use of this software.
  12. //
  13. //    Permission is granted to anyone to use this software for any purpose,
  14. //    including commercial applications, and to alter it and redistribute it
  15. //    freely, subject to the following restrictions:
  16. //
  17. //    1.    The origin of this software must not be misrepresented; you must
  18. //        not claim that you wrote the original software. If you use this
  19. //        software in a product, an acknowledgment in the product
  20. //        documentation would be appreciated but is not required.
  21. //    2.    Altered source versions must be plainly marked as such, and must
  22. //        not be misrepresented as being the original software.
  23. //    3.    This notice may not be removed or altered from any source
  24. //        distribution.
  25.  
  26. #ifndef f_SYSTEM_VDRINGBUFFER_H
  27. #define f_SYSTEM_VDRINGBUFFER_H
  28.  
  29. #include <string.h>
  30. #include <utility>
  31.  
  32. #include <vd2/system/atomic.h>
  33.  
  34. class VDRingBufferBase {
  35. public:
  36.     VDRingBufferBase()
  37.         : nSize(0)
  38.         , nReadPoint(0)
  39.         , nWritePoint(0)
  40.     {
  41.     }
  42.  
  43.     int         getSize() const { return nSize; }
  44.     int         getReadOffset() const { return nReadPoint; }
  45.     int         getWriteOffset() const { return nWritePoint; }
  46.  
  47. protected:
  48.     int                 nSize;
  49.     int                 nReadPoint;
  50.     int                 nWritePoint;
  51. };
  52.  
  53. template<class T, class Allocator = std::allocator<T> >
  54. class VDRingBuffer : public VDRingBufferBase, private Allocator {
  55. protected:
  56.     T                *pBuffer;
  57.     VDAtomicInt         nLevel;
  58.  
  59. public:
  60.     VDRingBuffer();
  61.     VDRingBuffer(int size);
  62.     ~VDRingBuffer();
  63.  
  64.     void     Init(int size);
  65.     void     Shutdown();
  66.  
  67.     int         getLevel() const { return nLevel; }
  68.     int         getSpace() const { return nSize - nLevel; }
  69.     int         getWriteSpace() const;
  70.     T *         getWritePtr() const { return pBuffer+nWritePoint; }
  71.  
  72.     int         size() const { return nSize; }
  73.     bool     empty() const { return !nLevel; }
  74.     bool     full() const { return nLevel == nSize; }
  75.  
  76.     void     Flush() { nReadPoint = nWritePoint = nLevel = 0; }
  77.  
  78.     int         Read(T *pBuffer, int bytes);
  79.     const T    *LockRead(int requested, int& actual);
  80.     const T    *LockReadAll(int& actual);
  81.     const T *LockReadWrapped(int requested, int& actual, int& nReadPoint);
  82.     const T *LockReadAllWrapped(int& actual, int& nReadPoint);
  83.     int         UnlockRead(int actual);
  84.  
  85.     int         Write(const T *pData, int bytes);
  86.     T        *LockWrite(int requested, int& actual);
  87.     T        *LockWriteAll(int& actual);
  88.     int         UnlockWrite(int actual);
  89. };
  90.  
  91. template<class T, class Allocator>
  92. VDRingBuffer<T, Allocator>::VDRingBuffer(int size)
  93.     : pBuffer(NULL)
  94. {
  95.     Init(size);
  96. }
  97.  
  98. template<class T, class Allocator>
  99. VDRingBuffer<T, Allocator>::VDRingBuffer()
  100.     : pBuffer(NULL)
  101.     , nLevel(0)
  102. {
  103. }
  104.  
  105. template<class T, class Allocator>
  106. VDRingBuffer<T, Allocator>::~VDRingBuffer() {
  107.     Shutdown();
  108. }
  109.  
  110. template<class T, class Allocator>
  111. void VDRingBuffer<T, Allocator>::Init(int size) {
  112.     Shutdown();
  113.     pBuffer        = allocate(nSize = size, 0);
  114.     nLevel        = 0;
  115.     nReadPoint    = 0;
  116.     nWritePoint    = 0;
  117. }
  118.  
  119. template<class T, class Allocator>
  120. void VDRingBuffer<T, Allocator>::Shutdown() {
  121.     if (pBuffer) {
  122.         deallocate(pBuffer, nSize);
  123.         pBuffer = NULL;
  124.     }
  125. }
  126.  
  127. template<class T, class Allocator>
  128. int VDRingBuffer<T, Allocator>::getWriteSpace() const {
  129.     volatile int tc = nSize - nWritePoint;
  130.     volatile int space = nSize - nLevel;
  131.  
  132.     if (tc > space)
  133.         tc = space;
  134.  
  135.     return tc;
  136. }
  137.  
  138. template<class T, class Allocator>
  139. int VDRingBuffer<T, Allocator>::Read(T *pBuffer, int units) {
  140.     VDASSERT(units >= 0);
  141.  
  142.     int actual = 0;
  143.     const T *pSrc;
  144.  
  145.     while(units) {
  146.         int tc;
  147.  
  148.         pSrc = LockRead(units, tc);
  149.  
  150.         if (!tc)
  151.             break;
  152.  
  153.         memcpy(pBuffer, pSrc, tc * sizeof(T));
  154.  
  155.         UnlockRead(tc);
  156.  
  157.         actual += tc;
  158.         units -= tc;
  159.         pBuffer += tc;
  160.     }
  161.  
  162.     return actual;
  163. }
  164.  
  165. template<class T, class Allocator>
  166. const T *VDRingBuffer<T, Allocator>::LockRead(int requested, int& actual) {
  167.     VDASSERT(requested >= 0);
  168.  
  169.     int nLevelNow = nLevel;
  170.  
  171.     if (requested > nLevelNow)
  172.         requested = nLevelNow;
  173.  
  174.     if (requested + nReadPoint > nSize)
  175.         requested = nSize - nReadPoint;
  176.  
  177.     actual = requested;
  178.  
  179.     return pBuffer + nReadPoint;
  180. }
  181.  
  182. template<class T, class Allocator>
  183. const T *VDRingBuffer<T, Allocator>::LockReadAll(int& actual) {
  184.     int requested = nLevel;
  185.  
  186.     if (requested + nReadPoint > nSize)
  187.         requested = nSize - nReadPoint;
  188.  
  189.     actual = requested;
  190.  
  191.     return pBuffer + nReadPoint;
  192. }
  193.  
  194. template<class T, class Allocator>
  195. const T *VDRingBuffer<T, Allocator>::LockReadWrapped(int requested, int& actual, int& readpt) {
  196.     int nLevelNow = nLevel;
  197.  
  198.     if (requested > nLevelNow)
  199.         requested = nLevelNow;
  200.  
  201.     actual = requested;
  202.     readpt = nReadPoint;
  203.  
  204.     return pBuffer;
  205. }
  206.  
  207. template<class T, class Allocator>
  208. const T *VDRingBuffer<T, Allocator>::LockReadAllWrapped(int& actual, int& readpt) {
  209.     int requested = nLevel;
  210.  
  211.     actual = requested;
  212.     readpt = nReadPoint;
  213.  
  214.     return pBuffer;
  215. }
  216.  
  217. template<class T, class Allocator>
  218. int VDRingBuffer<T, Allocator>::UnlockRead(int actual) {
  219.     VDASSERT(actual >= 0);
  220.     VDASSERT(nLevel >= actual);
  221.  
  222.     int newpt = nReadPoint + actual;
  223.  
  224.     if (newpt >= nSize)
  225.         newpt -= nSize;
  226.  
  227.     nReadPoint = newpt;
  228.  
  229.     return nLevel.add(-actual);
  230. }
  231.  
  232. template<class T, class Allocator>
  233. int VDRingBuffer<T, Allocator>::Write(const T *src, int elements) {
  234.     VDASSERT(elements >= 0);
  235.  
  236.     int actual = 0;
  237.     while(elements) {
  238.         int tc;
  239.         void *dst = LockWrite(elements, tc);
  240.  
  241.         if (!tc)
  242.             break;
  243.  
  244.         memcpy(dst, src, tc*sizeof(T));
  245.  
  246.         UnlockWrite(tc);
  247.  
  248.         actual += tc;
  249.         elements -= tc;
  250.         src += tc;
  251.     }
  252.  
  253.     return actual;
  254. }
  255.  
  256. template<class T, class Allocator>
  257. T *VDRingBuffer<T, Allocator>::LockWrite(int requested, int& actual) {
  258.     VDASSERT(requested >= 0);
  259.     int nLevelNow = nSize - nLevel;
  260.  
  261.     if (requested > nLevelNow)
  262.         requested = nLevelNow;
  263.  
  264.     if (requested + nWritePoint > nSize)
  265.         requested = nSize - nWritePoint;
  266.  
  267.     actual = requested;
  268.  
  269.     return pBuffer + nWritePoint;
  270. }
  271.  
  272. template<class T, class Allocator>
  273. T *VDRingBuffer<T, Allocator>::LockWriteAll(int& actual) {
  274.     int requested = nSize - nLevel;
  275.  
  276.     if (requested + nWritePoint > nSize)
  277.         requested = nSize - nWritePoint;
  278.  
  279.     actual = requested;
  280.  
  281.     return pBuffer + nWritePoint;
  282. }
  283.  
  284. template<class T, class Allocator>
  285. int VDRingBuffer<T, Allocator>::UnlockWrite(int actual) {
  286.     VDASSERT(actual >= 0);
  287.     VDASSERT(nLevel + actual <= nSize);
  288.  
  289.     int newpt = nWritePoint + actual;
  290.  
  291.     if (newpt >= nSize)
  292.         newpt = 0;
  293.  
  294.     nWritePoint = newpt;
  295.  
  296.     return nLevel.add(actual);
  297. }
  298.  
  299.  
  300.  
  301. #endif
  302.