YYCache设计思路及源码学习

设计思路

利用YYCache来进行操作,实质操作分为了内存缓存操作(YYMemoryCache)和硬盘缓存操作(YYDiskCache)。内存缓存设计一般是在内存中开辟一个空间用以保存请求的数据(一般使用字典操作)。硬盘缓存设计即是将文件保存至本地,这种保存分为小文件保存和大文件保存,对于小文件保存使用数据库操作性能效率相对较高,对于大文件则使用直接存放。YYDiskCache为线程安全的类,其操作是基于YYKVStorage(线程不安全的类)的操作。以下为大致源码分析

主类YYCache

必须初始化名字 名字即为存储路径,NS_DESIGNATED_INITIALIZER提示为设计初始化方法,UNAVAILABLE_ATTRIBUTE定义为未实现方法,关于这两种宏定义都存在于系统框架中

- (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;

最终构造函数如下所示:包含了硬盘缓存和内存缓存

- (instancetype)initWithPath:(NSString *)path {
if (path.length == 0) return nil;
YYDiskCache *diskCache = [[YYDiskCache alloc] initWithPath:path];
if (!diskCache) return nil;
NSString *name = [path lastPathComponent];
YYMemoryCache *memoryCache = [YYMemoryCache new];
memoryCache.name = name;
self = [super init];
_name = name;
_diskCache = diskCache;
_memoryCache = memoryCache;
return self;
}

对于YYCache所设计方法,所做操作本质上来说就是增删改查,内部本质是对YYDiskCache和YYMemoryCache的操作,由于读取效率的问题,读取时先有内存缓存中读取,若没有则由硬盘缓存中读取(再存入内存缓存中)

- (BOOL)containsObjectForKey:(NSString *)key
- (void)containsObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key, BOOL contains))block
- (id<NSCoding>)objectForKey:(NSString *)key
- (void)objectForKey:(NSString *)key withBlock:(void(^)(NSString *key, id<NSCoding> object))block
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key
- (void)setObject:(id<NSCoding>)object forKey:(NSString *)key withBlock:(void(^)(void))block
- (void)removeObjectForKey:(NSString *)key
- (void)removeObjectForKey:(NSString *)key withBlock:(void(^)(NSString *key))block
- (void)removeAllObjects
- (void)removeAllObjectsWithBlock:(void(^)(void))block
- (void)removeAllObjectsWithProgressBlock:(void(^)(int removedCount, int totalCount))progress
                             endBlock:(void(^)(BOOL error))end

YYMemoryCache和YYDiskCache

为了方便理解和YYCache对YYDiskCache和YYMemoryCache的操作,两类的通用接口设计如下

- (BOOL)containsObjectForKey:(id)key
- (id)objectForKey:(id)key
- (void)setObject:(id)object forKey:(id)key
- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost
- (void)removeObjectForKey:(id)key
- (void)removeAllObjects

在YYDiskCache则包含了YYCache中所有的接口设计

YYMemoryCache

主要成员变量

  1. pthread_mutex_t(保证线程安全)

  2. _YYLinkedMap自定义类(主包含数据映射字典和链表(根据LRU算法计算自动移除的节点))

  3. dispatch_queue_t操作队列(保证线程不阻塞)
    其中YYLinkeedMap包含了如下成员变量--LRU算法:常使用节点被移动到头结点,即经常使用的节点靠前越靠后就为越不常使用的节点具体实现可查看类中的insertNodeAtHead和bringNodeToHead方法

    CFMutableDictionaryRef _dic; // 字典内 存放对应的缓存数据
    NSUInteger _totalCost;
    NSUInteger _totalCount;
    _YYLinkedMapNode *_head; // 头结点
    _YYLinkedMapNode *_tail; // 尾节点,利用LRU算法实现
    BOOL _releaseOnMainThread;
    BOOL _releaseAsynchronously;

YYDiskCache

主要成员变量

  1. YYKVStorage *_kv; //硬盘存储主要类(线程不安全)
  2. dispatch_semaphore_t _lock;
  3. dispatch_queue_t _queue;
    在YYDiskCache中所做的操作都是基于YYKVStorage的操作,只是增加了信号量上锁以保证线程安全

YYKVStorage

此类主要是利用sqlite3和数据库打交道,当然对于比较大型的文件是直接使用系统的write方法来进行文件保存,这样能更大限度的提升效率。在YYKVStorage的存储中都是以对象的方式进行存储,其对象封装为YYKVStorageItem其中的字段设计如下

key                 text,
filename            text,
size                integer,
inline_data         blob,
modification_time   integer,
last_access_time    integer,
extended_data       blob,
primary key(key)

剩下的就是YYKVStorage如何利用sqlite3进行数据的访问,关于sqlite3的操作就不详述了。
以上便是整个YYCache设计的主要思路,当然里面包含了其他的一些东西。以笔者目前的功力还不能吃透,其中便是YYDispatchQueuePool,在这里YYCache中利用了自己设计的队列池来进行管理。由于没有这方面的经验和时间来学习。这一块就算留作以后研究的一个点吧。
最后贴上YY大神关于自己YYCache的设计思路链接

原文地址:https://www.cnblogs.com/purple-sweet-pottoes/p/5784163.html