You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
59 lines
1.4 KiB
59 lines
1.4 KiB
package exchange |
|
|
|
import "sig-pub/pkg/utils/collect" |
|
|
|
type Publisher[TID comparable, T any] struct { |
|
m0 *collect.ConcurrentMap[string, map[TID]T] |
|
} |
|
|
|
func NewPublisher[TID comparable, T any](concurrentLevel int) *Publisher[TID, T] { |
|
m := collect.NewConcurrentMap[string, map[TID]T](concurrentLevel, func(k string) string { return k }) |
|
return &Publisher[TID, T]{ |
|
m0: m, |
|
} |
|
} |
|
|
|
// Subscribe 订阅 |
|
func (p *Publisher[TID, T]) Subscribe(k string, tid TID, ele T) { |
|
_ = p.m0.LoadAndUpdate(k, func(v map[TID]T) (remove bool, nextV map[TID]T) { |
|
if v == nil { |
|
v = make(map[TID]T) |
|
} |
|
v[tid] = ele |
|
return false, v |
|
}) |
|
} |
|
|
|
// Unsubscribe 取消订阅 |
|
func (p *Publisher[TID, T]) Unsubscribe(k string, tid TID) { |
|
p.m0.LoadAndUpdate(k, func(v map[TID]T) (remove bool, nextV map[TID]T) { |
|
delete(v, tid) |
|
if len(v) == 0 { |
|
return true, v |
|
} |
|
return false, v |
|
}) |
|
} |
|
|
|
// UnsubscribeAll 取消所有订阅 |
|
func (p *Publisher[TID, T]) UnsubscribeAll(tid TID) { |
|
p.m0.RangeUpdate(func(key string, v map[TID]T) (next bool, remove bool, newV map[TID]T) { |
|
delete(v, tid) |
|
remove = len(v) == 0 |
|
return true, remove, v |
|
}) |
|
} |
|
|
|
// Publisher 获取匹配的 subscribers |
|
func (p *Publisher[TID, T]) Publisher(k string) (subs []T) { |
|
p.m0.LoadRLock(k, func(subIds map[TID]T, ok bool) { |
|
if !ok { |
|
return |
|
} |
|
for _, sub := range subIds { |
|
subs = append(subs, sub) |
|
} |
|
}) |
|
// todo cache subs |
|
return |
|
}
|
|
|