Files
bl/common/utils/concurrent-swiss-map/concurrent_swiss_map.go
昔念 d74652373c ```
refactor(socket): 更新广播和退出逻辑中的类型引用

更新socket服务器中广播功能和退出功能的代码,
将player.Player类型替换为player.ClientData类型,
并相应调整方法调用以适应新的数据结构。

feat(map): 添加LoadOrStore方法支持

在并发安全的swiss map中新增LoadOrStore方法,
提供原子性的加载或存储功能,增强map的操作能力。

refactor(login): 优化登录逻辑中的玩家获取方式

重构登录控制器中获取玩家对象的方式,
直接从
2026-03-16 22:30:12 +08:00

218 lines
4.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package csmap
import (
"encoding/json"
"sync"
"sync/atomic"
)
// CsMap 基于官方 sync.Map 重构,完全兼容原有接口
type CsMap[K comparable, V any] struct {
inner sync.Map // 核心替换为官方 sync.Map
}
// 以下配置方法保留(兼容原有调用方式,但内部无实际作用)
type OptFunc[K comparable, V any] func(o *CsMap[K, V])
// New 创建基于 sync.Map 的并发安全 Map兼容原有配置参数参数无实际作用
func New[K comparable, V any](options ...OptFunc[K, V]) *CsMap[K, V] {
m := &CsMap[K, V]{}
// 遍历配置项(兼容原有代码,无实际逻辑)
for _, option := range options {
option(m)
}
return m
}
// 保留原有配置方法(空实现,保证接口兼容)
func WithShardCount[K comparable, V any](count uint64) func(csMap *CsMap[K, V]) {
return func(csMap *CsMap[K, V]) {}
}
func WithCustomHasher[K comparable, V any](h func(key K) uint64) func(csMap *CsMap[K, V]) {
return func(csMap *CsMap[K, V]) {}
}
func WithSize[K comparable, V any](size uint64) func(csMap *CsMap[K, V]) {
return func(csMap *CsMap[K, V]) {}
}
// -------------------------- 核心操作方法(基于 sync.Map 实现) --------------------------
// Store 存储键值对,兼容原有接口
func (m *CsMap[K, V]) Store(key K, value V) {
m.inner.Store(key, value)
}
func (m *CsMap[K, V]) LoadOrStore(key K, value V) (actual V, loaded bool) {
T, OK := m.inner.LoadOrStore(key, value)
return T.(V), OK
}
// Delete 删除指定键,返回是否删除成功
func (m *CsMap[K, V]) Delete(key K) bool {
// sync.Map.Delete 无返回值,需先 Load 判断是否存在
_, ok := m.inner.Load(key)
if ok {
m.inner.Delete(key)
}
return ok
}
// DeleteIf 满足条件时删除
func (m *CsMap[K, V]) DeleteIf(key K, condition func(value V) bool) bool {
// 先 Load 获取值,再判断条件
val, ok := m.inner.Load(key)
if !ok {
return false
}
v, okCast := val.(V)
if !okCast {
return false
}
if condition(v) {
m.inner.Delete(key)
return true
}
return false
}
// Load 获取指定键的值
func (m *CsMap[K, V]) Load(key K) (V, bool) {
var zero V
val, ok := m.inner.Load(key)
if !ok {
return zero, false
}
// 类型断言(保证类型安全)
v, okCast := val.(V)
if !okCast {
return zero, false
}
return v, true
}
// Has 判断键是否存在
func (m *CsMap[K, V]) Has(key K) bool {
_, ok := m.inner.Load(key)
return ok
}
// Clear 清空所有数据
func (m *CsMap[K, V]) Clear() {
// sync.Map 无直接 Clear 方法,通过 Range 遍历删除
m.inner.Range(func(key, value any) bool {
m.inner.Delete(key)
return true
})
}
// Count 统计元素数量
func (m *CsMap[K, V]) Count() int {
count := 0
m.inner.Range(func(key, value any) bool {
count++
return true
})
return count
}
// SetIfAbsent 仅当键不存在时设置值
func (m *CsMap[K, V]) SetIfAbsent(key K, value V) {
m.inner.LoadOrStore(key, value)
}
// SetIf 根据条件设置值
func (m *CsMap[K, V]) SetIf(key K, conditionFn func(previousValue V, previousFound bool) (value V, set bool)) {
prevVal, found := m.inner.Load(key)
var prevV V
if found {
prevV, _ = prevVal.(V)
}
// 执行条件函数
newVal, set := conditionFn(prevV, found)
if set {
m.inner.Store(key, newVal)
}
}
// SetIfPresent 仅当键存在时设置值
func (m *CsMap[K, V]) SetIfPresent(key K, value V) {
// 先判断是否存在,再设置
if _, ok := m.inner.Load(key); ok {
m.inner.Store(key, value)
}
}
// IsEmpty 判断是否为空
func (m *CsMap[K, V]) IsEmpty() bool {
return m.Count() == 0
}
// Tuple 保留原有结构体(兼容序列化逻辑)
type Tuple[K comparable, V any] struct {
Key K
Val V
}
// -------------------------- 关键修复Range 方法(无锁阻塞风险) --------------------------
func (m *CsMap[K, V]) Range(f func(key K, value V) (stop bool)) {
if f == nil {
return
}
var stopFlag atomic.Bool
// 基于 sync.Map 的 Range 实现,无额外 goroutine/channel
m.inner.Range(func(key, value any) bool {
// 检测终止标志
if stopFlag.Load() {
return false
}
// 类型断言
k, okK := key.(K)
v, okV := value.(V)
if !okK || !okV {
return true // 类型不匹配时跳过,继续遍历
}
// 执行用户回调
if f(k, v) {
stopFlag.Store(true)
return false // 终止遍历
}
return true
})
}
// -------------------------- 序列化方法(兼容原有逻辑) --------------------------
func (m *CsMap[K, V]) MarshalJSON() ([]byte, error) {
tmp := make(map[K]V, m.Count())
m.Range(func(key K, value V) (stop bool) {
tmp[key] = value
return false
})
return json.Marshal(tmp)
}
func (m *CsMap[K, V]) UnmarshalJSON(b []byte) error {
tmp := make(map[K]V)
if err := json.Unmarshal(b, &tmp); err != nil {
return err
}
// 清空原有数据
m.Clear()
// 批量存储
for key, val := range tmp {
m.Store(key, val)
}
return nil
}
// -------------------------- 移除所有无用的旧方法produce/listen 等) --------------------------