Browse Source

修改syncvar

yjp 1 year ago
parent
commit
7030feaae8
4 changed files with 129 additions and 290 deletions
  1. 0 178
      syncutils/sync_slice.go
  2. 0 112
      syncutils/sync_slice_test.go
  3. 32 0
      syncutils/sync_var.go
  4. 97 0
      syncutils/sync_var_test.go

+ 0 - 178
syncutils/sync_slice.go

@@ -1,178 +0,0 @@
-package syncutils
-
-import "sync"
-
-// RangeFunc Range方法回调函数
-type RangeFunc[T any] func(index int, e T) bool
-
-// SyncSlice 并发安全的slice
-type SyncSlice[T any] struct {
-	writeLocker sync.Locker
-	readLocker  sync.Locker
-	s           []T
-}
-
-// NewSyncSlice 创建SyncSlice
-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,
-	}
-}
-
-// Lock 手动上写锁
-func (syncSlice *SyncSlice[T]) Lock() {
-	syncSlice.writeLocker.Lock()
-}
-
-// Unlock 手动解写锁
-func (syncSlice *SyncSlice[T]) Unlock() {
-	syncSlice.writeLocker.Unlock()
-}
-
-// RLock 手动上读锁
-func (syncSlice *SyncSlice[T]) RLock() {
-	syncSlice.readLocker.Lock()
-}
-
-// RUnlock 手动解读锁
-func (syncSlice *SyncSlice[T]) RUnlock() {
-	syncSlice.readLocker.Unlock()
-}
-
-// AppendNoLock 不上锁添加元素
-func (syncSlice *SyncSlice[T]) AppendNoLock(elements ...T) {
-	if elements == nil || len(elements) == 0 {
-		return
-	}
-
-	syncSlice.appendNoLock(elements...)
-}
-
-// DeleteAtNoLock 不上锁删除元素
-func (syncSlice *SyncSlice[T]) DeleteAtNoLock(index int) T {
-	if index < 0 {
-		var zero T
-		return zero
-	}
-
-	return syncSlice.deleteAtNoLock(index)
-}
-
-// RangeNoLock 不上锁遍历slice
-func (syncSlice *SyncSlice[T]) RangeNoLock(rangeFunc RangeFunc[T]) {
-	if rangeFunc == nil {
-		return
-	}
-
-	syncSlice.rangeNoLock(rangeFunc)
-}
-
-// LenNoLock 不上锁获取slice长度
-func (syncSlice *SyncSlice[T]) LenNoLock() int {
-	return syncSlice.lenNoLock()
-}
-
-// CapNoLock 不上锁获取slice容量
-func (syncSlice *SyncSlice[T]) CapNoLock() int {
-	return syncSlice.capNoLock()
-}
-
-// Append 上锁添加元素
-func (syncSlice *SyncSlice[T]) Append(elements ...T) {
-	if elements == nil || len(elements) == 0 {
-		return
-	}
-
-	syncSlice.writeLocker.Lock()
-	defer syncSlice.writeLocker.Unlock()
-
-	syncSlice.appendNoLock(elements...)
-}
-
-// DeleteAt 上锁删除元素
-func (syncSlice *SyncSlice[T]) DeleteAt(index int) T {
-	if index < 0 {
-		var zero T
-		return zero
-	}
-
-	syncSlice.writeLocker.Lock()
-	defer syncSlice.writeLocker.Unlock()
-
-	return syncSlice.deleteAtNoLock(index)
-}
-
-// Range 上锁遍历slice
-func (syncSlice *SyncSlice[T]) Range(rangeFunc RangeFunc[T]) {
-	if rangeFunc == nil {
-		return
-	}
-
-	syncSlice.readLocker.Lock()
-	defer syncSlice.readLocker.Unlock()
-
-	syncSlice.rangeNoLock(rangeFunc)
-}
-
-// Len 上锁获取slice长度
-func (syncSlice *SyncSlice[T]) Len() int {
-	syncSlice.readLocker.Lock()
-	defer syncSlice.readLocker.Unlock()
-
-	return syncSlice.lenNoLock()
-}
-
-// Cap 上锁获取slice容量
-func (syncSlice *SyncSlice[T]) Cap() int {
-	syncSlice.readLocker.Lock()
-	defer syncSlice.readLocker.Unlock()
-
-	return syncSlice.capNoLock()
-}
-
-func (syncSlice *SyncSlice[T]) appendNoLock(elements ...T) {
-	syncSlice.s = append(syncSlice.s, elements...)
-}
-
-func (syncSlice *SyncSlice[T]) deleteAtNoLock(index int) T {
-	if len(syncSlice.s)-1 < index {
-		var zero T
-		return zero
-	}
-
-	v := syncSlice.s[index]
-	syncSlice.s = append(syncSlice.s[:index], syncSlice.s[index+1:]...)
-	return v
-}
-
-func (syncSlice *SyncSlice[T]) rangeNoLock(rangeFunc RangeFunc[T]) {
-	for i, e := range syncSlice.s {
-		stop := rangeFunc(i, e)
-		if stop {
-			return
-		}
-	}
-}
-
-func (syncSlice *SyncSlice[T]) lenNoLock() int {
-	return len(syncSlice.s)
-}
-
-func (syncSlice *SyncSlice[T]) capNoLock() int {
-	return cap(syncSlice.s)
-}

+ 0 - 112
syncutils/sync_slice_test.go

@@ -1,112 +0,0 @@
-package syncutils
-
-import (
-	"fmt"
-	"strconv"
-	"testing"
-)
-
-func TestSyncSlice(t *testing.T) {
-	syncSlice := NewSyncSlice([]string{"aaa", "bbb", "ccc"}, false)
-
-	syncSlice.Append("ddd")
-	fmt.Println("Len:", syncSlice.Len())
-	fmt.Println("Cap:", syncSlice.Cap())
-	fmt.Println()
-
-	syncSlice.Range(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	fmt.Println()
-
-	deleted := syncSlice.DeleteAt(3)
-	fmt.Println("Deleted:", deleted)
-	fmt.Println()
-
-	syncSlice.Range(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	fmt.Println()
-
-	syncSlice.Lock()
-
-	syncSlice.AppendNoLock("ddd")
-	fmt.Println("Len:", syncSlice.LenNoLock())
-	fmt.Println("Cap:", syncSlice.CapNoLock())
-	fmt.Println()
-
-	syncSlice.RangeNoLock(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	fmt.Println()
-
-	deleted = syncSlice.DeleteAtNoLock(3)
-	fmt.Println("Deleted:", deleted)
-	fmt.Println()
-
-	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")
-	fmt.Println("Len:", rwSyncSlice.Len())
-	fmt.Println("Cap:", rwSyncSlice.Cap())
-	fmt.Println()
-
-	rwSyncSlice.Range(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	fmt.Println()
-
-	deleted = rwSyncSlice.DeleteAt(3)
-	fmt.Println("Deleted:", deleted)
-	fmt.Println()
-
-	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.Unlock()
-
-	rwSyncSlice.RLock()
-	fmt.Println("Len:", rwSyncSlice.LenNoLock())
-	fmt.Println("Cap:", rwSyncSlice.CapNoLock())
-	fmt.Println()
-
-	rwSyncSlice.RangeNoLock(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	rwSyncSlice.RUnlock()
-
-	fmt.Println()
-
-	rwSyncSlice.Lock()
-	deleted = rwSyncSlice.DeleteAtNoLock(3)
-	rwSyncSlice.Unlock()
-	fmt.Println("Deleted:", deleted)
-	fmt.Println()
-
-	rwSyncSlice.RLock()
-	rwSyncSlice.RangeNoLock(func(index int, e string) bool {
-		fmt.Println("Index", strconv.Itoa(index)+":", e)
-		return false
-	})
-	rwSyncSlice.RUnlock()
-
-	fmt.Println()
-}

+ 32 - 0
syncutils/sync_var.go

@@ -2,12 +2,20 @@ package syncutils
 
 import "sync"
 
+// WriteVarFunc 回调变量用来写的函数
+type WriteVarFunc[T any] func(v T) T
+
+// ReadVarFunc 回调变量用来读的函数
+type ReadVarFunc[T any] func(v T)
+
+// SyncVar 线程安全的变量封装
 type SyncVar[T any] struct {
 	writeLocker sync.Locker
 	readLocker  sync.Locker
 	v           T
 }
 
+// NewSyncVar 创建线程安全的变量
 func NewSyncVar[T any](v T, isRWMutex bool) *SyncVar[T] {
 	var writeLocker sync.Locker
 	var readLocker sync.Locker
@@ -28,3 +36,27 @@ func NewSyncVar[T any](v T, isRWMutex bool) *SyncVar[T] {
 		v:           v,
 	}
 }
+
+// ForWrite 为写而获取变量
+func (syncVar *SyncVar[T]) ForWrite(writeVarFunc WriteVarFunc[T]) {
+	if writeVarFunc == nil {
+		return
+	}
+
+	syncVar.writeLocker.Lock()
+	defer syncVar.writeLocker.Unlock()
+
+	syncVar.v = writeVarFunc(syncVar.v)
+}
+
+// ForRead 为写而获取变量
+func (syncVar *SyncVar[T]) ForRead(readVarFunc ReadVarFunc[T]) {
+	if readVarFunc == nil {
+		return
+	}
+
+	syncVar.readLocker.Lock()
+	defer syncVar.readLocker.Unlock()
+
+	readVarFunc(syncVar.v)
+}

+ 97 - 0
syncutils/sync_var_test.go

@@ -0,0 +1,97 @@
+package syncutils
+
+import (
+	"fmt"
+	"strconv"
+	"testing"
+)
+
+func TestSyncVar(t *testing.T) {
+	syncSlice := NewSyncVar([]string{"aaa", "bbb", "ccc"}, false)
+
+	syncSlice.ForWrite(func(s []string) []string {
+		return append(s, "ddd")
+	})
+
+	syncSlice.ForRead(func(s []string) {
+		for i, v := range s {
+			fmt.Println("Index", strconv.Itoa(i)+":", v)
+		}
+		fmt.Println()
+	})
+
+	syncSlice.ForWrite(func(s []string) []string {
+		for i, v := range s {
+			if v == "ddd" {
+				return append(s[:i], s[i+1:]...)
+			}
+		}
+
+		return s
+	})
+
+	syncSlice.ForRead(func(s []string) {
+		for i, v := range s {
+			fmt.Println("Index", strconv.Itoa(i)+":", v)
+		}
+		fmt.Println()
+	})
+
+	rwSyncSlice := NewSyncVar([]string{"aaa", "bbb", "ccc"}, true)
+
+	rwSyncSlice.ForWrite(func(s []string) []string {
+		return append(s, "ddd")
+	})
+
+	rwSyncSlice.ForRead(func(s []string) {
+		for i, v := range s {
+			fmt.Println("Index", strconv.Itoa(i)+":", v)
+		}
+		fmt.Println()
+	})
+
+	rwSyncSlice.ForWrite(func(s []string) []string {
+		for i, v := range s {
+			if v == "ddd" {
+				return append(s[:i], s[i+1:]...)
+			}
+		}
+
+		return s
+	})
+
+	rwSyncSlice.ForRead(func(s []string) {
+		for i, v := range s {
+			fmt.Println("Index", strconv.Itoa(i)+":", v)
+		}
+		fmt.Println()
+	})
+
+	type Student struct {
+		Name string
+		Age  int
+	}
+
+	rwSyncStruct := NewSyncVar(&Student{
+		Name: "test",
+		Age:  10,
+	}, true)
+
+	rwSyncStruct.ForRead(func(v *Student) {
+		fmt.Println("Name:", v.Name)
+		fmt.Println("Age:", v.Age)
+		fmt.Println()
+	})
+
+	rwSyncStruct.ForWrite(func(v *Student) *Student {
+		v.Name = "test_new"
+		v.Age = 20
+		return v
+	})
+
+	rwSyncStruct.ForRead(func(v *Student) {
+		fmt.Println("Name:", v.Name)
+		fmt.Println("Age:", v.Age)
+		fmt.Println()
+	})
+}