// deletes the key before unlocking, Intent needs to recheck key status
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;
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
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,
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 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 notification) {
for _, ch := range s.chs {
- ch <- v
- close(ch)
+ if ch != nil {
+ ch <- v
+ close(ch)
+ }
}
s.chs = nil
}
}
key := []fscache.CacheKey{"mylist-anime", user.UID, aid}
- ic := make(chan notification, 1)
+ ic := make(chan notification, 2)
go func() { ch <- (<-ic).(*MyListAnime); close(ch) }()
if intentMap.Intent(ic, key...) {
return
if f := e.FID.File(); f != nil {
f.LID[user.UID] = e.LID
cacheFile(f)
+
+ now := time.Now()
+ mla := <-adb.MyListAnime(f.AID)
+
+ key := []fscache.CacheKey{"mylist-anime", user.UID, f.AID}
+
+ intentMap.Intent(nil, key...)
+
+ if mla == nil {
+ mla = &MyListAnime{}
+ }
+
+ if mla.Cached.Before(now) {
+ el := mla.EpisodesWithState[e.MyListState]
+ el.Add(f.EpisodeNumber)
+ mla.EpisodesWithState[e.MyListState] = el
+
+ if e.DateWatched.IsZero() {
+ mla.WatchedEpisodes.Sub(f.EpisodeNumber)
+ } else {
+ mla.WatchedEpisodes.Add(f.EpisodeNumber)
+ }
+
+ eg := mla.EpisodesPerGroup[f.GID]
+ eg.Add(f.EpisodeNumber)
+ mla.EpisodesPerGroup[f.GID] = eg
+
+ if mla.Cached.IsZero() {
+ // as attractive as such an ancient mtime would be,
+ // few filesystems can represent it; just make it old enough
+ mla.Cached = now.Add(-2 * MyListCacheDuration)
+ }
+
+ Cache.Set(mla, key...)
+ Cache.Chtime(mla.Cached, key...)
+ }
+
+ // this unfortunately races if Intent returns true:
+ // only the first NotifyClose call actually notifies
+ go intentMap.NotifyClose(mla, key...)
}
CacheSet(e, "mylist", "by-fid", e.FID, user.UID)
}
- // TODO: Add mylist info to Anime, also update there
CacheSet(e, "mylist", e.LID)
return e