package anidb
-import "sync"
+import (
+ "github.com/EliasFleckenstein03/go-fscache"
+ "strings"
+ "sync"
+)
+
+type notification interface{}
type intentStruct struct {
sync.Mutex
- chs []chan Cacheable
+ chs []chan notification
}
type intentMapStruct struct {
m: map[string]*intentStruct{},
}
+func intentKey(key ...fscache.CacheKey) string {
+ return strings.Join(fscache.Stringify(key...), "-")
+}
+
// Register a channel to be notified when the specified keys are notified.
// Returns whether the caller was the first to register intent for the given
// keys.
// Cache checks should be done after registering intent, since it's possible to
// register Intent while a Notify is running, and the Notify is done after
// setting the cache.
-func (m *intentMapStruct) Intent(ch chan Cacheable, keys ...cacheKey) bool {
- key := cachePath(keys...)
+func (m *intentMapStruct) Intent(ch chan notification, keys ...fscache.CacheKey) bool {
+ key := intentKey(keys...)
m.intentLock.Lock()
defer m.intentLock.Unlock()
//
// The intentStruct can be directly unlocked, or given to Free to also
// remove it from the intent map.
-func (m *intentMapStruct) LockIntent(keys ...cacheKey) *intentStruct {
+func (m *intentMapStruct) LockIntent(keys ...fscache.CacheKey) *intentStruct {
m.Lock()
defer m.Unlock()
return m._lockIntent(keys...)
}
-func (m *intentMapStruct) _lockIntent(keys ...cacheKey) *intentStruct {
- s, ok := m.m[cachePath(keys...)]
+func (m *intentMapStruct) _lockIntent(keys ...fscache.CacheKey) *intentStruct {
+ s, ok := m.m[intentKey(keys...)]
if !ok {
return nil
}
}
// Removes the given intent from the intent map and unlocks the intentStruct.
-func (m *intentMapStruct) Free(is *intentStruct, keys ...cacheKey) {
+func (m *intentMapStruct) Free(is *intentStruct, keys ...fscache.CacheKey) {
m.Lock()
defer m.Unlock()
m._free(is, keys...)
}
-func (m *intentMapStruct) _free(is *intentStruct, keys ...cacheKey) {
+func (m *intentMapStruct) _free(is *intentStruct, keys ...fscache.CacheKey) {
// deletes the key before unlocking, Intent needs to recheck key status
- delete(m.m, cachePath(keys...))
+ delete(m.m, intentKey(keys...))
// better than unlocking then deleting -- could delete a "brand new" entry
- is.Unlock()
+ if is != nil {
+ is.Unlock()
+ }
}
// Notifies and closes all channels that are listening for the specified keys;
// also removes them from the intent map.
//
// Should be called after setting the cache.
-func (m *intentMapStruct) NotifyClose(v Cacheable, keys ...cacheKey) {
+func (m *intentMapStruct) NotifyClose(v notification, keys ...fscache.CacheKey) {
m.Lock()
defer m.Unlock()
is := m._lockIntent(keys...)
defer m._free(is, keys...)
- is.NotifyClose(v)
+ if is != nil {
+ is.NotifyClose(v)
+ }
}
// Closes all channels that are listening for the specified keys
// and removes them from the intent map.
-func (m *intentMapStruct) Close(keys ...cacheKey) {
+func (m *intentMapStruct) Close(keys ...fscache.CacheKey) {
m.Lock()
defer m.Unlock()
is := m._lockIntent(keys...)
defer m._free(is, keys...)
- is.Close()
+ if is != nil {
+ is.Close()
+ }
}
// Notifies all channels that are listening for the specified keys,
// but doesn't close or remove them from the intent map.
-func (m *intentMapStruct) Notify(v Cacheable, keys ...cacheKey) {
+func (m *intentMapStruct) Notify(v notification, keys ...fscache.CacheKey) {
m.Lock()
defer m.Unlock()
is := m._lockIntent(keys...)
- defer is.Unlock()
+ if is != nil {
+ defer is.Unlock()
- is.Notify(v)
+ is.Notify(v)
+ }
}
// NOTE: does not lock the stuct
-func (s *intentStruct) Notify(v Cacheable) {
+func (s *intentStruct) Notify(v notification) {
for _, ch := range s.chs {
- ch <- v
+ if ch != nil {
+ ch <- v
+ }
}
}
// NOTE: does not lock the struct
func (s *intentStruct) Close() {
for _, ch := range s.chs {
- close(ch)
+ if ch != nil {
+ close(ch)
+ }
}
s.chs = nil
}
// NOTE: does not lock the struct
-func (s *intentStruct) NotifyClose(v Cacheable) {
+func (s *intentStruct) NotifyClose(v notification) {
for _, ch := range s.chs {
- ch <- v
- close(ch)
+ if ch != nil {
+ ch <- v
+ close(ch)
+ }
}
s.chs = nil
}