xref: /MusicPlayer2/MusicPlayer2/ListCache.h (revision 965ce478a79b0d21e8a6e2ade0490efa175855dd)
1 #pragma once
2 #include "ListItem.h"
3 
4 // 为UI缓存CRecentList持有的指定类型数据
5 // 并提供适合UI直接使用的特殊接口(要求在同一个线程调用那些小写的方法)
6 class CListCache
7 {
8 public:
CListCache(ListType type)9     CListCache(ListType type) : m_type(type) { ASSERT(type != LT_MAX); }
~CListCache()10     ~CListCache() {};
11 
12 ////////////////////////////////////////////////////////////////////////////////
13 //  以下所有小写的方法要求总是在同一个线程调用才能够保证线程安全
14 //  如果reload返回true表示数据可能有变化,必要重绘
15 
16     // 重新载入数据
17     bool reload();
18     // 获取ListItem总数
size()19     size_t size() const { return m_ui_list.size(); }
20     // 获取位于特定index的ListItem,不允许超过size()的参数
at(size_t index)21     const ListItem& at(size_t index) const { return m_ui_list.at(index); }
22     // 当前播放的列表在m_ui_list中时返回其在m_ui_list的索引,否则返回-1
playing_index()23     int playing_index() const { return m_ui_current_play_index; }
24 
25 ////////////////////////////////////////////////////////////////////////////////
26 //  以下方法直接基于CRecentList的数据提供,有线程安全保证,但因为锁粒度问题不能用于绘制UI
27 //  作为CRecentList的友元,使用其中数据时同时也要维持其互斥量保护的数据不外露
28 //  当上面的小写方法在自绘UI线程中使用时以下方法供主线程的消息处理使用
29 //  但要求一次消息处理期间只能调用一个方法一次,以避开多次加锁间的同步问题 (可以在这里添加适合各自情况的各种方法)
30 
31     // 获取位于特定index的ListItem(index越界时返回空项目)
32     ListItem GetItem(size_t index) const;
33     // 获取特定ListItem的index(ListItem不存在时返回-1)
34     int GetIndex(const ListItem& list_item) const;
35 
36     // 如果可能,再写一个方法,不要用这个
37     // 注意func返回后sub_list就失去了安全保证,不能再使用,也不能保证下次调用此方法时sub_list仍然相同
38     void ReadAllListItem(std::function<void(vector<const ListItem*>& sub_list)> func) const;
39 
40 private:
41     // 先锁定CRecentList的m_mutex再调用,返回的指针在解锁前有效
42     vector<const ListItem*> BuildSubList() const;
43 
44 private:
45     // 在构造时确定,表示此对象用来缓存哪个列表集合
46     const ListType m_type;
47     // 约定m_ui_开头的成员变量只允许小写的成员方法访问
48     vector<ListItem> m_ui_list;
49     int m_ui_current_play_index{ -1 };
50     int m_ui_ver{};
51 };
52 
53