You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Queue.h 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. #pragma once
  2. #if defined TARGET_HAS_ThirdPartyGUSBampCAPI_Linux
  3. #include <stdint.h>
  4. #include <string.h>
  5. #ifndef MIN
  6. #define MIN(a, b) (((a) < (b)) ? (a) : (b))
  7. #endif
  8. #ifndef MAX
  9. #define MAX(a, b) (((a) > (b)) ? (a) : (b))
  10. #endif
  11. template <class T>
  12. class Queue
  13. {
  14. T* buffer = nullptr;
  15. int head = 0, tail = 0, size = 0;
  16. public:
  17. Queue() { }
  18. Queue(T* array, const int len)
  19. {
  20. size = len;
  21. buffer = array;
  22. }
  23. void SetBuffer(T* array, const int len)
  24. {
  25. size = len;
  26. head = tail = 0;
  27. buffer = array;
  28. }
  29. int Get(T* elements, int len)
  30. {
  31. // Trim the length if necessary to only as large as the number of available elements in the buffer
  32. len = MIN(len, Avail());
  33. int nonwrapped = MIN((size - tail), len);
  34. const int wrapped = len - nonwrapped;
  35. // memcpy the data starting at the head all the way up to the last element *(storage - 1)
  36. memcpy(elements, (buffer + tail), nonwrapped * sizeof(T));
  37. // If there's still data to copy memcpy whatever remains, starting at the first element *(begin) until the end of data. The first step will have ensured
  38. // that we don't crash into the tail during this process.
  39. memcpy((elements + nonwrapped), buffer, wrapped * sizeof(T));
  40. // Recalculate head
  41. tail = (tail + nonwrapped + wrapped) % size;
  42. return len;
  43. }
  44. // Returns the number of bytes actually placed in the array
  45. int Put(const T* elements, int len)
  46. {
  47. // Trim the length if necessary to only as large as the nuber of free elements in the buffer
  48. len = MIN(len, Free());
  49. // Figure out how much to append to the end of the buffer and how much will overlap onto the start
  50. int nonwrapped = MIN((size - head), len);
  51. const int wrapped = len - nonwrapped;
  52. // memcpy the data starting at the head all the way up to the last element *(storage - 1)
  53. memcpy((buffer + head), elements, nonwrapped * sizeof(T));
  54. // If there's still data to copy memcpy whatever remains onto the beginning of the array
  55. memcpy(buffer, (elements + nonwrapped), wrapped * sizeof(T));
  56. // Re-recalculate head
  57. head = (head + nonwrapped + wrapped) % size;
  58. return len;
  59. }
  60. // Expand the size of queue without actually modifying any of the contents - useful for copying directly onto the queu buffer
  61. int Pad(int len)
  62. {
  63. // Trim the length if necessary to only as large as the nuber of free elements in the buffer
  64. len = MIN(len, Free());
  65. // Figure out how much to append to the end of the buffer and how much will overlap onto the start
  66. const int nonwrapped = MIN((size - head), len), wrapped = len - nonwrapped;
  67. // Re-recalculate head
  68. head = (head + nonwrapped + wrapped) % size;
  69. return len;
  70. }
  71. // Removes the oldest entry from the Queue
  72. void Pop() { if (Avail()) tail = (tail + 1) % size; }
  73. // Returns the oldest element in the array (the one added before any other)
  74. T& Tail() { return buffer[tail]; }
  75. // Returns the newest element in the array (the one added after every other)
  76. T& Head() { return buffer[(head + size - 1) % size]; }
  77. T& operator[](int n) { return buffer[tail + n % size]; }
  78. void Clear() { head = tail = 0; }
  79. int Avail() const { return (size + head - tail) % size; }
  80. int Free() const { return (size - 1 - Avail()); }
  81. // Gets the number of free elements that can be stored contiguously
  82. int FreeContiguous() { return head < tail ? tail - head - 1 : MIN(size - head, Free()); }
  83. // Gets a pointer to the next free address in the buffer
  84. T* NextFreeAddress() { return buffer + head; }
  85. };
  86. #endif // TARGET_HAS_ThirdPartyGUSBampCAPI_Linux