diff --git a/game/activity/activity.go b/game/activity/activity.go index 2fe3e81..959f54a 100644 --- a/game/activity/activity.go +++ b/game/activity/activity.go @@ -115,7 +115,7 @@ type Activity[Type, ID generic.Basic] struct { tickerKey string // 定时器 key retention time.Duration // 活动数据保留时间 retentionKey string // 保留定时器 key - mutex sync.Mutex // 互斥锁 + mutex sync.RWMutex getLastNewDayTime func() time.Time // 获取上次新的一天的时间 setLastNewDayTime func(time.Time) // 设置上次新的一天的时间 diff --git a/game/activity/controller.go b/game/activity/controller.go index 1c2bf3a..7231c13 100644 --- a/game/activity/controller.go +++ b/game/activity/controller.go @@ -1,6 +1,9 @@ package activity -import "github.com/kercylan98/minotaur/utils/generic" +import ( + "github.com/kercylan98/minotaur/utils/generic" + "sync" +) type none byte @@ -52,59 +55,81 @@ type Controller[Type, ID generic.Basic, Data any, EntityID generic.Basic, Entity entityInitializer func(activityType Type, activityId ID, data map[ID]*DataMeta[Data], entityData map[ID]map[EntityID]*EntityDataMeta[EntityData]) // 实体数据初始化器 globalData map[ID]*DataMeta[Data] // 全局数据 entityData map[ID]map[EntityID]*EntityDataMeta[EntityData] // 实体数据 + mutex sync.RWMutex } // GetGlobalData 获取特定活动全局数据 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetGlobalData(activityId ID) Data { slf.globalDataLoader(activityId) + slf.mutex.RLock() + defer slf.mutex.RUnlock() return slf.globalData[activityId].Data } // GetEntityData 获取特定活动实体数据 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetEntityData(activityId ID, entityId EntityID) EntityData { slf.entityDataLoader(activityId, entityId) + slf.mutex.RLock() + defer slf.mutex.RUnlock() return slf.entityData[activityId][entityId].Data } // GetAllEntityData 获取特定活动所有实体数据 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) GetAllEntityData(activityId ID) map[EntityID]EntityData { var entities = make(map[EntityID]EntityData) + slf.mutex.RLock() for k, v := range slf.entityData[activityId] { entities[k] = v.Data } + slf.mutex.RUnlock() return entities } // IsOpen 活动是否开启 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpen(activityId ID) bool { + slf.mutex.RLock() activity, exist := slf.activities[activityId] + slf.mutex.RUnlock() if !exist { return false } + activity.mutex.RLock() + defer activity.mutex.RUnlock() return activity.state == stateStarted } // IsShow 活动是否展示 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsShow(activityId ID) bool { + slf.mutex.RLock() activity, exist := slf.activities[activityId] + slf.mutex.RUnlock() if !exist { return false } + activity.mutex.RLock() + defer activity.mutex.RUnlock() return activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded)) } // IsOpenOrShow 活动是否开启或展示 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) IsOpenOrShow(activityId ID) bool { + slf.mutex.RLock() activity, exist := slf.activities[activityId] + slf.mutex.RUnlock() if !exist { return false } + + activity.mutex.RLock() + defer activity.mutex.RUnlock() return activity.state == stateStarted || activity.state == stateUpcoming || (activity.state == stateEnded && activity.tl.HasState(stateExtendedShowEnded)) } // Refresh 刷新活动 func (slf *Controller[Type, ID, Data, EntityID, EntityData]) Refresh(activityId ID) { + slf.mutex.RLock() activity, exist := slf.activities[activityId] + slf.mutex.RUnlock() if !exist { return } diff --git a/game/activity/controller_internal.go b/game/activity/controller_internal.go index 88814f1..c459cd3 100644 --- a/game/activity/controller_internal.go +++ b/game/activity/controller_internal.go @@ -32,11 +32,15 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent defer controllersLock.Unlock() controller.activities = make(map[ID]*Activity[Type, ID]) controllerGlobalDataReader = append(controllerGlobalDataReader, func(handler func(activityType, activityId, data any)) { + controller.mutex.RLock() + defer controller.mutex.RUnlock() for activityId, data := range controller.globalData { handler(activityType, activityId, data) } }) controllerEntityDataReader = append(controllerEntityDataReader, func(handler func(activityType, activityId, entityId, data any)) { + controller.mutex.RLock() + defer controller.mutex.RUnlock() for activityId, entities := range controller.entityData { for entityId, data := range entities { handler(activityType, activityId, entityId, data) @@ -51,6 +55,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent tof = tof.Elem() } controller.globalDataLoader = func(activityId any) { + controller.mutex.Lock() + defer controller.mutex.Unlock() var id = activityId.(ID) if _, exist := controller.globalData[id]; exist { return @@ -71,6 +77,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent tof = tof.Elem() } controller.entityDataLoader = func(activityId any, entityId any) { + controller.mutex.Lock() + defer controller.mutex.Unlock() var id, eid = activityId.(ID), entityId.(EntityID) entities, exist := controller.entityData[id] if !exist { @@ -92,6 +100,7 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent controllers[activityType] = controller controllerRegisters[activityType] = func(activityType, activityId any) (act any, optionInitCallback func(activity any)) { var at, ai = activityType.(Type), activityId.(ID) + controller.mutex.Lock() activity, exist := controller.activities[ai] if !exist { activity = &Activity[Type, ID]{ @@ -107,6 +116,7 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent }, } } + controller.mutex.Unlock() controller.activities[activity.id] = activity return activity, func(activity any) { act := activity.(*Activity[Type, ID]) @@ -120,6 +130,8 @@ func regController[Type, ID generic.Basic, Data any, EntityID generic.Basic, Ent } controllerReset[activityType] = func(activityId any) { var id = activityId.(ID) + controller.mutex.Lock() + defer controller.mutex.Unlock() delete(controller.globalData, id) delete(controller.entityData, id) }