Skip to content

Commit 0e6194a

Browse files
committed
feat(list): first version of deque as fork from container/list (#45).
- includes 100% test coverage and cmd/ demo with tests.
1 parent 44d3bac commit 0e6194a

8 files changed

Lines changed: 768 additions & 11 deletions

File tree

LICENSE-GO.txt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
Copyright 2009 The Go Authors.
2+
3+
Redistribution and use in source and binary forms, with or without
4+
modification, are permitted provided that the following conditions are
5+
met:
6+
7+
* Redistributions of source code must retain the above copyright
8+
notice, this list of conditions and the following disclaimer.
9+
* Redistributions in binary form must reproduce the above
10+
copyright notice, this list of conditions and the following disclaimer
11+
in the documentation and/or other materials provided with the
12+
distribution.
13+
* Neither the name of Google LLC nor the names of its
14+
contributors may be used to endorse or promote products derived from
15+
this software without specific prior written permission.
16+
17+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18+
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19+
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20+
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21+
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22+
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23+
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24+
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25+
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

README.md

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,29 @@
77
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/fgm/container/badge)](https://securityscorecards.dev/viewer/?uri=github.com/fgm/container)
88
[![OpenSSF Best Practices](https://www.bestpractices.dev/projects/10245/badge)](https://www.bestpractices.dev/projects/10245)
99

10-
This module contains minimal type-safe Ordered Map, Queue, Set and Stack implementations
11-
using Go generics.
10+
This module contains minimal type-safe Double-ended queue, Ordered Map, Queue, Set and Stack implementations
11+
using Go generics, as well as a concurrent-safe WaitableQueue.
1212

1313
The Ordered Map supports both stable (in-place) updates and recency-based ordering,
1414
making it suitable both for highest performance (in-place), and for LRU caches (recency).
1515

16+
The double-ended queue is currently a fork of the Go stdlib [container/list](https://pkg.go.dev/container/list) package,
17+
replacing the `any` value with a type parameter for type safety.
18+
This API is not stable, as it differs from the other packages,
19+
and will be deprecated when a simpler one is found, more in line with the other packages.
20+
1621
## Contents
1722

1823
See the available types by underlying storage
1924

20-
| Type | Slice | Map | List | List+sync.Pool | List+int. pool | Recommended |
21-
|---------------|:-----:|:---:|:----:|:--------------:|:--------------:|----------------------|
22-
| OrderedMap | Y | | | | | Slice with size hint |
23-
| Queue | Y | | Y | Y | Y | Slice with size hint |
24-
| WaitableQueue | Y | | | | | Slice with size hint |
25-
| Set | | Y | | | | Map with size hint |
26-
| Stack | Y | | Y | Y | Y | Slice with size hint |
27-
25+
| Type | Slice | Map | List | List+sync.Pool | List+int. pool | Recommended |
26+
|--------------------|:-----:|:---:|:----:|:--------------:|:--------------:|-----------------------|
27+
| Double-ended queue | | | Y | | | Type-safe stdlib fork |
28+
| OrderedMap | Y | | | | | Slice with size hint |
29+
| Queue | Y | | Y | Y | Y | Slice with size hint |
30+
| WaitableQueue | Y | | | | | Slice with size hint |
31+
| Set | | Y | | | | Map with size hint |
32+
| Stack | Y | | Y | Y | Y | Slice with size hint |
2833

2934
**CAVEAT**: In order to optimize performance, except for WaitableQueue,
3035
all of these implementations are unsafe for concurrent execution,
@@ -43,9 +48,11 @@ See [BENCHARKS.md](BENCHMARKS.md) for details.
4348

4449
See complete listings in:
4550

51+
- [`cmd/list`](cmd/list/real_main.go)
4652
- [`cmd/orderedmap`](cmd/orderedmap/real_main.go)
4753
- [`cmd/queuestack`](cmd/queuestack/real_main.go)
4854
- [`cmd/set`](cmd/set/real_main.go)
55+
- [`cmd/waitablequeue`](cmd/waitablequeue/real_main.go)
4956

5057
### Ordered Map
5158

@@ -137,7 +144,6 @@ the benchmarks, like:
137144

138145
This will also run the fuzz tests in unit test mode, without triggering the fuzzing logic.
139146

140-
141147
#### Fuzz tests
142148

143149
Fuzz tests are not run by CI, but you can run them on-demand during development with:
@@ -150,3 +156,11 @@ Fuzz tests are not run by CI, but you can run them on-demand during development
150156

151157
- Adjust `-fuzztime` duration as relevant: 20 seconds is just a smoke test.
152158
- Be sure to escape the `^$` and `\Q\E` characters in the `-fuzz` argument in your shell.
159+
160+
## Licensing
161+
162+
- In the directory [container](container) and below,
163+
this project includes code derived from the Go standard library's container/list package,
164+
which is licensed under the BSD 3-Clause License.
165+
The original copyright and license text are included in the source files.
166+
- The rest of this project is licensed under the Apache License 2.0.

cmd/list/main.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import (
4+
"os"
5+
)
6+
7+
func main() {
8+
os.Exit(realMain(os.Stdout))
9+
}

cmd/list/real_main.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
"io"
6+
7+
"github.com/fgm/container/list"
8+
)
9+
10+
type Element int
11+
12+
func realMain(w io.Writer) int {
13+
var e Element = 13
14+
15+
l := list.New[Element]()
16+
// Add squares.
17+
for i := range e {
18+
l.PushBack(i * i)
19+
}
20+
fmt.Fprintf(w, "elements in list: %d\n", l.Len())
21+
22+
found := 0
23+
for {
24+
if cur := l.Front(); cur != nil {
25+
found++
26+
l.Remove(cur)
27+
fmt.Fprintf(w, "Element: %3v len: %d\n", cur.Value, l.Len())
28+
} else {
29+
break
30+
}
31+
if cur := l.Back(); cur != nil {
32+
found++
33+
l.Remove(cur)
34+
fmt.Fprintf(w, "Element: %3v len: %d\n", cur.Value, l.Len())
35+
} else {
36+
break
37+
}
38+
}
39+
fmt.Fprintf(w, "Found %d elements, expected %d\n", found, e)
40+
return 0
41+
}

cmd/list/real_main_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
package main
2+
3+
import (
4+
"bytes"
5+
"testing"
6+
7+
"github.com/google/go-cmp/cmp"
8+
)
9+
10+
func TestRealMain(t *testing.T) {
11+
var buf bytes.Buffer
12+
exitCode := realMain(&buf)
13+
14+
if exitCode != 0 {
15+
t.Fatalf("expected exit code 0, got %d", exitCode)
16+
}
17+
18+
expectedOutput := `elements in list: 13
19+
Element: 0 len: 12
20+
Element: 144 len: 11
21+
Element: 1 len: 10
22+
Element: 121 len: 9
23+
Element: 4 len: 8
24+
Element: 100 len: 7
25+
Element: 9 len: 6
26+
Element: 81 len: 5
27+
Element: 16 len: 4
28+
Element: 64 len: 3
29+
Element: 25 len: 2
30+
Element: 49 len: 1
31+
Element: 36 len: 0
32+
Found 13 elements, expected 13
33+
`
34+
if buf.String() != expectedOutput {
35+
t.Fatal(cmp.Diff(expectedOutput, buf.String()))
36+
}
37+
}

list/example_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright 2013 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
//
5+
// This file contains code from the go stdlib container/list package,
6+
// and is therefore dual licensed under the BSD 3 clause license, and the Apache 2.0 license.
7+
package list_test
8+
9+
import (
10+
"fmt"
11+
12+
"github.com/fgm/container/list"
13+
)
14+
15+
func Example() {
16+
// Create a new list and put some numbers in it.
17+
l := list.New[int]()
18+
e4 := l.PushBack(4)
19+
e1 := l.PushFront(1)
20+
l.InsertBefore(3, e4)
21+
l.InsertAfter(2, e1)
22+
23+
// Iterate through list and print its contents.
24+
for e := l.Front(); e != nil; e = e.Next() {
25+
fmt.Println(e.Value)
26+
}
27+
28+
// Output:
29+
// 1
30+
// 2
31+
// 3
32+
// 4
33+
}

0 commit comments

Comments
 (0)