gob/collection/concurrent/slice.go

139 lines
2.7 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package concurrent
import (
"sync"
. "gitea.zaclys.com/bvaudour/gob/option"
)
// Slice fournit une solution pour ajouter des éléments dans un slice de façon concurrente.
type Slice[T any] struct {
data []T
mtx sync.Mutex
closed bool
}
func (sl *Slice[T]) checkOpened() {
if sl.closed {
panic("The slice cannot be modified anymore.")
}
}
func (sl *Slice[T]) checkClosed() {
if !sl.closed {
panic("The slice needs to be opened.")
}
}
func (sl *Slice[T]) changeState(closed bool) {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.closed = closed
}
func (sl *Slice[T]) get() (out []T) {
out = make([]T, len(sl.data))
copy(out, sl.data)
return
}
func (sl *Slice[T]) checkIdx(i int) bool {
return i >= 0 && i < len(sl.data)
}
// Insert ajoute les entrées fournies en début de slice.
// Cette méthode nécessite que le slice soit ouvert.
func (sl *Slice[T]) Insert(elems ...T) {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.checkOpened()
sl.data = append(elems, sl.data...)
}
// Insert ajoute les entrées fournies en fin de slice.
// Cette méthode nécessite que le slice soit ouvert.
func (sl *Slice[T]) Append(elems ...T) {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.checkOpened()
sl.data = append(sl.data, elems...)
}
// Clear vide le slice.
// Cette méthode nécessite que le slice soit ouvert.
func (sl *Slice[T]) Clear() {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.checkOpened()
sl.data = []T{}
}
// Close empêche les modifications du slice.
func (sl *Slice[T]) Close() {
sl.changeState(true)
}
// Open permet les modifications du slice.
func (sl *Slice[T]) Open() {
sl.changeState(false)
}
// Set modifie lentrée du slice à lindex donné et retourne vrai si lentrée a été modifiée.
// Cette méthode nécessite que le slice soit ouvert.
func (sl *Slice[T]) Set(index int, value T) (ok bool) {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.checkOpened()
if ok = sl.checkIdx(index); ok {
sl.data[index] = value
}
return
}
// Get retourne la valeur du slice à lindex donné.
func (sl *Slice[T]) Get(index int) (value Option[T]) {
sl.mtx.Lock()
defer sl.mtx.Unlock()
if sl.checkIdx(index) {
value = Some(sl.data[index])
}
return
}
// Data retourne le slice.
// Cette méthode nécessite que le slice soit fermé.
func (sl *Slice[T]) Data() []T {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.checkClosed()
return sl.get()
}
// CloseData retourne le slice après lavoir préalablement fermé en écriture.
func (sl *Slice[T]) CloseData() []T {
sl.mtx.Lock()
defer sl.mtx.Unlock()
sl.closed = true
return sl.get()
}
// NewSlice retourne un slice initialisé avec les valeurs fournies.
func NewSlice[T any](elems ...T) *Slice[T] {
return &Slice[T]{
data: elems,
}
}