Skip to content

Commit

Permalink
Updated Deque to support generics
Browse files Browse the repository at this point in the history
  • Loading branch information
christianrpetrin committed Mar 2, 2023
1 parent 1c27c9e commit acaec1b
Show file tree
Hide file tree
Showing 11 changed files with 577 additions and 147 deletions.
5 changes: 5 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ go:
- "1.13.x"
- "1.14.x"
- "1.15.x"
- "1.16.x"
- "1.17.x"
- "1.18.x"
- "1.19.x"
- "1.20.x"
- tip

before_install:
Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,8 @@
# 1.0.4
- Fixed bug related to PushFront/PopBack: [here](https://github.com/ef-ds/deque/pull/21)
- The minor change had no significant performance impact

# 2.0.0
- Updated Deque to support generics!
- This is a breaking change and will require users to specify the desired data type used with Deque (such as Deque[int]). We recommend the users to update their existing code to use the specific data type the Deque needs to handle (such as int, string, etc), but the interface type can still be used. Just declare Deque as "var d deque.Deque[interface{}]" and use it normally. No other changes should be required to use Deque v2.0.0.
- Deque v2 is up to 10% faster and uses up to 35% less memory it used to use in most test cases! Benchmark tests: [v1.0.3 vs v2.0.0](testdata/release_v2.0.0.md); [comparison tests](https://github.com/ef-ds/deque-bench-tests/blob/master/PERFORMANCE.md)
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,6 @@ From a configured [Go environment](https://golang.org/doc/install#testing):
go get -u github.com/ef-ds/deque
```

If you are using dep:
```sh
dep ensure -add github.com/ef-ds/[email protected]
```

We recommend to target only released versions for production use.


Expand All @@ -30,7 +25,7 @@ import (
)

func main() {
var d deque.Deque
var d deque.Deque[int]

for i := 1; i <= 5; i++ {
d.PushBack(i)
Expand Down Expand Up @@ -64,7 +59,7 @@ import (
)

func main() {
var d deque.Deque
var d deque.Deque[int]

for i := 1; i <= 5; i++ {
d.PushBack(i)
Expand All @@ -87,6 +82,9 @@ Output:

Also refer to the [integration](integration_test.go) and [API](api_test.go) tests.

## Generics

Starting with v2.0.0, Deque supports generics. Looking for a previous non-generic stable release? Check out version [1.0.4](https://github.com/ef-ds/deque/releases/tag/v1.0.4).


## Tests
Expand Down
20 changes: 10 additions & 10 deletions api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@ import (
)

func TestPopFrontWithZeroValueShouldReturnReadyToUseDeque(t *testing.T) {
var d deque.Deque
var d deque.Deque[int]
d.PushBack(1)
d.PushBack(2)

v, ok := d.PopFront()
if !ok || v.(int) != 1 {
if !ok || v != 1 {
t.Errorf("Expected: 1; Got: %d", v)
}
v, ok = d.PopFront()
if !ok || v.(int) != 2 {
if !ok || v != 2 {
t.Errorf("Expected: 2; Got: %d", v)
}
_, ok = d.PopFront()
Expand All @@ -46,16 +46,16 @@ func TestPopFrontWithZeroValueShouldReturnReadyToUseDeque(t *testing.T) {
}

func TestPopBackWithZeroValueShouldReturnReadyToUseDeque(t *testing.T) {
var d deque.Deque
var d deque.Deque[int]
d.PushBack(1)
d.PushBack(2)

v, ok := d.PopBack()
if !ok || v.(int) != 2 {
if !ok || v != 2 {
t.Errorf("Expected: 2; Got: %d", v)
}
v, ok = d.PopBack()
if !ok || v.(int) != 1 {
if !ok || v != 1 {
t.Errorf("Expected: 1; Got: %d", v)
}
_, ok = d.PopBack()
Expand All @@ -65,7 +65,7 @@ func TestPopBackWithZeroValueShouldReturnReadyToUseDeque(t *testing.T) {
}

func TestWithZeroValueAndEmptyShouldReturnAsEmpty(t *testing.T) {
var d deque.Deque
var d deque.Deque[int]
if _, ok := d.Front(); ok {
t.Error("Expected: false as the queue is empty; Got: true")
}
Expand All @@ -84,7 +84,7 @@ func TestWithZeroValueAndEmptyShouldReturnAsEmpty(t *testing.T) {
}

func TestInitShouldReturnEmptyDeque(t *testing.T) {
var d deque.Deque
var d deque.Deque[int]
d.PushBack(1)

d.Init()
Expand All @@ -107,7 +107,7 @@ func TestInitShouldReturnEmptyDeque(t *testing.T) {
}

func TestPopFrontWithNilValuesShouldReturnAllValuesInOrder(t *testing.T) {
d := deque.New()
d := deque.New[interface{}]()
d.PushBack(1)
d.PushBack(nil)
d.PushBack(2)
Expand Down Expand Up @@ -136,7 +136,7 @@ func TestPopFrontWithNilValuesShouldReturnAllValuesInOrder(t *testing.T) {
}

func TestPopBackWithNilValuesShouldReturnAllValuesInOrder(t *testing.T) {
d := deque.New()
d := deque.New[interface{}]()
d.PushBack(1)
d.PushBack(nil)
d.PushBack(2)
Expand Down
30 changes: 15 additions & 15 deletions benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ var (
}

// Used to store temp values, avoiding any compiler optimizations.
tmp interface{}
tmp *testData
tmp2 bool

fillCount = 10000
Expand All @@ -63,7 +63,7 @@ func BenchmarkFillQueue(b *testing.B) {
for _, test := range tests {
b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
q := deque.New()
q := deque.New[*testData]()
for i := 0; i < test.count; i++ {
q.PushBack(nil)
}
Expand All @@ -79,7 +79,7 @@ func BenchmarkFillStack(b *testing.B) {
for _, test := range tests {
b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
q := deque.New()
q := deque.New[*testData]()
for i := 0; i < test.count; i++ {
q.PushFront(nil)
}
Expand All @@ -100,7 +100,7 @@ func BenchmarkRefillQueue(b *testing.B) {
}

b.Run(strconv.Itoa(test.count), func(b *testing.B) {
q := deque.New()
q := deque.New[*testData]()
for n := 0; n < b.N; n++ {
for n := 0; n < refillCount; n++ {
for i := 0; i < test.count; i++ {
Expand All @@ -118,7 +118,7 @@ func BenchmarkRefillQueue(b *testing.B) {
func BenchmarkRefillStack(b *testing.B) {
for _, test := range tests {
b.Run(strconv.Itoa(test.count), func(b *testing.B) {
q := deque.New()
q := deque.New[*testData]()
for n := 0; n < b.N; n++ {
for n := 0; n < refillCount; n++ {
for i := 0; i < test.count; i++ {
Expand All @@ -134,7 +134,7 @@ func BenchmarkRefillStack(b *testing.B) {
}

func BenchmarkRefillFullQueue(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < fillCount; i++ {
d.PushBack(nil)
}
Expand Down Expand Up @@ -166,7 +166,7 @@ func BenchmarkRefillFullQueue(b *testing.B) {
}

func BenchmarkRefillFullStack(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < fillCount; i++ {
d.PushBack(nil)
}
Expand All @@ -192,7 +192,7 @@ func BenchmarkRefillFullStack(b *testing.B) {
}

func BenchmarkStableQueue(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < fillCount; i++ {
d.PushBack(nil)
}
Expand All @@ -214,7 +214,7 @@ func BenchmarkStableQueue(b *testing.B) {
}

func BenchmarkStableStack(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < fillCount; i++ {
d.PushBack(nil)
}
Expand All @@ -239,7 +239,7 @@ func BenchmarkSlowIncreaseQueue(b *testing.B) {
for _, test := range tests {
b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < test.count; i++ {
d.PushBack(nil)
d.PushBack(nil)
Expand All @@ -257,7 +257,7 @@ func BenchmarkSlowIncreaseStack(b *testing.B) {
for _, test := range tests {
b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
d := deque.New()
d := deque.New[*testData]()
for i := 0; i < test.count; i++ {
d.PushFront(nil)
d.PushFront(nil)
Expand All @@ -272,7 +272,7 @@ func BenchmarkSlowIncreaseStack(b *testing.B) {
}

func BenchmarkSlowDecreaseQueue(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for _, test := range tests {
items := test.count / 2
for i := 0; i <= items; i++ {
Expand Down Expand Up @@ -300,7 +300,7 @@ func BenchmarkSlowDecreaseQueue(b *testing.B) {
}

func BenchmarkSlowDecreaseStack(b *testing.B) {
d := deque.New()
d := deque.New[*testData]()
for _, test := range tests {
items := test.count / 2
for i := 0; i <= items; i++ {
Expand Down Expand Up @@ -336,7 +336,7 @@ func BenchmarkMicroserviceQueue(b *testing.B) {

b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
d := deque.New()
d := deque.New[*testData]()

// Simulate stable traffic
for i := 0; i < test.count; i++ {
Expand Down Expand Up @@ -395,7 +395,7 @@ func BenchmarkMicroserviceStack(b *testing.B) {

b.Run(strconv.Itoa(test.count), func(b *testing.B) {
for n := 0; n < b.N; n++ {
d := deque.New()
d := deque.New[*testData]()

// Simulate stable traffic
for i := 0; i < test.count; i++ {
Expand Down
Loading

0 comments on commit acaec1b

Please sign in to comment.