-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathconcurrent_arena.go
64 lines (55 loc) · 1.45 KB
/
concurrent_arena.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
package memoryArena
import (
"fmt"
"sync"
"unsafe"
)
type ConcurrentArena[T any] struct {
*MemoryArena[T]
mutex sync.RWMutex
}
func NewConcurrentArena[T any](size int) (*ConcurrentArena[T], error) {
arena, err := NewMemoryArena[T](size)
if err != nil {
return nil, err
}
return &ConcurrentArena[T]{
MemoryArena: arena,
mutex: sync.RWMutex{},
}, nil
}
func (arena *ConcurrentArena[T]) Allocate(size int) (unsafe.Pointer, error) {
return arena.MemoryArena.Allocate(size)
}
func (arena *ConcurrentArena[T]) Reset() {
arena.mutex.Lock()
defer arena.mutex.Unlock()
arena.MemoryArena.Reset()
}
func (arena *ConcurrentArena[T]) AllocateObject(obj interface{}) (unsafe.Pointer, error) {
arena.mutex.Lock()
defer arena.mutex.Unlock()
// Ensure the object is of the expected type.
value, ok := obj.(T)
if !ok {
return nil, fmt.Errorf("invalid type: expected %T", *new(T))
}
size := int(unsafe.Sizeof(value))
ptr, err := arena.Allocate(size)
if err != nil {
return nil, fmt.Errorf("allocation failed due to insufficient memory")
}
// Directly copy the value into the allocated memory.
*(*T)(ptr) = value
return ptr, nil
}
func (arena *ConcurrentArena[T]) ResizePreserve(newSize int) error {
arena.mutex.Lock()
defer arena.mutex.Unlock()
return arena.MemoryArena.ResizePreserve(newSize)
}
func (arena *ConcurrentArena[T]) Resize(newSize int) error {
arena.mutex.Lock()
defer arena.mutex.Unlock()
return arena.MemoryArena.Resize(newSize)
}