Module collection (2)
This commit is contained in:
parent
485fca69ec
commit
8bf49d9e03
119
collection/concurrent/map.go
Normal file
119
collection/concurrent/map.go
Normal file
@ -0,0 +1,119 @@
|
||||
package concurrent
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
. "gitea.zaclys.com/bvaudour/gob/option"
|
||||
)
|
||||
|
||||
// Map fournit une solution pour ajouter des éléments dans un map de façon concurrente.
|
||||
type Map[K comparable, V any] struct {
|
||||
data map[K]V
|
||||
mtx sync.Mutex
|
||||
closed bool
|
||||
}
|
||||
|
||||
func (m *Map[K, V]) checkOpened() {
|
||||
if m.closed {
|
||||
panic("The map cannot be modified anymore.")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map[K, V]) checkClosed() {
|
||||
if !m.closed {
|
||||
panic("The Map needs to be opened.")
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Map[K, V]) changeState(closed bool) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
m.closed = closed
|
||||
}
|
||||
|
||||
func (m *Map[K, V]) get() (out map[K]V) {
|
||||
out = make(map[K]V)
|
||||
for k, v := range m.data {
|
||||
out[k] = v
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Clear vide le map.
|
||||
// Cette méthode nécessite que le map soit ouvert.
|
||||
func (m *Map[K, V]) Clear() {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
m.checkOpened()
|
||||
clear(m.data)
|
||||
}
|
||||
|
||||
// Close empêche les modifications du map.
|
||||
func (m *Map[K, V]) Close() {
|
||||
m.changeState(true)
|
||||
}
|
||||
|
||||
// Open permet les modifications du map.
|
||||
func (m *Map[K, V]) Open() {
|
||||
m.changeState(false)
|
||||
}
|
||||
|
||||
// Set associe la clé et la valeur données dans le map.
|
||||
// Cette méthode nécessite que le map soit ouvert.
|
||||
func (m *Map[K, V]) Set(key K, value V) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
m.checkOpened()
|
||||
m.data[key] = value
|
||||
}
|
||||
|
||||
// Get retourne la valeur du map à la clé donnée.
|
||||
func (m *Map[K, V]) Get(key K) (value Option[V]) {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
if v, ok := m.data[key]; ok {
|
||||
value = Some(v)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Data retourne le map.
|
||||
// Cette méthode nécessite que le map soit fermé.
|
||||
func (m *Map[K, V]) Data() map[K]V {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
m.checkClosed()
|
||||
|
||||
return m.get()
|
||||
}
|
||||
|
||||
// CloseData retourne le map après l’avoir préalablement fermé en écriture.
|
||||
func (m *Map[K, V]) CloseData() map[K]V {
|
||||
m.mtx.Lock()
|
||||
defer m.mtx.Unlock()
|
||||
|
||||
m.closed = true
|
||||
|
||||
return m.get()
|
||||
}
|
||||
|
||||
// NewMap retourne un map initialisé avec les valeurs fournies.
|
||||
func NewMap[K comparable, V any](elems ...map[K]V) *Map[K, V] {
|
||||
out := make(map[K]V)
|
||||
for _, m := range elems {
|
||||
for k, v := range m {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
return &Map[K, V]{
|
||||
data: out,
|
||||
}
|
||||
}
|
138
collection/concurrent/slice.go
Normal file
138
collection/concurrent/slice.go
Normal file
@ -0,0 +1,138 @@
|
||||
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 l’entrée du slice à l’index donné et retourne vrai si l’entré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 à l’index 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 l’avoir 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,
|
||||
}
|
||||
}
|
12
test/main.go
Normal file
12
test/main.go
Normal file
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a := []int{1, 2, 3}
|
||||
fmt.Println(a)
|
||||
clear(a)
|
||||
fmt.Println(a)
|
||||
}
|
Loading…
Reference in New Issue
Block a user