From 83b9d5c682b21d88133f24da0f94dd56bd79e687 Mon Sep 17 00:00:00 2001
From: 单军华
Date: Thu, 19 Jul 2018 13:38:55 +0800
Subject: [PATCH] change

---
 screendisplay/Pods/YYCache/YYCache/YYMemoryCache.m |  505 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 505 insertions(+), 0 deletions(-)

diff --git a/screendisplay/Pods/YYCache/YYCache/YYMemoryCache.m b/screendisplay/Pods/YYCache/YYCache/YYMemoryCache.m
new file mode 100644
index 0000000..9042d9b
--- /dev/null
+++ b/screendisplay/Pods/YYCache/YYCache/YYMemoryCache.m
@@ -0,0 +1,505 @@
+//
+//  YYMemoryCache.m
+//  YYCache <https://github.com/ibireme/YYCache>
+//
+//  Created by ibireme on 15/2/7.
+//  Copyright (c) 2015 ibireme.
+//
+//  This source code is licensed under the MIT-style license found in the
+//  LICENSE file in the root directory of this source tree.
+//
+
+#import "YYMemoryCache.h"
+#import <UIKit/UIKit.h>
+#import <CoreFoundation/CoreFoundation.h>
+#import <QuartzCore/QuartzCore.h>
+#import <pthread.h>
+
+
+static inline dispatch_queue_t YYMemoryCacheGetReleaseQueue() {
+    return dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0);
+}
+
+/**
+ A node in linked map.
+ Typically, you should not use this class directly.
+ */
+@interface _YYLinkedMapNode : NSObject {
+    @package
+    __unsafe_unretained _YYLinkedMapNode *_prev; // retained by dic
+    __unsafe_unretained _YYLinkedMapNode *_next; // retained by dic
+    id _key;
+    id _value;
+    NSUInteger _cost;
+    NSTimeInterval _time;
+}
+@end
+
+@implementation _YYLinkedMapNode
+@end
+
+
+/**
+ A linked map used by YYMemoryCache.
+ It's not thread-safe and does not validate the parameters.
+ 
+ Typically, you should not use this class directly.
+ */
+@interface _YYLinkedMap : NSObject {
+    @package
+    CFMutableDictionaryRef _dic; // do not set object directly
+    NSUInteger _totalCost;
+    NSUInteger _totalCount;
+    _YYLinkedMapNode *_head; // MRU, do not change it directly
+    _YYLinkedMapNode *_tail; // LRU, do not change it directly
+    BOOL _releaseOnMainThread;
+    BOOL _releaseAsynchronously;
+}
+
+/// Insert a node at head and update the total cost.
+/// Node and node.key should not be nil.
+- (void)insertNodeAtHead:(_YYLinkedMapNode *)node;
+
+/// Bring a inner node to header.
+/// Node should already inside the dic.
+- (void)bringNodeToHead:(_YYLinkedMapNode *)node;
+
+/// Remove a inner node and update the total cost.
+/// Node should already inside the dic.
+- (void)removeNode:(_YYLinkedMapNode *)node;
+
+/// Remove tail node if exist.
+- (_YYLinkedMapNode *)removeTailNode;
+
+/// Remove all node in background queue.
+- (void)removeAll;
+
+@end
+
+@implementation _YYLinkedMap
+
+- (instancetype)init {
+    self = [super init];
+    _dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+    _releaseOnMainThread = NO;
+    _releaseAsynchronously = YES;
+    return self;
+}
+
+- (void)dealloc {
+    CFRelease(_dic);
+}
+
+- (void)insertNodeAtHead:(_YYLinkedMapNode *)node {
+    CFDictionarySetValue(_dic, (__bridge const void *)(node->_key), (__bridge const void *)(node));
+    _totalCost += node->_cost;
+    _totalCount++;
+    if (_head) {
+        node->_next = _head;
+        _head->_prev = node;
+        _head = node;
+    } else {
+        _head = _tail = node;
+    }
+}
+
+- (void)bringNodeToHead:(_YYLinkedMapNode *)node {
+    if (_head == node) return;
+    
+    if (_tail == node) {
+        _tail = node->_prev;
+        _tail->_next = nil;
+    } else {
+        node->_next->_prev = node->_prev;
+        node->_prev->_next = node->_next;
+    }
+    node->_next = _head;
+    node->_prev = nil;
+    _head->_prev = node;
+    _head = node;
+}
+
+- (void)removeNode:(_YYLinkedMapNode *)node {
+    CFDictionaryRemoveValue(_dic, (__bridge const void *)(node->_key));
+    _totalCost -= node->_cost;
+    _totalCount--;
+    if (node->_next) node->_next->_prev = node->_prev;
+    if (node->_prev) node->_prev->_next = node->_next;
+    if (_head == node) _head = node->_next;
+    if (_tail == node) _tail = node->_prev;
+}
+
+- (_YYLinkedMapNode *)removeTailNode {
+    if (!_tail) return nil;
+    _YYLinkedMapNode *tail = _tail;
+    CFDictionaryRemoveValue(_dic, (__bridge const void *)(_tail->_key));
+    _totalCost -= _tail->_cost;
+    _totalCount--;
+    if (_head == _tail) {
+        _head = _tail = nil;
+    } else {
+        _tail = _tail->_prev;
+        _tail->_next = nil;
+    }
+    return tail;
+}
+
+- (void)removeAll {
+    _totalCost = 0;
+    _totalCount = 0;
+    _head = nil;
+    _tail = nil;
+    if (CFDictionaryGetCount(_dic) > 0) {
+        CFMutableDictionaryRef holder = _dic;
+        _dic = CFDictionaryCreateMutable(CFAllocatorGetDefault(), 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+        
+        if (_releaseAsynchronously) {
+            dispatch_queue_t queue = _releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+            dispatch_async(queue, ^{
+                CFRelease(holder); // hold and release in specified queue
+            });
+        } else if (_releaseOnMainThread && !pthread_main_np()) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                CFRelease(holder); // hold and release in specified queue
+            });
+        } else {
+            CFRelease(holder);
+        }
+    }
+}
+
+@end
+
+
+
+@implementation YYMemoryCache {
+    pthread_mutex_t _lock;
+    _YYLinkedMap *_lru;
+    dispatch_queue_t _queue;
+}
+
+- (void)_trimRecursively {
+    __weak typeof(self) _self = self;
+    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(_autoTrimInterval * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
+        __strong typeof(_self) self = _self;
+        if (!self) return;
+        [self _trimInBackground];
+        [self _trimRecursively];
+    });
+}
+
+- (void)_trimInBackground {
+    dispatch_async(_queue, ^{
+        [self _trimToCost:self->_costLimit];
+        [self _trimToCount:self->_countLimit];
+        [self _trimToAge:self->_ageLimit];
+    });
+}
+
+- (void)_trimToCost:(NSUInteger)costLimit {
+    BOOL finish = NO;
+    pthread_mutex_lock(&_lock);
+    if (costLimit == 0) {
+        [_lru removeAll];
+        finish = YES;
+    } else if (_lru->_totalCost <= costLimit) {
+        finish = YES;
+    }
+    pthread_mutex_unlock(&_lock);
+    if (finish) return;
+    
+    NSMutableArray *holder = [NSMutableArray new];
+    while (!finish) {
+        if (pthread_mutex_trylock(&_lock) == 0) {
+            if (_lru->_totalCost > costLimit) {
+                _YYLinkedMapNode *node = [_lru removeTailNode];
+                if (node) [holder addObject:node];
+            } else {
+                finish = YES;
+            }
+            pthread_mutex_unlock(&_lock);
+        } else {
+            usleep(10 * 1000); //10 ms
+        }
+    }
+    if (holder.count) {
+        dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+        dispatch_async(queue, ^{
+            [holder count]; // release in queue
+        });
+    }
+}
+
+- (void)_trimToCount:(NSUInteger)countLimit {
+    BOOL finish = NO;
+    pthread_mutex_lock(&_lock);
+    if (countLimit == 0) {
+        [_lru removeAll];
+        finish = YES;
+    } else if (_lru->_totalCount <= countLimit) {
+        finish = YES;
+    }
+    pthread_mutex_unlock(&_lock);
+    if (finish) return;
+    
+    NSMutableArray *holder = [NSMutableArray new];
+    while (!finish) {
+        if (pthread_mutex_trylock(&_lock) == 0) {
+            if (_lru->_totalCount > countLimit) {
+                _YYLinkedMapNode *node = [_lru removeTailNode];
+                if (node) [holder addObject:node];
+            } else {
+                finish = YES;
+            }
+            pthread_mutex_unlock(&_lock);
+        } else {
+            usleep(10 * 1000); //10 ms
+        }
+    }
+    if (holder.count) {
+        dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+        dispatch_async(queue, ^{
+            [holder count]; // release in queue
+        });
+    }
+}
+
+- (void)_trimToAge:(NSTimeInterval)ageLimit {
+    BOOL finish = NO;
+    NSTimeInterval now = CACurrentMediaTime();
+    pthread_mutex_lock(&_lock);
+    if (ageLimit <= 0) {
+        [_lru removeAll];
+        finish = YES;
+    } else if (!_lru->_tail || (now - _lru->_tail->_time) <= ageLimit) {
+        finish = YES;
+    }
+    pthread_mutex_unlock(&_lock);
+    if (finish) return;
+    
+    NSMutableArray *holder = [NSMutableArray new];
+    while (!finish) {
+        if (pthread_mutex_trylock(&_lock) == 0) {
+            if (_lru->_tail && (now - _lru->_tail->_time) > ageLimit) {
+                _YYLinkedMapNode *node = [_lru removeTailNode];
+                if (node) [holder addObject:node];
+            } else {
+                finish = YES;
+            }
+            pthread_mutex_unlock(&_lock);
+        } else {
+            usleep(10 * 1000); //10 ms
+        }
+    }
+    if (holder.count) {
+        dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+        dispatch_async(queue, ^{
+            [holder count]; // release in queue
+        });
+    }
+}
+
+- (void)_appDidReceiveMemoryWarningNotification {
+    if (self.didReceiveMemoryWarningBlock) {
+        self.didReceiveMemoryWarningBlock(self);
+    }
+    if (self.shouldRemoveAllObjectsOnMemoryWarning) {
+        [self removeAllObjects];
+    }
+}
+
+- (void)_appDidEnterBackgroundNotification {
+    if (self.didEnterBackgroundBlock) {
+        self.didEnterBackgroundBlock(self);
+    }
+    if (self.shouldRemoveAllObjectsWhenEnteringBackground) {
+        [self removeAllObjects];
+    }
+}
+
+#pragma mark - public
+
+- (instancetype)init {
+    self = super.init;
+    pthread_mutex_init(&_lock, NULL);
+    _lru = [_YYLinkedMap new];
+    _queue = dispatch_queue_create("com.ibireme.cache.memory", DISPATCH_QUEUE_SERIAL);
+    
+    _countLimit = NSUIntegerMax;
+    _costLimit = NSUIntegerMax;
+    _ageLimit = DBL_MAX;
+    _autoTrimInterval = 5.0;
+    _shouldRemoveAllObjectsOnMemoryWarning = YES;
+    _shouldRemoveAllObjectsWhenEnteringBackground = YES;
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidReceiveMemoryWarningNotification) name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(_appDidEnterBackgroundNotification) name:UIApplicationDidEnterBackgroundNotification object:nil];
+    
+    [self _trimRecursively];
+    return self;
+}
+
+- (void)dealloc {
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidReceiveMemoryWarningNotification object:nil];
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationDidEnterBackgroundNotification object:nil];
+    [_lru removeAll];
+    pthread_mutex_destroy(&_lock);
+}
+
+- (NSUInteger)totalCount {
+    pthread_mutex_lock(&_lock);
+    NSUInteger count = _lru->_totalCount;
+    pthread_mutex_unlock(&_lock);
+    return count;
+}
+
+- (NSUInteger)totalCost {
+    pthread_mutex_lock(&_lock);
+    NSUInteger totalCost = _lru->_totalCost;
+    pthread_mutex_unlock(&_lock);
+    return totalCost;
+}
+
+- (BOOL)releaseOnMainThread {
+    pthread_mutex_lock(&_lock);
+    BOOL releaseOnMainThread = _lru->_releaseOnMainThread;
+    pthread_mutex_unlock(&_lock);
+    return releaseOnMainThread;
+}
+
+- (void)setReleaseOnMainThread:(BOOL)releaseOnMainThread {
+    pthread_mutex_lock(&_lock);
+    _lru->_releaseOnMainThread = releaseOnMainThread;
+    pthread_mutex_unlock(&_lock);
+}
+
+- (BOOL)releaseAsynchronously {
+    pthread_mutex_lock(&_lock);
+    BOOL releaseAsynchronously = _lru->_releaseAsynchronously;
+    pthread_mutex_unlock(&_lock);
+    return releaseAsynchronously;
+}
+
+- (void)setReleaseAsynchronously:(BOOL)releaseAsynchronously {
+    pthread_mutex_lock(&_lock);
+    _lru->_releaseAsynchronously = releaseAsynchronously;
+    pthread_mutex_unlock(&_lock);
+}
+
+- (BOOL)containsObjectForKey:(id)key {
+    if (!key) return NO;
+    pthread_mutex_lock(&_lock);
+    BOOL contains = CFDictionaryContainsKey(_lru->_dic, (__bridge const void *)(key));
+    pthread_mutex_unlock(&_lock);
+    return contains;
+}
+
+- (id)objectForKey:(id)key {
+    if (!key) return nil;
+    pthread_mutex_lock(&_lock);
+    _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key));
+    if (node) {
+        node->_time = CACurrentMediaTime();
+        [_lru bringNodeToHead:node];
+    }
+    pthread_mutex_unlock(&_lock);
+    return node ? node->_value : nil;
+}
+
+- (void)setObject:(id)object forKey:(id)key {
+    [self setObject:object forKey:key withCost:0];
+}
+
+- (void)setObject:(id)object forKey:(id)key withCost:(NSUInteger)cost {
+    if (!key) return;
+    if (!object) {
+        [self removeObjectForKey:key];
+        return;
+    }
+    pthread_mutex_lock(&_lock);
+    _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key));
+    NSTimeInterval now = CACurrentMediaTime();
+    if (node) {
+        _lru->_totalCost -= node->_cost;
+        _lru->_totalCost += cost;
+        node->_cost = cost;
+        node->_time = now;
+        node->_value = object;
+        [_lru bringNodeToHead:node];
+    } else {
+        node = [_YYLinkedMapNode new];
+        node->_cost = cost;
+        node->_time = now;
+        node->_key = key;
+        node->_value = object;
+        [_lru insertNodeAtHead:node];
+    }
+    if (_lru->_totalCost > _costLimit) {
+        dispatch_async(_queue, ^{
+            [self trimToCost:_costLimit];
+        });
+    }
+    if (_lru->_totalCount > _countLimit) {
+        _YYLinkedMapNode *node = [_lru removeTailNode];
+        if (_lru->_releaseAsynchronously) {
+            dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+            dispatch_async(queue, ^{
+                [node class]; //hold and release in queue
+            });
+        } else if (_lru->_releaseOnMainThread && !pthread_main_np()) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [node class]; //hold and release in queue
+            });
+        }
+    }
+    pthread_mutex_unlock(&_lock);
+}
+
+- (void)removeObjectForKey:(id)key {
+    if (!key) return;
+    pthread_mutex_lock(&_lock);
+    _YYLinkedMapNode *node = CFDictionaryGetValue(_lru->_dic, (__bridge const void *)(key));
+    if (node) {
+        [_lru removeNode:node];
+        if (_lru->_releaseAsynchronously) {
+            dispatch_queue_t queue = _lru->_releaseOnMainThread ? dispatch_get_main_queue() : YYMemoryCacheGetReleaseQueue();
+            dispatch_async(queue, ^{
+                [node class]; //hold and release in queue
+            });
+        } else if (_lru->_releaseOnMainThread && !pthread_main_np()) {
+            dispatch_async(dispatch_get_main_queue(), ^{
+                [node class]; //hold and release in queue
+            });
+        }
+    }
+    pthread_mutex_unlock(&_lock);
+}
+
+- (void)removeAllObjects {
+    pthread_mutex_lock(&_lock);
+    [_lru removeAll];
+    pthread_mutex_unlock(&_lock);
+}
+
+- (void)trimToCount:(NSUInteger)count {
+    if (count == 0) {
+        [self removeAllObjects];
+        return;
+    }
+    [self _trimToCount:count];
+}
+
+- (void)trimToCost:(NSUInteger)cost {
+    [self _trimToCost:cost];
+}
+
+- (void)trimToAge:(NSTimeInterval)age {
+    [self _trimToAge:age];
+}
+
+- (NSString *)description {
+    if (_name) return [NSString stringWithFormat:@"<%@: %p> (%@)", self.class, self, _name];
+    else return [NSString stringWithFormat:@"<%@: %p>", self.class, self];
+}
+
+@end

--
Gitblit v1.8.0