feat: 房间管理器实现
This commit is contained in:
parent
d26ef3aca6
commit
45c855a516
|
@ -0,0 +1,12 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import "errors"
|
||||||
|
|
||||||
|
var (
|
||||||
|
// ErrRoomNotExist 房间不存在
|
||||||
|
ErrRoomNotExist = errors.New("room not exist")
|
||||||
|
// ErrRoomPlayerFull 房间人数已满
|
||||||
|
ErrRoomPlayerFull = errors.New("room player full")
|
||||||
|
// ErrPlayerNotExist 玩家不存在
|
||||||
|
ErrPlayerNotExist = errors.New("player not exist")
|
||||||
|
)
|
|
@ -0,0 +1,95 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
|
type (
|
||||||
|
// PlayerJoinRoomEventHandle 玩家加入房间事件处理函数
|
||||||
|
PlayerJoinRoomEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P)
|
||||||
|
// PlayerLeaveRoomEventHandle 玩家离开房间事件处理函数
|
||||||
|
PlayerLeaveRoomEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, player P)
|
||||||
|
// PlayerKickedOutEventHandle 玩家被踢出房间事件处理函数
|
||||||
|
PlayerKickedOutEventHandle[PID comparable, P game.Player[PID], R Room[PID, P]] func(room R, executor, kicked PID, reason string)
|
||||||
|
)
|
||||||
|
|
||||||
|
func newEvent[PID comparable, P game.Player[PID], R Room[PID, P]]() *event[PID, P, R] {
|
||||||
|
return &event[PID, P, R]{
|
||||||
|
playerJoinRoomEventRoomHandles: make(map[int64][]PlayerJoinRoomEventHandle[PID, P, R]),
|
||||||
|
playerLeaveRoomEventRoomHandles: make(map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]),
|
||||||
|
playerKickedOutEventRoomHandles: make(map[int64][]PlayerKickedOutEventHandle[PID, P, R]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type event[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
||||||
|
playerJoinRoomEventHandles []PlayerJoinRoomEventHandle[PID, P, R]
|
||||||
|
playerJoinRoomEventRoomHandles map[int64][]PlayerJoinRoomEventHandle[PID, P, R]
|
||||||
|
playerLeaveRoomEventHandles []PlayerLeaveRoomEventHandle[PID, P, R]
|
||||||
|
playerLeaveRoomEventRoomHandles map[int64][]PlayerLeaveRoomEventHandle[PID, P, R]
|
||||||
|
playerKickedOutEventHandles []PlayerKickedOutEventHandle[PID, P, R]
|
||||||
|
playerKickedOutEventRoomHandles map[int64][]PlayerKickedOutEventHandle[PID, P, R]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (slf *event[PID, P, R]) unReg(guid int64) {
|
||||||
|
delete(slf.playerJoinRoomEventRoomHandles, guid)
|
||||||
|
delete(slf.playerLeaveRoomEventRoomHandles, guid)
|
||||||
|
delete(slf.playerKickedOutEventRoomHandles, guid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerJoinRoomEvent(handle PlayerJoinRoomEventHandle[PID, P, R]) {
|
||||||
|
slf.playerJoinRoomEventHandles = append(slf.playerJoinRoomEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerJoinRoomEvent 玩家进入房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerJoinRoomEvent(room R, player P) {
|
||||||
|
for _, handle := range slf.playerJoinRoomEventHandles {
|
||||||
|
handle(room, player)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerJoinRoomEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerJoinRoomEventWithRoom 玩家进入房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerJoinRoomEventWithRoom(room R, handle PlayerJoinRoomEventHandle[PID, P, R]) {
|
||||||
|
slf.playerJoinRoomEventRoomHandles[room.GetGuid()] = append(slf.playerJoinRoomEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerLeaveRoomEvent 玩家离开房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerLeaveRoomEvent(handle PlayerLeaveRoomEventHandle[PID, P, R]) {
|
||||||
|
slf.playerLeaveRoomEventHandles = append(slf.playerLeaveRoomEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerLeaveRoomEventWithRoom 玩家离开房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerLeaveRoomEventWithRoom(room R, handle PlayerLeaveRoomEventHandle[PID, P, R]) {
|
||||||
|
slf.playerLeaveRoomEventRoomHandles[room.GetGuid()] = append(slf.playerLeaveRoomEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerLeaveRoomEvent 玩家离开房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerLeaveRoomEvent(room R, player P) {
|
||||||
|
for _, handle := range slf.playerLeaveRoomEventHandles {
|
||||||
|
handle(room, player)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerLeaveRoomEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, player)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerKickedOutEvent 玩家被踢出房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerKickedOutEvent(handle PlayerKickedOutEventHandle[PID, P, R]) {
|
||||||
|
slf.playerKickedOutEventHandles = append(slf.playerKickedOutEventHandles, handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RegPlayerKickedOutEventWithRoom 玩家被踢出房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) RegPlayerKickedOutEventWithRoom(room R, handle PlayerKickedOutEventHandle[PID, P, R]) {
|
||||||
|
slf.playerKickedOutEventRoomHandles[room.GetGuid()] = append(slf.playerKickedOutEventRoomHandles[room.GetGuid()], handle)
|
||||||
|
}
|
||||||
|
|
||||||
|
// OnPlayerKickedOutEvent 玩家被踢出房间时将立即执行被注册的事件处理函数
|
||||||
|
func (slf *event[PID, P, R]) OnPlayerKickedOutEvent(room R, executor, kicked PID, reason string) {
|
||||||
|
for _, handle := range slf.playerKickedOutEventHandles {
|
||||||
|
handle(room, executor, kicked, reason)
|
||||||
|
}
|
||||||
|
for _, handle := range slf.playerKickedOutEventRoomHandles[room.GetGuid()] {
|
||||||
|
handle(room, executor, kicked, reason)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
|
type info[PlayerID comparable, P game.Player[PlayerID], R Room[PlayerID, P]] struct {
|
||||||
|
room R
|
||||||
|
playerLimit int // 玩家人数上限, <= 0 表示无限制
|
||||||
|
}
|
|
@ -0,0 +1,259 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/kercylan98/minotaur/game"
|
||||||
|
"github.com/kercylan98/minotaur/utils/concurrent"
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewManager 创建房间管理器
|
||||||
|
func NewManager[PID comparable, P game.Player[PID], R Room[PID, P]]() *Manager[PID, P, R] {
|
||||||
|
manager := &Manager[PID, P, R]{
|
||||||
|
event: newEvent[PID, P, R](),
|
||||||
|
rooms: concurrent.NewBalanceMap[int64, *info[PID, P, R]](),
|
||||||
|
players: concurrent.NewBalanceMap[PID, P](),
|
||||||
|
pr: concurrent.NewBalanceMap[PID, map[int64]struct{}](),
|
||||||
|
}
|
||||||
|
|
||||||
|
return manager
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manager 房间管理器
|
||||||
|
type Manager[PID comparable, P game.Player[PID], R Room[PID, P]] struct {
|
||||||
|
*event[PID, P, R]
|
||||||
|
rooms *concurrent.BalanceMap[int64, *info[PID, P, R]] // 所有房间
|
||||||
|
players *concurrent.BalanceMap[PID, P] // 所有加入房间的玩家
|
||||||
|
pr *concurrent.BalanceMap[PID, map[int64]struct{}] // 玩家所在房间
|
||||||
|
rp *concurrent.BalanceMap[int64, map[PID]struct{}] // 房间中的玩家
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// CreateRoom 创建房间
|
||||||
|
func (slf *Manager[PID, P, R]) CreateRoom(room R) {
|
||||||
|
roomInfo := &info[PID, P, R]{room: room}
|
||||||
|
slf.rooms.Set(room.GetGuid(), roomInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReleaseRoom 释放房间
|
||||||
|
func (slf *Manager[PID, P, R]) ReleaseRoom(guid int64) {
|
||||||
|
slf.unReg(guid)
|
||||||
|
slf.rooms.Delete(guid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoom 获取房间
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoom(guid int64) R {
|
||||||
|
return slf.rooms.Get(guid).room
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exist 检查房间是否存在
|
||||||
|
func (slf *Manager[PID, P, R]) Exist(guid int64) bool {
|
||||||
|
return slf.rooms.Exist(guid)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRooms 获取所有房间
|
||||||
|
func (slf *Manager[PID, P, R]) GetRooms() map[int64]R {
|
||||||
|
var rooms = make(map[int64]R)
|
||||||
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
|
for id, info := range m {
|
||||||
|
rooms[id] = info.room
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return rooms
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoomCount 获取房间数量
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoomCount() int {
|
||||||
|
return slf.rooms.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoomPlayerCount 获取房间中玩家数量
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoomPlayerCount(guid int64) int {
|
||||||
|
var count int
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
count = len(m[guid])
|
||||||
|
})
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// ExistPlayer 检查玩家是否在任一房间内
|
||||||
|
func (slf *Manager[PID, P, R]) ExistPlayer(id PID) bool {
|
||||||
|
return slf.players.Exist(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InRoom 检查玩家是否在指定房间内
|
||||||
|
func (slf *Manager[PID, P, R]) InRoom(id PID, guid int64) bool {
|
||||||
|
var in bool
|
||||||
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
|
rooms, exist := m[id]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, in = rooms[guid]
|
||||||
|
})
|
||||||
|
return in
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayer 获取玩家
|
||||||
|
func (slf *Manager[PID, P, R]) GetPlayer(id PID) P {
|
||||||
|
return slf.players.Get(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayers 获取所有玩家
|
||||||
|
func (slf *Manager[PID, P, R]) GetPlayers() *concurrent.BalanceMap[PID, P] {
|
||||||
|
return slf.players
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerCount 获取玩家数量
|
||||||
|
func (slf *Manager[PID, P, R]) GetPlayerCount() int {
|
||||||
|
return slf.players.Size()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerRoom 获取玩家所在房间
|
||||||
|
func (slf *Manager[PID, P, R]) GetPlayerRoom(id PID) []R {
|
||||||
|
var result = make([]R, 0)
|
||||||
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
|
rooms, exist := m[id]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for id := range rooms {
|
||||||
|
result = append(result, slf.rooms.Get(id).room)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetPlayerRoomCount 获取玩家所在房间数量
|
||||||
|
func (slf *Manager[PID, P, R]) GetPlayerRoomCount(id PID) int {
|
||||||
|
var count int
|
||||||
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
|
count = len(m[id])
|
||||||
|
})
|
||||||
|
return count
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoomPlayer 获取房间中的玩家
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoomPlayer(roomId int64, playerId PID) P {
|
||||||
|
var player P
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, exist = players[playerId]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
player = slf.players.Get(playerId)
|
||||||
|
})
|
||||||
|
return player
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoomPlayers 获取房间中的玩家
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoomPlayers(guid int64) map[PID]P {
|
||||||
|
var result = make(map[PID]P)
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[guid]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for id := range players {
|
||||||
|
result[id] = slf.players.Get(id)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetRoomPlayerLimit 获取房间中的玩家数量上限
|
||||||
|
func (slf *Manager[PID, P, R]) GetRoomPlayerLimit(guid int64) int {
|
||||||
|
return slf.rooms.Get(guid).playerLimit
|
||||||
|
}
|
||||||
|
|
||||||
|
// Leave 使玩家离开房间
|
||||||
|
func (slf *Manager[PID, P, R]) Leave(roomId int64, player P) {
|
||||||
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
|
room, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slf.OnPlayerLeaveRoomEvent(room.room, player)
|
||||||
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
|
rooms, exist := m[player.GetID()]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(rooms, roomId)
|
||||||
|
})
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
delete(players, player.GetID())
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Join 使玩家加入房间
|
||||||
|
func (slf *Manager[PID, P, R]) Join(player P, roomId int64) error {
|
||||||
|
var err error
|
||||||
|
slf.rooms.Atom(func(m map[int64]*info[PID, P, R]) {
|
||||||
|
room, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
err = ErrRoomNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if room.playerLimit > 0 && room.playerLimit <= slf.GetRoomPlayerCount(roomId) {
|
||||||
|
err = ErrRoomPlayerFull
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slf.pr.Atom(func(m map[PID]map[int64]struct{}) {
|
||||||
|
rooms, exist := m[player.GetID()]
|
||||||
|
if !exist {
|
||||||
|
rooms = make(map[int64]struct{})
|
||||||
|
m[player.GetID()] = rooms
|
||||||
|
}
|
||||||
|
rooms[roomId] = struct{}{}
|
||||||
|
})
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
players = make(map[PID]struct{})
|
||||||
|
m[roomId] = players
|
||||||
|
}
|
||||||
|
players[player.GetID()] = struct{}{}
|
||||||
|
})
|
||||||
|
slf.players.Set(player.GetID(), player)
|
||||||
|
slf.OnPlayerJoinRoomEvent(room.room, player)
|
||||||
|
})
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// KickOut 以某种原因踢出特定玩家
|
||||||
|
// - 该函数不会校验任何权限相关的内容,调用后将直接踢出玩家
|
||||||
|
func (slf *Manager[PID, P, R]) KickOut(roomId int64, executor, kicked PID, reason string) error {
|
||||||
|
var err error
|
||||||
|
var room R
|
||||||
|
slf.rp.Atom(func(m map[int64]map[PID]struct{}) {
|
||||||
|
players, exist := m[roomId]
|
||||||
|
if !exist {
|
||||||
|
err = ErrPlayerNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, exist = players[executor]
|
||||||
|
if !exist {
|
||||||
|
err = ErrPlayerNotExist
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, exist = players[kicked]
|
||||||
|
if !exist {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
room = slf.rooms.Get(roomId).room
|
||||||
|
})
|
||||||
|
if err == nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
slf.OnPlayerKickedOutEvent(room, executor, kicked, reason)
|
||||||
|
slf.Leave(roomId, slf.players.Get(kicked))
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
package room
|
||||||
|
|
||||||
|
import "github.com/kercylan98/minotaur/game"
|
||||||
|
|
||||||
|
// Room 房间类似于简版的游戏世界(World),不过没有游戏实体
|
||||||
|
type Room[PlayerID comparable, P game.Player[PlayerID]] interface {
|
||||||
|
// GetGuid 获取房间的唯一标识符
|
||||||
|
GetGuid() int64
|
||||||
|
// GetPlayerLimit 获取玩家人数上限
|
||||||
|
GetPlayerLimit() int
|
||||||
|
// GetPlayer 根据玩家id获取玩家
|
||||||
|
GetPlayer(id PlayerID) P
|
||||||
|
// GetPlayers 获取房间中的所有玩家
|
||||||
|
GetPlayers() map[PlayerID]P
|
||||||
|
// GetPlayerCount 获取玩家数量
|
||||||
|
GetPlayerCount() int
|
||||||
|
// IsExistPlayer 检查房间中是否存在特定玩家
|
||||||
|
IsExistPlayer(id PlayerID) bool
|
||||||
|
// IsOwner 检查玩家是否是房主
|
||||||
|
IsOwner(id PlayerID) bool
|
||||||
|
// ChangeOwner 设置玩家为房主
|
||||||
|
ChangeOwner(id PlayerID)
|
||||||
|
|
||||||
|
// Join 使特定玩家加入房间
|
||||||
|
Join(player P) error
|
||||||
|
// Leave 使特定玩家离开房间
|
||||||
|
Leave(id PlayerID)
|
||||||
|
// KickOut 将特定玩家踢出房间
|
||||||
|
KickOut(id, target PlayerID, reason string) error
|
||||||
|
}
|
|
@ -21,150 +21,183 @@ func NewBalanceMap[Key comparable, value any](options ...BalanceMapOption[Key, v
|
||||||
type BalanceMap[Key comparable, Value any] struct {
|
type BalanceMap[Key comparable, Value any] struct {
|
||||||
lock sync.RWMutex
|
lock sync.RWMutex
|
||||||
data map[Key]Value
|
data map[Key]Value
|
||||||
|
atom bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set 设置一个值
|
// Set 设置一个值
|
||||||
func (slf *BalanceMap[Key, Value]) Set(key Key, value Value) {
|
func (slf *BalanceMap[Key, Value]) Set(key Key, value Value) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
defer slf.lock.Unlock()
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
slf.data[key] = value
|
slf.data[key] = value
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get 获取一个值
|
// Get 获取一个值
|
||||||
func (slf *BalanceMap[Key, Value]) Get(key Key) Value {
|
func (slf *BalanceMap[Key, Value]) Get(key Key) Value {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
defer slf.lock.RUnlock()
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
return slf.data[key]
|
return slf.data[key]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Atom 原子操作
|
// Atom 原子操作
|
||||||
func (slf *BalanceMap[Key, Value]) Atom(handle func(m map[Key]Value)) {
|
func (slf *BalanceMap[Key, Value]) Atom(handle func(m map[Key]Value)) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
handle(slf.data)
|
handle(slf.data)
|
||||||
slf.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exist 判断是否存在
|
// Exist 判断是否存在
|
||||||
func (slf *BalanceMap[Key, Value]) Exist(key Key) bool {
|
func (slf *BalanceMap[Key, Value]) Exist(key Key) bool {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
_, exist := slf.data[key]
|
_, exist := slf.data[key]
|
||||||
slf.lock.RUnlock()
|
|
||||||
return exist
|
return exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetExist 获取一个值并判断是否存在
|
// GetExist 获取一个值并判断是否存在
|
||||||
func (slf *BalanceMap[Key, Value]) GetExist(key Key) (Value, bool) {
|
func (slf *BalanceMap[Key, Value]) GetExist(key Key) (Value, bool) {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
value, exist := slf.data[key]
|
value, exist := slf.data[key]
|
||||||
slf.lock.RUnlock()
|
|
||||||
return value, exist
|
return value, exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete 删除一个值
|
// Delete 删除一个值
|
||||||
func (slf *BalanceMap[Key, Value]) Delete(key Key) {
|
func (slf *BalanceMap[Key, Value]) Delete(key Key) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
delete(slf.data, key)
|
delete(slf.data, key)
|
||||||
defer slf.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteGet 删除一个值并返回
|
// DeleteGet 删除一个值并返回
|
||||||
func (slf *BalanceMap[Key, Value]) DeleteGet(key Key) Value {
|
func (slf *BalanceMap[Key, Value]) DeleteGet(key Key) Value {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
v := slf.data[key]
|
v := slf.data[key]
|
||||||
delete(slf.data, key)
|
delete(slf.data, key)
|
||||||
slf.lock.Unlock()
|
|
||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteGetExist 删除一个值并返回是否存在
|
// DeleteGetExist 删除一个值并返回是否存在
|
||||||
func (slf *BalanceMap[Key, Value]) DeleteGetExist(key Key) (Value, bool) {
|
func (slf *BalanceMap[Key, Value]) DeleteGetExist(key Key) (Value, bool) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
v, exist := slf.data[key]
|
v, exist := slf.data[key]
|
||||||
delete(slf.data, key)
|
delete(slf.data, key)
|
||||||
defer slf.lock.Unlock()
|
|
||||||
return v, exist
|
return v, exist
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteExist 删除一个值并返回是否存在
|
// DeleteExist 删除一个值并返回是否存在
|
||||||
func (slf *BalanceMap[Key, Value]) DeleteExist(key Key) bool {
|
func (slf *BalanceMap[Key, Value]) DeleteExist(key Key) bool {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
if _, exist := slf.data[key]; !exist {
|
if _, exist := slf.data[key]; !exist {
|
||||||
slf.lock.Unlock()
|
slf.lock.Unlock()
|
||||||
return exist
|
return exist
|
||||||
}
|
}
|
||||||
delete(slf.data, key)
|
delete(slf.data, key)
|
||||||
slf.lock.Unlock()
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear 清空
|
// Clear 清空
|
||||||
func (slf *BalanceMap[Key, Value]) Clear() {
|
func (slf *BalanceMap[Key, Value]) Clear() {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
for k := range slf.data {
|
for k := range slf.data {
|
||||||
delete(slf.data, k)
|
delete(slf.data, k)
|
||||||
}
|
}
|
||||||
slf.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ClearHandle 清空并处理
|
// ClearHandle 清空并处理
|
||||||
func (slf *BalanceMap[Key, Value]) ClearHandle(handle func(key Key, value Value)) {
|
func (slf *BalanceMap[Key, Value]) ClearHandle(handle func(key Key, value Value)) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
for k, v := range slf.data {
|
for k, v := range slf.data {
|
||||||
handle(k, v)
|
handle(k, v)
|
||||||
delete(slf.data, k)
|
delete(slf.data, k)
|
||||||
}
|
}
|
||||||
slf.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Range 遍历所有值,如果 handle 返回 true 则停止遍历
|
// Range 遍历所有值,如果 handle 返回 true 则停止遍历
|
||||||
func (slf *BalanceMap[Key, Value]) Range(handle func(key Key, value Value) bool) {
|
func (slf *BalanceMap[Key, Value]) Range(handle func(key Key, value Value) bool) {
|
||||||
slf.lock.Lock()
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
defer slf.lock.Unlock()
|
||||||
|
}
|
||||||
for k, v := range slf.data {
|
for k, v := range slf.data {
|
||||||
key, value := k, v
|
key, value := k, v
|
||||||
if handle(key, value) {
|
if handle(key, value) {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
slf.lock.Unlock()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keys 获取所有的键
|
// Keys 获取所有的键
|
||||||
func (slf *BalanceMap[Key, Value]) Keys() []Key {
|
func (slf *BalanceMap[Key, Value]) Keys() []Key {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
var s = make([]Key, 0, len(slf.data))
|
var s = make([]Key, 0, len(slf.data))
|
||||||
for k := range slf.data {
|
for k := range slf.data {
|
||||||
s = append(s, k)
|
s = append(s, k)
|
||||||
}
|
}
|
||||||
slf.lock.RUnlock()
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Slice 获取所有的值
|
// Slice 获取所有的值
|
||||||
func (slf *BalanceMap[Key, Value]) Slice() []Value {
|
func (slf *BalanceMap[Key, Value]) Slice() []Value {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
var s = make([]Value, 0, len(slf.data))
|
var s = make([]Value, 0, len(slf.data))
|
||||||
for _, v := range slf.data {
|
for _, v := range slf.data {
|
||||||
s = append(s, v)
|
s = append(s, v)
|
||||||
}
|
}
|
||||||
slf.lock.RUnlock()
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map 转换为普通 map
|
// Map 转换为普通 map
|
||||||
func (slf *BalanceMap[Key, Value]) Map() map[Key]Value {
|
func (slf *BalanceMap[Key, Value]) Map() map[Key]Value {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
var m = make(map[Key]Value)
|
var m = make(map[Key]Value)
|
||||||
for k, v := range slf.data {
|
for k, v := range slf.data {
|
||||||
m[k] = v
|
m[k] = v
|
||||||
}
|
}
|
||||||
slf.lock.RUnlock()
|
|
||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
// Size 获取数量
|
// Size 获取数量
|
||||||
func (slf *BalanceMap[Key, Value]) Size() int {
|
func (slf *BalanceMap[Key, Value]) Size() int {
|
||||||
slf.lock.RLock()
|
if !slf.atom {
|
||||||
defer slf.lock.RUnlock()
|
slf.lock.RLock()
|
||||||
|
defer slf.lock.RUnlock()
|
||||||
|
}
|
||||||
return len(slf.data)
|
return len(slf.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,11 +208,13 @@ func (slf *BalanceMap[Key, Value]) MarshalJSON() ([]byte, error) {
|
||||||
|
|
||||||
func (slf *BalanceMap[Key, Value]) UnmarshalJSON(bytes []byte) error {
|
func (slf *BalanceMap[Key, Value]) UnmarshalJSON(bytes []byte) error {
|
||||||
var m = make(map[Key]Value)
|
var m = make(map[Key]Value)
|
||||||
|
if !slf.atom {
|
||||||
|
slf.lock.Lock()
|
||||||
|
slf.lock.Unlock()
|
||||||
|
}
|
||||||
if err := json.Unmarshal(bytes, &m); err != nil {
|
if err := json.Unmarshal(bytes, &m); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slf.lock.Lock()
|
|
||||||
slf.data = m
|
slf.data = m
|
||||||
slf.lock.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue