From f39550329a465e73647a485f9c01962835e6652a Mon Sep 17 00:00:00 2001 From: boyce <6549168@qq.com> Date: Tue, 4 Jun 2019 20:58:20 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=AE=89=E5=85=A8map?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- util/example_test.go | 99 +++++------------------- util/mapex.go | 178 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 165 insertions(+), 112 deletions(-) diff --git a/util/example_test.go b/util/example_test.go index db4cbbe..e233ba3 100644 --- a/util/example_test.go +++ b/util/example_test.go @@ -2,91 +2,34 @@ package util_test import ( "fmt" - "github.com/name5566/leaf/util" + "testing" + + "github.com/duanhf2012/origin/util" ) -func ExampleMap() { - m := new(util.Map) - - fmt.Println(m.Get("key")) - m.Set("key", "value") - fmt.Println(m.Get("key")) - m.Del("key") - fmt.Println(m.Get("key")) - - m.Set(1, "1") - m.Set(2, 2) - m.Set("3", 3) - - fmt.Println(m.Len()) - - // Output: - // - // value - // - // 3 -} - -func ExampleRandGroup() { - i := util.RandGroup(0, 0, 50, 50) - switch i { - case 2, 3: - fmt.Println("ok") +func ExampleMap(t *testing.T) { + maps := util.NewMapEx() + for i := 0; i < 10000; i++ { + maps.Set(i, i) } - // Output: - // ok -} - -func ExampleRandInterval() { - v := util.RandInterval(-1, 1) - switch v { - case -1, 0, 1: - fmt.Println("ok") + for i := 0; i < 10000; i++ { + ret := maps.Get(i) + if ret.(int) != i { + fmt.Printf("cannot find i:%d\n", i) + } } - // Output: - // ok -} - -func ExampleRandIntervalN() { - r := util.RandIntervalN(-1, 0, 2) - if r[0] == -1 && r[1] == 0 || - r[0] == 0 && r[1] == -1 { - fmt.Println("ok") + for i := 0; i < 10000; i++ { + maps.LockSet(i, func(key interface{}, val interface{}) interface{} { + return val.(int) + 1 + }) } - // Output: - // ok -} - -func ExampleDeepCopy() { - src := []int{1, 2, 3} - - var dst []int - util.DeepCopy(&dst, &src) - - for _, v := range dst { - fmt.Println(v) + for i := 0; i < 10000; i++ { + ret := maps.Get(i) + if ret.(int) != i { + fmt.Printf("cannot find i:%d\n", i) + } } - - // Output: - // 1 - // 2 - // 3 -} - -func ExampleDeepClone() { - src := []int{1, 2, 3} - - dst := util.DeepClone(src).([]int) - - for _, v := range dst { - fmt.Println(v) - } - - // Output: - // 1 - // 2 - // 3 } diff --git a/util/mapex.go b/util/mapex.go index f9daa7e..e83bfe7 100644 --- a/util/mapex.go +++ b/util/mapex.go @@ -2,92 +2,202 @@ package util import ( "fmt" + "sync" "github.com/duanhf2012/origin/util/hash" ) const ( - DEFAULT_MAX_HASH_NUM = 100 + DEFAULT_SAFE_MAP_MAX_HASH_NUM = 10 ) type MapEx struct { - m []Map - hashMapNum uint + sync.RWMutex + m []map[interface{}]interface{} + l []sync.RWMutex + hashMapNum int +} + +func (m *MapEx) Init(hashMapNum int) { + m.hashMapNum = hashMapNum + + m.m = []map[interface{}]interface{}{} + m.l = []sync.RWMutex{} + + for i := 0; i < hashMapNum; i++ { + m.m = append(m.m, make(map[interface{}]interface{})) + m.l = append(m.l, sync.RWMutex{}) + } } func NewMapEx() *MapEx { mapEx := MapEx{} - mapEx.Init(DEFAULT_MAX_HASH_NUM) + mapEx.Init(DEFAULT_SAFE_MAP_MAX_HASH_NUM) return &mapEx } -func (m *MapEx) Init(hashMapNum uint) { - var i uint - for i = 0; i < hashMapNum; i++ { - m.m = append(m.m, Map{}) - } - - m.hashMapNum = hashMapNum -} - func (m *MapEx) ClearMap() { - var i uint - for i = 0; i < m.hashMapNum; i++ { - m.m[i].ClearMap() + for i := 0; i < DEFAULT_SAFE_MAP_MAX_HASH_NUM; i++ { + m.l[i].Lock() + m.m[i] = map[interface{}]interface{}{} + m.l[i].Unlock() } } -func (m *MapEx) GetHashCode(key interface{}) uint { - return hash.HashNumber(fmt.Sprint(key)) +func (m *MapEx) GetHashCode(key interface{}) int { + return int(hash.HashNumber(fmt.Sprint(key))) } -func (m *MapEx) GetMapByKey(key interface{}) *Map { +func (m *MapEx) GetArrayIdByKey(key interface{}) int { idx := m.GetHashCode(key) % m.hashMapNum + if idx > m.hashMapNum { + return -1 + } + + return idx +} + +func (m *MapEx) GetMapByKey(key interface{}) map[interface{}]interface{} { + idx := m.GetArrayIdByKey(key) if idx < 0 || idx > m.hashMapNum { return nil } - return &m.m[idx] + return m.m[idx] } -func (m *MapEx) Get(key interface{}) interface{} { +func (m *MapEx) UnsafeGet(key interface{}) interface{} { + mapData := m.GetMapByKey(key) if mapData == nil { return nil } - return mapData.Get(key) + + val, ok := mapData[key] + if ok == false { + return nil + } + + return val +} + +func (m *MapEx) Get(key interface{}) interface{} { + idx := m.GetArrayIdByKey(key) + if idx < 0 || idx > m.hashMapNum { + return nil + } + + m.l[idx].RLock() + defer m.l[idx].RUnlock() + + val := m.m[idx] + ret, ok := val[key] + if ok == false { + return nil + } + return ret } func (m *MapEx) Set(key interface{}, value interface{}) { + idx := m.GetArrayIdByKey(key) + if idx < 0 || idx > m.hashMapNum { + return + } + + m.l[idx].Lock() + defer m.l[idx].Unlock() + + val := m.m[idx] + val[key] = value +} + +func (m *MapEx) UnsafeDel(key interface{}) { mapData := m.GetMapByKey(key) if mapData == nil { return } - mapData.Set(key, value) + delete(mapData, key) } func (m *MapEx) Del(key interface{}) { - - mapData := m.GetMapByKey(key) - if mapData == nil { + idx := m.GetArrayIdByKey(key) + if idx < 0 || idx > m.hashMapNum { return } - mapData.Del(key) + m.l[idx].Lock() + defer m.l[idx].Unlock() + + val := m.m[idx] + delete(val, key) +} + +func (m *MapEx) Len() int { + lens := 0 + for i := 0; i < m.hashMapNum; i++ { + m.l[i].RLock() + lens += len(m.m[i]) + m.l[i].RUnlock() + } + + return lens } func (m *MapEx) RLockRange(f func(key interface{}, value interface{})) { - var i uint - for i = 0; i < m.hashMapNum; i++ { - m.m[i].RLockRange(f) + for i := 0; i < m.hashMapNum; i++ { + m.l[i].RLock() + for key, val := range m.m[i] { + f(key, val) + } + m.l[i].RUnlock() } - } func (m *MapEx) LockRange(f func(key interface{}, value interface{})) { - var i uint - for i = 0; i < m.hashMapNum; i++ { - m.m[i].LockRange(f) + for i := 0; i < m.hashMapNum; i++ { + m.l[i].Lock() + for key, val := range m.m[i] { + f(key, val) + } + m.l[i].Unlock() } } + +func (m *MapEx) LockGet(key interface{}, f func(value interface{})) { + idx := m.GetArrayIdByKey(key) + if idx < 0 || idx > m.hashMapNum { + f(nil) + return + } + + m.l[idx].Lock() + val := m.m[idx] + ret, ok := val[key] + if ok == false { + f(nil) + } else { + f(ret) + } + m.l[idx].Unlock() +} + +func (m *MapEx) LockSet(key interface{}, f func(value interface{}) interface{}) { + idx := m.GetArrayIdByKey(key) + if idx < 0 || idx > m.hashMapNum { + f(nil) + return + } + + m.l[idx].Lock() + val := m.m[idx] + ret, ok := val[key] + + if ok == false { + val[key] = f(nil) + } else { + val[key] = f(ret) + } + + m.l[idx].Unlock() +}