ring-buffer.sl 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  2. %
  3. % RING-BUFFER.SL - General Ring Buffers
  4. %
  5. % Author: Alan Snyder
  6. % Hewlett-Packard/CRC
  7. % Date: 6 July 1982
  8. % Revised: 16 November 1982
  9. %
  10. % 16-Nov-82 Alan Snyder
  11. % Recoded using OBJECTS package. Added FETCH and ROTATE operations.
  12. %
  13. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  14. (BothTimes (load objects))
  15. (CompileTime (load fast-int fast-vectors))
  16. (de ring-buffer-create (maximum-size)
  17. (make-instance 'ring-buffer 'maximum-size maximum-size))
  18. (defflavor ring-buffer ((maximum-size 16) % Maximum number of elements.
  19. vec % Stores the elements.
  20. (size 0) % Elements 0..size-1 are valid.
  21. (ptr -1) % Element vec[ptr] is current.
  22. )
  23. ()
  24. (gettable-instance-variables maximum-size size)
  25. (initable-instance-variables maximum-size)
  26. )
  27. (defmethod (ring-buffer init) (init-plist)
  28. (setf vec (mkvect (- maximum-size 1))))
  29. (defmethod (ring-buffer push) (new-element)
  30. (let ((new-ptr (+ ptr 1)))
  31. (when (> new-ptr (vector-upper-bound vec))
  32. (setf new-ptr 0))
  33. (when (>= new-ptr size)
  34. (setf size (+ new-ptr 1)))
  35. (setf ptr new-ptr)
  36. (vector-store vec new-ptr new-element)
  37. new-element
  38. ))
  39. (defmethod (ring-buffer top) ()
  40. % Returns NIL if the buffer is empty.
  41. (=> self fetch 0))
  42. (defmethod (ring-buffer pop) ()
  43. % Returns NIL if the buffer is empty.
  44. (when (> size 0)
  45. (let ((old-element (vector-fetch vec ptr)))
  46. (setf ptr (- ptr 1))
  47. (when (< ptr 0) (setf ptr (- size 1)))
  48. old-element
  49. )))
  50. (defmethod (ring-buffer fetch) (index)
  51. % Index 0 is the top element.
  52. % Index -1 is the next previous element, etc.
  53. % Index 1 is the most previous element, etc.
  54. % Returns NIL if the buffer is empty.
  55. (when (> size 0)
  56. (vector-fetch vec (ring-buffer-mod (+ ptr index) size))
  57. ))
  58. (defmethod (ring-buffer rotate) (count)
  59. % Rotate -1 makes the next "older" element current (like POP), etc.
  60. % Rotate 1 makes the next "newer" element current, etc.
  61. (when (> size 0)
  62. (setf ptr (ring-buffer-mod (+ ptr count) size))
  63. ))
  64. (de ring-buffer-mod (a b)
  65. (let ((remainder (// a b)))
  66. (if (>= remainder 0) remainder (+ b remainder))
  67. ))
  68. % The following functions are defined for backwards compatibility:
  69. (de ring-buffer-push (rb new-element)
  70. (=> rb push new-element))
  71. (de ring-buffer-top (rb)
  72. (=> rb top))
  73. (de ring-buffer-pop (rb)
  74. (=> rb pop))