package lucifer3 import ( "fmt" "sync/atomic" ) type Service interface { Active() bool ServiceID() ServiceID Handle(bus *EventBus, event Event, sender ServiceID) } type ServiceID struct { Kind ServiceKind ID int64 Name string } func (s *ServiceID) String() string { if s == nil { return "BROADCAST" } if s.Kind == SKNotService { return "EXTERNAL" } if s.Name != "" { return s.Name } else { return fmt.Sprintf("%s[%d]", s.Kind.String(), s.ID) } } type ServiceCommon struct { serviceID ServiceID inactive uint32 } func (s *ServiceCommon) Active() bool { return atomic.LoadUint32(&s.inactive) == 0 } func (s *ServiceCommon) markInactive() { atomic.StoreUint32(&s.inactive, 1) } func (s *ServiceCommon) ServiceID() ServiceID { return s.serviceID } type ServiceKind int func (s ServiceKind) String() string { switch s { case SKSingleton: return "Singleton" case SKStorage: return "Storage" case SKDeviceHub: return "DeviceHub" case SKEffect: return "Effect" case SKCallback: return "Callback" case SKNotService: return "NotService" default: return "???" } } const ( SKNotService ServiceKind = iota SKSingleton SKStorage SKDeviceHub SKEffect SKCallback ) type callbackService struct { ServiceCommon cb func(event Event, sender ServiceID) bool } func (c *callbackService) Handle(_ *EventBus, event Event, sender ServiceID) { if !c.cb(event, sender) { c.markInactive() } } var nextCallback int64 = 0 func newCallbackService(cb func(event Event, sender ServiceID) bool) Service { return &callbackService{ ServiceCommon: ServiceCommon{ serviceID: ServiceID{ Kind: SKCallback, ID: atomic.AddInt64(&nextCallback, 1), }, inactive: 0, }, cb: cb, } }