From 4c571a0d1b7e249062d8535adf2ac69b80d3a2fb Mon Sep 17 00:00:00 2001 From: qydysky <32743305+qydysky@users.noreply.github.com> Date: Sun, 12 Mar 2023 21:35:22 +0800 Subject: [PATCH] fix --- .github/workflows/test.yml | 1 + pool/Pool.go | 24 ++++++++++++-------- pool/Pool_test.go | 10 +++++++-- reqf/Reqf_test.go | 32 +++++++++++++++++++++++++++ sync/Map.go | 45 +++++--------------------------------- sync/Map_test.go | 16 +++++++++++--- 6 files changed, 75 insertions(+), 53 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0f8c093..f890c1d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -31,3 +31,4 @@ jobs: go test -count 1 -timeout 5s -v -race github.com/qydysky/part/pool go test -count 1 -timeout 10s -v -race github.com/qydysky/part/funcCtrl go test -count 1 -timeout 30s -v -race github.com/qydysky/part/msgq + go test -count 1 -timeout 5s -v -race github.com/qydysky/part/sync diff --git a/pool/Pool.go b/pool/Pool.go index 25e3c9d..f7c4b24 100644 --- a/pool/Pool.go +++ b/pool/Pool.go @@ -10,10 +10,15 @@ type Buf[T any] struct { inUse func(*T) bool reuseF func(*T) *T poolF func(*T) *T - buf []*T + buf []poolItem[T] l sync.RWMutex } +type poolItem[T any] struct { + i *T + pooled bool +} + // 创建池 // // NewF: func() *T 新值 @@ -40,7 +45,7 @@ func (t *Buf[T]) PoolInUse() (inUse int) { defer t.l.RUnlock() for i := 0; i < len(t.buf); i++ { - if t.inUse(t.buf[i]) { + if !t.buf[i].pooled && t.inUse(t.buf[i].i) { inUse++ } } @@ -60,8 +65,7 @@ func (t *Buf[T]) Trim() { defer t.l.Unlock() for i := 0; i < len(t.buf); i++ { - if !t.inUse(t.buf[i]) { - t.buf[i] = nil + if t.buf[i].pooled && !t.inUse(t.buf[i].i) { t.buf = append(t.buf[:i], t.buf[i+1:]...) i-- } @@ -73,8 +77,9 @@ func (t *Buf[T]) Get() *T { defer t.l.Unlock() for i := 0; i < len(t.buf); i++ { - if !t.inUse(t.buf[i]) { - return t.reuseF(t.buf[i]) + if t.buf[i].pooled && !t.inUse(t.buf[i].i) { + t.buf[i].pooled = false + return t.reuseF(t.buf[i].i) } } @@ -91,8 +96,9 @@ func (t *Buf[T]) Put(item ...*T) { var cu = 0 for i := 0; i < len(t.buf); i++ { - if !t.inUse(t.buf[i]) { - t.buf[i] = t.poolF(item[cu]) + if t.buf[i].pooled && !t.inUse(t.buf[i].i) { + t.buf[i].i = t.poolF(item[cu]) + t.buf[i].pooled = true cu++ if cu >= len(item) { return @@ -101,6 +107,6 @@ func (t *Buf[T]) Put(item ...*T) { } for i := cu; i < len(item) && t.maxsize > len(t.buf); i++ { - t.buf = append(t.buf, t.poolF(item[i])) + t.buf = append(t.buf, poolItem[T]{t.poolF(item[i]), true}) } } diff --git a/pool/Pool_test.go b/pool/Pool_test.go index 51152da..4fa847c 100644 --- a/pool/Pool_test.go +++ b/pool/Pool_test.go @@ -44,12 +44,18 @@ func TestXxx(t *testing.T) { t.Fatal() } - b.Put(c1) c1.v = false + var c3 = b.Get() var c3p = uintptr(unsafe.Pointer(c3)) - if c1p != c3p || len(c1.d) != 0 || b.PoolInUse() != 1 || b.PoolSum() != 1 { + if c1p == c3p || len(c1.d) == 0 || b.PoolInUse() != 0 || b.PoolSum() != 0 { t.Fatal() } + + b.Put(c1) + + if len(c1.d) == 0 || b.PoolInUse() != 0 || b.PoolSum() != 1 { + t.Fatal(len(c1.d) != 0, b.PoolInUse() != 0, b.PoolSum() != 1) + } } diff --git a/reqf/Reqf_test.go b/reqf/Reqf_test.go index da6438d..50274ac 100644 --- a/reqf/Reqf_test.go +++ b/reqf/Reqf_test.go @@ -3,6 +3,7 @@ package part import ( "bytes" "context" + "encoding/json" "io" "net/http" "testing" @@ -58,6 +59,22 @@ func init() { time.Sleep(time.Second) } }, + `/json`: func(w http.ResponseWriter, _ *http.Request) { + w.WriteHeader(200) + flusher, flushSupport := w.(http.Flusher) + if flushSupport { + flusher.Flush() + } + w.Write([]byte("{\"a\":")) + if flushSupport { + flusher.Flush() + } + time.Sleep(time.Millisecond * 20) + w.Write([]byte("123}")) + if flushSupport { + flusher.Flush() + } + }, `/exit`: func(_ http.ResponseWriter, _ *http.Request) { s.Server.Shutdown(context.Background()) }, @@ -98,6 +115,21 @@ func Test_req(t *testing.T) { } } +type J struct { + A int `json:"a"` +} + +func Test_req12(t *testing.T) { + r := New() + r.Reqf(Rval{ + Url: "http://" + addr + "/json", + Timeout: 10 * 1000, + Retry: 2, + }) + var j J + json.Unmarshal(r.Respon, &j) +} + func Test_req2(t *testing.T) { r := New() { diff --git a/sync/Map.go b/sync/Map.go index c1c961c..fb62b0c 100644 --- a/sync/Map.go +++ b/sync/Map.go @@ -1,10 +1,8 @@ package part import ( - "runtime" "sync" "sync/atomic" - "unsafe" ) type Map struct { @@ -40,41 +38,10 @@ func (t *Map) Len() int { return int(t.size.Load()) } -type ptr struct { - p unsafe.Pointer -} - -func (t *ptr) tryStore(v *any) { - t.p = unsafe.Pointer(v) - // atomic.StorePointer(&t.p, unsafe.Pointer(v)) -} - -func (t *ptr) tryLoad() (any, bool) { - // p := atomic.LoadPointer(&t.p) - if t.p == nil { - return nil, false - } - return *(*any)(t.p), true -} - -type pLock struct { - i unsafe.Pointer - busy unsafe.Pointer -} - -func (l *pLock) Lock() { - if l.busy == nil { - l.busy = unsafe.Pointer(&struct{}{}) - } - for !atomic.CompareAndSwapPointer(&l.i, nil, l.busy) { - runtime.Gosched() - } -} - -func (l *pLock) Locking() bool { - return atomic.LoadPointer(&l.i) != nil -} - -func (l *pLock) Unlock() { - atomic.CompareAndSwapPointer(&l.i, l.busy, nil) +func (t *Map) Copy() (m Map) { + t.Range(func(k, v any) bool { + m.Store(k, v) + return true + }) + return } diff --git a/sync/Map_test.go b/sync/Map_test.go index 4f13cd8..1457b20 100644 --- a/sync/Map_test.go +++ b/sync/Map_test.go @@ -26,7 +26,6 @@ func Test_customMap(t *testing.T) { //range c.Store(1, 1) c.Range(func(key, value interface{}) bool { - t.Log(key, value) if key.(int) != value.(int) { t.Error(`3`) } @@ -37,12 +36,10 @@ func Test_customMap(t *testing.T) { if v, ok := c.Load(0); ok && v != nil { t.Error(`4`) } - t.Log(c.Len()) c.Delete(1) if v, ok := c.Load(1); ok && v != nil { t.Error(`6`) } - t.Log(c.Len()) } func Benchmark_customMap_Set(b *testing.B) { @@ -167,6 +164,19 @@ func Test_Range(t *testing.T) { } } +func Test_1(t *testing.T) { + var c Map + c.Store("o", []string{"111", "222"}) + m := c.Copy() + if v, ok := m.LoadV("o").([]string); !ok || len(v) != 2 || v[0] != "111" || v[1] != "222" { + t.Fatal() + } + c.Delete("o") + if v, ok := m.LoadV("o").([]string); !ok || len(v) != 2 || v[0] != "111" || v[1] != "222" { + t.Fatal() + } +} + func Benchmark_customMap_Range(b *testing.B) { var c Map var w = &sync.WaitGroup{} -- 2.39.2