Browse Source

添加同步slice及测试

yjp 1 year ago
parent
commit
507f86842c
2 changed files with 199 additions and 0 deletions
  1. 122 0
      syncutils/sync_slice.go
  2. 77 0
      syncutils/sync_slice_test.go

+ 122 - 0
syncutils/sync_slice.go

@@ -0,0 +1,122 @@
+package syncutils
+
+import "sync"
+
+type RangeFunc[T any] func(index int, e T) bool
+
+type SyncSlice[T any] struct {
+	writeLocker sync.Locker
+	readLocker  sync.Locker
+	s           []T
+}
+
+func NewSyncSlice[T any](s []T, isRWMutex bool) *SyncSlice[T] {
+	var writeLocker sync.Locker
+	var readLocker sync.Locker
+
+	if !isRWMutex {
+		mutex := &sync.Mutex{}
+		writeLocker = mutex
+		readLocker = mutex
+	} else {
+		mutex := &sync.RWMutex{}
+		writeLocker = mutex
+		readLocker = mutex.RLocker()
+	}
+
+	return &SyncSlice[T]{
+		writeLocker: writeLocker,
+		readLocker:  readLocker,
+		s:           s,
+	}
+}
+
+func (syncSlice *SyncSlice[T]) Lock() {
+	syncSlice.writeLocker.Lock()
+}
+
+func (syncSlice *SyncSlice[T]) Unlock() {
+	syncSlice.writeLocker.Unlock()
+}
+
+func (syncSlice *SyncSlice[T]) RLock() {
+	syncSlice.readLocker.Lock()
+}
+
+func (syncSlice *SyncSlice[T]) RUnlock() {
+	syncSlice.readLocker.Unlock()
+}
+
+func (syncSlice *SyncSlice[T]) AppendNoLock(elements ...T) {
+	if elements == nil || len(elements) == 0 {
+		return
+	}
+
+	syncSlice.appendNoLock(elements...)
+}
+
+func (syncSlice *SyncSlice[T]) DeleteAtNoLock(index int) {
+	if index < 0 {
+		return
+	}
+
+	syncSlice.deleteAtNoLock(index)
+}
+
+func (syncSlice *SyncSlice[T]) RangeNoLock(rangeFunc RangeFunc[T]) {
+	if rangeFunc == nil {
+		return
+	}
+
+	syncSlice.rangeNoLock(rangeFunc)
+}
+
+func (syncSlice *SyncSlice[T]) Append(elements ...T) {
+	if elements == nil || len(elements) == 0 {
+		return
+	}
+
+	syncSlice.writeLocker.Lock()
+	defer syncSlice.writeLocker.Unlock()
+
+	syncSlice.appendNoLock(elements...)
+}
+
+func (syncSlice *SyncSlice[T]) DeleteAt(index int) {
+	if index < 0 {
+		return
+	}
+
+	syncSlice.writeLocker.Lock()
+	defer syncSlice.writeLocker.Unlock()
+
+	syncSlice.deleteAtNoLock(index)
+}
+
+func (syncSlice *SyncSlice[T]) Range(rangeFunc RangeFunc[T]) {
+	if rangeFunc == nil {
+		return
+	}
+
+	syncSlice.readLocker.Lock()
+	defer syncSlice.readLocker.Unlock()
+
+	syncSlice.rangeNoLock(rangeFunc)
+}
+
+func (syncSlice *SyncSlice[T]) appendNoLock(elements ...T) {
+	syncSlice.s = append(syncSlice.s, elements...)
+}
+
+func (syncSlice *SyncSlice[T]) deleteAtNoLock(index int) {
+	syncSlice.s = append(syncSlice.s[:index], syncSlice.s[index+1:]...)
+}
+
+func (syncSlice *SyncSlice[T]) rangeNoLock(rangeFunc RangeFunc[T]) {
+	for i, e := range syncSlice.s {
+		stop := rangeFunc(i, e)
+		if stop {
+			return
+		}
+	}
+}

+ 77 - 0
syncutils/sync_slice_test.go

@@ -0,0 +1,77 @@
+package syncutils
+
+import (
+	"fmt"
+	"strconv"
+	"testing"
+)
+
+func TestSyncSlice(t *testing.T) {
+	syncSlice := NewSyncSlice([]string{"aaa", "bbb", "ccc"}, false)
+
+	syncSlice.Append("ddd")
+	syncSlice.Range(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	syncSlice.DeleteAt(3)
+	syncSlice.Range(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	syncSlice.Lock()
+
+	syncSlice.AppendNoLock("ddd")
+	syncSlice.RangeNoLock(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	syncSlice.DeleteAtNoLock(3)
+	syncSlice.RangeNoLock(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	syncSlice.Unlock()
+
+	rwSyncSlice := NewSyncSlice([]string{"aaa", "bbb", "ccc"}, true)
+
+	rwSyncSlice.Append("ddd")
+	rwSyncSlice.Range(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	rwSyncSlice.DeleteAt(3)
+	rwSyncSlice.Range(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	rwSyncSlice.Lock()
+
+	rwSyncSlice.AppendNoLock("ddd")
+	rwSyncSlice.RangeNoLock(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	rwSyncSlice.DeleteAtNoLock(3)
+	rwSyncSlice.RangeNoLock(func(index int, e string) bool {
+		fmt.Println("Index", strconv.Itoa(index)+":", e)
+		return false
+	})
+	fmt.Println()
+
+	rwSyncSlice.Unlock()
+}