github.com/nyan233/littlerpc@v0.4.6-0.20230316182519-0c8d5c48abaf/core/container/concurrent_array.go (about)

     1  package container
     2  
     3  import (
     4  	"fmt"
     5  	"sync/atomic"
     6  	"unsafe"
     7  
     8  	"github.com/nyan233/littlerpc/internal/reflect"
     9  )
    10  
    11  type ConcurrentArray[Value any] struct {
    12  	slice reflect.SliceHeader
    13  }
    14  
    15  func NewConcurrentArray[V any](cap int) *ConcurrentArray[V] {
    16  	rawSlice := make([]*V, cap, cap)
    17  	return &ConcurrentArray[V]{
    18  		slice: *(*reflect.SliceHeader)(unsafe.Pointer(&rawSlice)),
    19  	}
    20  }
    21  
    22  func (a *ConcurrentArray[Value]) Access(i int) *Value {
    23  	if i < 0 || i >= a.slice.Cap {
    24  		panic(fmt.Sprintf("index out of range [%d:%d]", i, a.slice.Cap))
    25  	}
    26  	offset := reflect.PtrSize * uintptr(i)
    27  	return (*Value)(atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(uintptr(a.slice.Data) + offset))))
    28  }
    29  
    30  func (a *ConcurrentArray[Value]) Swap(i int, v *Value) (old *Value) {
    31  	if i < 0 || i >= a.slice.Cap {
    32  		panic(fmt.Sprintf("index out of range [%d:%d]", i, a.slice.Cap))
    33  	}
    34  	offset := reflect.PtrSize * uintptr(i)
    35  	return (*Value)(atomic.SwapPointer((*unsafe.Pointer)(unsafe.Pointer(uintptr(a.slice.Data)+offset)), unsafe.Pointer(v)))
    36  }
    37  
    38  func (a *ConcurrentArray[Value]) Cap() int {
    39  	return a.slice.Cap
    40  }