Skip to content

Commit 3e0af5b

Browse files
committed
feat: separate into packages
1 parent f6ed8bd commit 3e0af5b

8 files changed

+88
-122
lines changed

collections_bench_test.go

-52
This file was deleted.

linked_list.go linkedlist/linked_list.go

+18-14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
1-
package mm
1+
package linkedlist
22

3-
import "fmt"
3+
import (
4+
"fmt"
5+
6+
"github.com/joetifa2003/mm-go"
7+
)
48

59
var popEmptyMsg = "cannot pop empty linked list"
610

@@ -18,23 +22,23 @@ type LinkedList[T any] struct {
1822
length int
1923
}
2024

21-
// NewLinkedList creates a new linked list.
22-
func NewLinkedList[T any]() *LinkedList[T] {
23-
linkedList := Alloc[LinkedList[T]]()
25+
// New creates a new linked list.
26+
func New[T any]() *LinkedList[T] {
27+
linkedList := mm.Alloc[LinkedList[T]]()
2428

2529
return linkedList
2630
}
2731

2832
func (ll *LinkedList[T]) init(value T) {
29-
ll.head = Alloc[linkedListNode[T]]()
33+
ll.head = mm.Alloc[linkedListNode[T]]()
3034
ll.head.value = value
3135
ll.tail = ll.head
3236
ll.length++
3337
}
3438

3539
func (ll *LinkedList[T]) popLast() T {
3640
value := ll.tail.value
37-
Free(ll.tail)
41+
mm.Free(ll.tail)
3842
ll.tail = nil
3943
ll.head = nil
4044
ll.length--
@@ -49,7 +53,7 @@ func (ll *LinkedList[T]) PushBack(value T) {
4953
return
5054
}
5155

52-
newNode := Alloc[linkedListNode[T]]()
56+
newNode := mm.Alloc[linkedListNode[T]]()
5357
newNode.value = value
5458
newNode.prev = ll.tail
5559
ll.tail.next = newNode
@@ -65,7 +69,7 @@ func (ll *LinkedList[T]) PushFront(value T) {
6569
return
6670
}
6771

68-
newNode := Alloc[linkedListNode[T]]()
72+
newNode := mm.Alloc[linkedListNode[T]]()
6973
newNode.value = value
7074
newNode.next = ll.head
7175
ll.head.prev = newNode
@@ -86,7 +90,7 @@ func (ll *LinkedList[T]) PopBack() T {
8690
value := ll.tail.value
8791
newTail := ll.tail.prev
8892
newTail.next = nil
89-
Free(ll.tail)
93+
mm.Free(ll.tail)
9094
ll.tail = newTail
9195
ll.length--
9296

@@ -106,7 +110,7 @@ func (ll *LinkedList[T]) PopFront() T {
106110
value := ll.head.value
107111
newHead := ll.head.next
108112
newHead.prev = nil
109-
Free(ll.head)
113+
mm.Free(ll.head)
110114
ll.head = newHead
111115
ll.length--
112116

@@ -163,7 +167,7 @@ func (ll *LinkedList[T]) RemoveAt(idx int) T {
163167
prevNode.next = nextNode
164168
ll.length--
165169

166-
Free(node)
170+
mm.Free(node)
167171

168172
return value
169173
}
@@ -258,9 +262,9 @@ func (ll *LinkedList[T]) Free() {
258262

259263
for currentNode != nil {
260264
nextNode := currentNode.next
261-
Free(currentNode)
265+
mm.Free(currentNode)
262266
currentNode = nextNode
263267
}
264268

265-
Free(ll)
269+
mm.Free(ll)
266270
}

linked_list_test.go linkedlist/linked_list_test.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
package mm
1+
package linkedlist_test
22

33
import (
44
"testing"
55

6+
"github.com/joetifa2003/mm-go/linkedlist"
67
"github.com/stretchr/testify/assert"
78
)
89

910
func testPushAndPop(t *testing.T) {
1011
assert := assert.New(t)
1112

12-
ll := NewLinkedList[int]()
13+
ll := linkedlist.New[int]()
1314
defer ll.Free()
1415

1516
ll.PushBack(15)
@@ -47,7 +48,7 @@ func testPushAndPop(t *testing.T) {
4748
func testForEach(t *testing.T) {
4849
assert := assert.New(t)
4950

50-
ll := NewLinkedList[int]()
51+
ll := linkedlist.New[int]()
5152
defer ll.Free()
5253

5354
ll.PushBack(2)
@@ -71,7 +72,7 @@ func testForEach(t *testing.T) {
7172
func testIndexing(t *testing.T) {
7273
assert := assert.New(t)
7374

74-
ll := NewLinkedList[int]()
75+
ll := linkedlist.New[int]()
7576
defer ll.Free()
7677

7778
ll.PushBack(1)
@@ -110,7 +111,7 @@ func testIndexing(t *testing.T) {
110111
func testRemove(t *testing.T) {
111112
assert := assert.New(t)
112113

113-
ll := NewLinkedList[int]()
114+
ll := linkedlist.New[int]()
114115
defer ll.Free()
115116

116117
ll.PushBack(1)

mm_test.go

+23-21
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
package mm
1+
package mm_test
22

33
import (
44
"fmt"
55
"runtime"
66
"testing"
77

8+
"github.com/joetifa2003/mm-go"
9+
"github.com/joetifa2003/mm-go/typedarena"
810
"github.com/stretchr/testify/assert"
911
)
1012

@@ -42,7 +44,7 @@ func BenchmarkHeapManaged(b *testing.B) {
4244
}
4345

4446
func manual(nodes int) {
45-
allocatedNodes := AllocMany[Node](nodes)
47+
allocatedNodes := mm.AllocMany[Node](nodes)
4648

4749
for j := 0; j < nodes; j++ {
4850
var prev *Node
@@ -61,7 +63,7 @@ func manual(nodes int) {
6163
}
6264
}
6365

64-
FreeMany(allocatedNodes)
66+
mm.FreeMany(allocatedNodes)
6567
runtime.GC()
6668
}
6769

@@ -70,7 +72,7 @@ func BenchmarkManual(b *testing.B) {
7072
}
7173

7274
func arenaManual(nodes int) {
73-
arena := NewTypedArena[Node](nodes)
75+
arena := typedarena.New[Node](nodes)
7476
allocatedNodes := arena.AllocMany(nodes)
7577

7678
for j := 0; j < nodes; j++ {
@@ -126,7 +128,7 @@ func createTreeManaged(depth int) *TreeNode {
126128
return nil
127129
}
128130

129-
func createTreeManual(depth int, arena *TypedArena[TreeNode]) *TreeNode {
131+
func createTreeManual(depth int, arena *typedarena.TypedArena[TreeNode]) *TreeNode {
130132
if depth != 0 {
131133
node := arena.Alloc()
132134
node.left = createTreeManual(depth-1, arena)
@@ -157,7 +159,7 @@ func BenchmarkBinaryTreeArena(b *testing.B) {
157159
for _, chunkSize := range []int{50, 100, 150, 250, 500} {
158160
b.Run(fmt.Sprintf("chunk size %d", chunkSize), func(b *testing.B) {
159161
for n := 0; n < b.N; n++ {
160-
arena := NewTypedArena[TreeNode](chunkSize)
162+
arena := typedarena.New[TreeNode](chunkSize)
161163
tree := createTreeManual(25, arena)
162164
sumBinaryTree(tree)
163165
arena.Free()
@@ -170,8 +172,8 @@ func BenchmarkBinaryTreeArena(b *testing.B) {
170172
func TestAllocMany(t *testing.T) {
171173
assert := assert.New(t)
172174

173-
allocated := AllocMany[int](2) // allocates 2 ints and returns it as a slice of ints with length 2
174-
defer FreeMany(allocated) // it's recommended to make sure the data gets deallocated (defer recommended to prevent leaks)
175+
allocated := mm.AllocMany[int](2) // allocates 2 ints and returns it as a slice of ints with length 2
176+
defer mm.FreeMany(allocated) // it's recommended to make sure the data gets deallocated (defer recommended to prevent leaks)
175177
assert.Equal(2, len(allocated))
176178
allocated[0] = 15 // changes the data in the slice (aka the heap)
177179
ptr := &allocated[0] // takes a pointer to the data in the heap
@@ -183,33 +185,33 @@ func TestAllocMany(t *testing.T) {
183185
func TestAlloc(t *testing.T) {
184186
assert := assert.New(t)
185187

186-
ptr := Alloc[int]() // allocates a single int and returns a ptr to it
187-
defer Free(ptr) // frees the int (defer recommended to prevent leaks)
188+
ptr := mm.Alloc[int]() // allocates a single int and returns a ptr to it
189+
defer mm.Free(ptr) // frees the int (defer recommended to prevent leaks)
188190

189191
*ptr = 15
190192
assert.Equal(15, *ptr)
191193

192-
ptr2 := Alloc[[1e3]int]() // creates large array to make malloc mmap new chunk
193-
defer Free(ptr2)
194+
ptr2 := mm.Alloc[[1e3]int]() // creates large array to make malloc mmap new chunk
195+
defer mm.Free(ptr2)
194196
}
195197

196198
func TestReallocate(t *testing.T) {
197199
assert := assert.New(t)
198200

199-
allocated := AllocMany[int](2) // allocates 2 int and returns it as a slice of ints with length 2
201+
allocated := mm.AllocMany[int](2) // allocates 2 int and returns it as a slice of ints with length 2
200202
allocated[0] = 15
201203
assert.Equal(2, len(allocated))
202-
allocated = Reallocate(allocated, 3)
204+
allocated = mm.Reallocate(allocated, 3)
203205
assert.Equal(3, len(allocated))
204206
assert.Equal(15, allocated[0]) // data after reallocation stays the same
205-
FreeMany(allocated) // didn't use defer here because i'm doing a reallocation and changing the value of allocated variable (otherwise can segfault)
207+
mm.FreeMany(allocated) // didn't use defer here because i'm doing a reallocation and changing the value of allocated variable (otherwise can segfault)
206208
}
207209

208210
func TestUnmapChunk(t *testing.T) {
209-
data1 := AllocMany[int](1e6)
210-
data2 := AllocMany[int](1e6)
211-
data3 := AllocMany[int](1e6)
212-
FreeMany(data2)
213-
FreeMany(data1)
214-
FreeMany(data3)
211+
data1 := mm.AllocMany[int](1e6)
212+
data2 := mm.AllocMany[int](1e6)
213+
data3 := mm.AllocMany[int](1e6)
214+
mm.FreeMany(data2)
215+
mm.FreeMany(data1)
216+
mm.FreeMany(data3)
215217
}

typed_arena.go typedarena/typed_arena.go

+16-11
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
1-
package mm
1+
package typedarena
2+
3+
import (
4+
"github.com/joetifa2003/mm-go"
5+
"github.com/joetifa2003/mm-go/vector"
6+
)
27

38
type typedChunk[T any] struct {
49
data []T
510
len int
611
}
712

813
func newChunk[T any](size int) *typedChunk[T] {
9-
chunk := Alloc[typedChunk[T]]()
10-
chunk.data = AllocMany[T](size)
14+
chunk := mm.Alloc[typedChunk[T]]()
15+
chunk.data = mm.AllocMany[T](size)
1116

1217
return chunk
1318
}
@@ -24,25 +29,25 @@ func (c *typedChunk[T]) AllocMany(n int) []T {
2429
}
2530

2631
func (c *typedChunk[T]) Free() {
27-
FreeMany(c.data)
28-
Free(c)
32+
mm.FreeMany(c.data)
33+
mm.Free(c)
2934
}
3035

3136
// TypedArena is a growable typed arena
3237
type TypedArena[T any] struct {
33-
chunks *Vector[*typedChunk[T]]
38+
chunks *vector.Vector[*typedChunk[T]]
3439
chunkSize int
3540
}
3641

37-
// NewTypedArena creates a typed arena with the specified chunk size.
42+
// New creates a typed arena with the specified chunk size.
3843
// a chunk is the the unit of the arena, if T is int for example and the
3944
// chunk size is 5, then each chunk is going to hold 5 ints. And if the
4045
// chunk is filled it will allocate another chunk that can hold 5 ints.
4146
// then you can call FreeArena and it will deallocate all chunks together
42-
func NewTypedArena[T any](chunkSize int) *TypedArena[T] {
43-
tArena := Alloc[TypedArena[T]]()
47+
func New[T any](chunkSize int) *TypedArena[T] {
48+
tArena := mm.Alloc[TypedArena[T]]()
4449
tArena.chunkSize = chunkSize
45-
tArena.chunks = NewVector[*typedChunk[T]]()
50+
tArena.chunks = vector.New[*typedChunk[T]]()
4651

4752
firstChunk := newChunk[T](chunkSize)
4853
tArena.chunks.Push(firstChunk)
@@ -86,5 +91,5 @@ func (ta *TypedArena[T]) Free() {
8691
c.Free()
8792
}
8893
ta.chunks.Free()
89-
Free(ta)
94+
mm.Free(ta)
9095
}

typed_test.go typedarena/typed_test.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
package mm
1+
package typedarena_test
22

33
import (
44
"testing"
55

6+
"github.com/joetifa2003/mm-go/typedarena"
67
"github.com/stretchr/testify/assert"
78
)
89

910
func TestTypedArena(t *testing.T) {
1011
assert := assert.New(t)
1112

12-
arena := NewTypedArena[int](4)
13+
arena := typedarena.New[int](4)
1314
defer arena.Free()
1415

1516
int1 := arena.Alloc() // allocates 1 int from arena

0 commit comments

Comments
 (0)