Skip to content

Commit 02dc9c1

Browse files
Merge pull request #233 from fsprojects/repo-assist/fix-issue-125-circular-buffer-array-enqueue-806b1b4611ff3be2
[Repo Assist] Fix CircularBuffer.Enqueue(array) - head pointer advances by count, not 1
2 parents fcec6f5 + cbcc08c commit 02dc9c1

2 files changed

Lines changed: 46 additions & 5 deletions

File tree

src/FSharpx.Collections/CircularBuffer.fs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,31 @@ type CircularBuffer<'T>(bufferSize: int) =
4848
dequeued
4949

5050
member this.Enqueue(value: _[], offset, count) =
51+
if isNull value then
52+
invalidArg "value" "value must not be null."
53+
54+
if offset < 0 then
55+
invalidArg "offset" "offset must not be negative."
56+
57+
if count < 0 then
58+
invalidArg "count" "count must not be negative."
59+
60+
if offset + count > value.Length then
61+
invalidArg "count" "offset and count exceed the length of the source array."
62+
5163
if count > bufferSize then
5264
invalidOp "Requested count is too large."
5365

5466
let mutable offset = offset
5567

56-
head <- (head + 1) % bufferSize
68+
let startPos = (head + 1) % bufferSize
5769

58-
for x, y in nextBuffer head count do
70+
for x, y in nextBuffer startPos count do
5971
Array.blit value offset buffer x y
6072
offset <- offset + y
6173

74+
head <- (head + count) % bufferSize
75+
6276
if length = bufferSize then
6377
tail <- (tail + count) % bufferSize
6478
else

tests/FSharpx.Collections.Tests/CircularBufferTests.fs

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,34 @@ module CircularBufferTests =
8484
Expect.throwsT<System.InvalidOperationException> "" f
8585
}
8686

87-
ptest "Printing after multiple enqueue circles" {
87+
test "fail on negative offset" {
88+
let f =
89+
fun _ ->
90+
let circularBuffer = CircularBuffer<int> 5
91+
circularBuffer.Enqueue([| 1; 2; 3 |], -1, 2)
92+
93+
Expect.throwsT<System.ArgumentException> "" f
94+
}
95+
96+
test "fail on negative count" {
97+
let f =
98+
fun _ ->
99+
let circularBuffer = CircularBuffer<int> 5
100+
circularBuffer.Enqueue([| 1; 2; 3 |], 0, -1)
101+
102+
Expect.throwsT<System.ArgumentException> "" f
103+
}
104+
105+
test "fail when offset + count exceeds array length" {
106+
let f =
107+
fun _ ->
108+
let circularBuffer = CircularBuffer<int> 5
109+
circularBuffer.Enqueue([| 1; 2; 3 |], 2, 3)
110+
111+
Expect.throwsT<System.ArgumentException> "" f
112+
}
113+
114+
test "Printing after multiple enqueue circles" {
88115
let circularBuffer = CircularBuffer<int> 5
89116

90117
circularBuffer.Enqueue [| 1; 2; 3; 4; 5 |]
@@ -96,7 +123,7 @@ module CircularBufferTests =
96123

97124

98125

99-
ptest "Printing from a queue 1..8 and dequeue 5, then enqueue 1..3 and dequeue 3, from array" {
126+
test "Printing from a queue 1..8 and dequeue 5, then enqueue 1..3 and dequeue 3, from array" {
100127
let circularBuffer = CircularBuffer<int> 5
101128

102129
circularBuffer.Enqueue([| 1; 2; 3; 4; 5 |])
@@ -106,7 +133,7 @@ module CircularBufferTests =
106133
Expect.equal "buffer" [| 1; 2; 3 |] <| circularBuffer.Dequeue 3
107134
}
108135

109-
ptest "Consider a large array with various, incoming array segments" {
136+
test "Consider a large array with various, incoming array segments" {
110137
let circularBuffer = CircularBuffer<int> 5
111138

112139
let source =

0 commit comments

Comments
 (0)