瀏覽代碼

improved compatibility: #10

ibireme 9 年之前
父節點
當前提交
a369de2c67
共有 5 個文件被更改,包括 41 次插入6 次删除
  1. 0 2
      YYCache/YYCache.h
  2. 4 2
      YYCache/YYDiskCache.h
  3. 35 0
      YYCache/YYDiskCache.m
  4. 2 0
      YYCache/YYKVStorage.h
  5. 0 2
      YYCache/YYMemoryCache.m

+ 0 - 2
YYCache/YYCache.h

@@ -55,7 +55,6 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[];
      the app's caches dictionary for disk cache. Once initialized you should not 
      the app's caches dictionary for disk cache. Once initialized you should not 
      read and write to this directory.
      read and write to this directory.
  @result A new cache object, or nil if an error occurs.
  @result A new cache object, or nil if an error occurs.
- @warning Multiple instances with the same name will make the storage unstable.
  */
  */
 - (instancetype)initWithName:(NSString *)name;
 - (instancetype)initWithName:(NSString *)name;
 
 
@@ -66,7 +65,6 @@ FOUNDATION_EXPORT const unsigned char YYCacheVersionString[];
  @param path  Full path of a directory in which the cache will write data.
  @param path  Full path of a directory in which the cache will write data.
      Once initialized you should not read and write to this directory.
      Once initialized you should not read and write to this directory.
  @result A new cache object, or nil if an error occurs.
  @result A new cache object, or nil if an error occurs.
- @warning Multiple instances with the same path will make the storage unstable.
  */
  */
 - (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
 - (instancetype)initWithPath:(NSString *)path NS_DESIGNATED_INITIALIZER;
 
 

+ 4 - 2
YYCache/YYDiskCache.h

@@ -145,7 +145,8 @@
  
  
  @return A new cache object, or nil if an error occurs.
  @return A new cache object, or nil if an error occurs.
  
  
- @warning Multiple instances with the same path will make the storage unstable.
+ @warning If the cache instance for the specified path already exists in memory, 
+     this method will return it directly, instead of creating a new instance.
  */
  */
 - (instancetype)initWithPath:(NSString *)path;
 - (instancetype)initWithPath:(NSString *)path;
 
 
@@ -164,7 +165,8 @@
  
  
  @return A new cache object, or nil if an error occurs.
  @return A new cache object, or nil if an error occurs.
  
  
- @warning Multiple instances with the same path will make the storage unstable.
+ @warning If the cache instance for the specified path already exists in memory, 
+     this method will return it directly, instead of creating a new instance.
  */
  */
 - (instancetype)initWithPath:(NSString *)path
 - (instancetype)initWithPath:(NSString *)path
              inlineThreshold:(NSUInteger)threshold NS_DESIGNATED_INITIALIZER;
              inlineThreshold:(NSUInteger)threshold NS_DESIGNATED_INITIALIZER;

+ 35 - 0
YYCache/YYDiskCache.m

@@ -11,6 +11,7 @@
 
 
 #import "YYDiskCache.h"
 #import "YYDiskCache.h"
 #import "YYKVStorage.h"
 #import "YYKVStorage.h"
+#import <libkern/OSAtomic.h>
 #import <CommonCrypto/CommonCrypto.h>
 #import <CommonCrypto/CommonCrypto.h>
 #import <objc/runtime.h>
 #import <objc/runtime.h>
 #import <time.h>
 #import <time.h>
@@ -45,6 +46,36 @@ static NSString *_YYNSStringMD5(NSString *string) {
             ];
             ];
 }
 }
 
 
+/// weak reference for all instances
+static NSMapTable *_globalInstances;
+static OSSpinLock _globalInstancesLock;
+
+static void _YYDiskCacheInitGlobal() {
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _globalInstancesLock = OS_SPINLOCK_INIT;
+        _globalInstances = [[NSMapTable alloc] initWithKeyOptions:NSPointerFunctionsStrongMemory valueOptions:NSPointerFunctionsWeakMemory capacity:0];
+    });
+}
+
+static YYDiskCache *_YYDiskCacheGetGlobal(NSString *path) {
+    if (path.length == 0) return nil;
+    _YYDiskCacheInitGlobal();
+    OSSpinLockLock(&_globalInstancesLock);
+    id cache = [_globalInstances objectForKey:path];
+    OSSpinLockUnlock(&_globalInstancesLock);
+    return cache;
+}
+
+static void _YYDiskCacheSetGlobal(YYDiskCache *cache) {
+    if (cache.path.length == 0) return;
+    _YYDiskCacheInitGlobal();
+    OSSpinLockLock(&_globalInstancesLock);
+    [_globalInstances setObject:cache forKey:cache.path];
+    OSSpinLockUnlock(&_globalInstancesLock);
+}
+
+
 
 
 @implementation YYDiskCache {
 @implementation YYDiskCache {
     YYKVStorage *_kv;
     YYKVStorage *_kv;
@@ -135,6 +166,9 @@ static NSString *_YYNSStringMD5(NSString *string) {
     self = [super init];
     self = [super init];
     if (!self) return nil;
     if (!self) return nil;
     
     
+    YYDiskCache *globalCache = _YYDiskCacheGetGlobal(path);
+    if (globalCache) return globalCache;
+    
     YYKVStorageType type;
     YYKVStorageType type;
     if (threshold == 0) {
     if (threshold == 0) {
         type = YYKVStorageTypeFile;
         type = YYKVStorageTypeFile;
@@ -159,6 +193,7 @@ static NSString *_YYNSStringMD5(NSString *string) {
     _autoTrimInterval = 60;
     _autoTrimInterval = 60;
     
     
     [self _trimRecursively];
     [self _trimRecursively];
+    _YYDiskCacheSetGlobal(self);
     return self;
     return self;
 }
 }
 
 

+ 2 - 0
YYCache/YYKVStorage.h

@@ -13,6 +13,7 @@
 
 
 /**
 /**
  YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data.
  YYKVStorageItem is used by `YYKVStorage` to store key-value pair and meta data.
+ Typically, you should not use this class directly.
  */
  */
 @interface YYKVStorageItem : NSObject
 @interface YYKVStorageItem : NSObject
 @property (nonatomic, strong) NSString *key;        ///< key
 @property (nonatomic, strong) NSString *key;        ///< key
@@ -56,6 +57,7 @@ typedef NS_ENUM(NSUInteger, YYKVStorageType) {
 
 
 /**
 /**
  YYKVStorage is a key-value storage based on sqlite and file system.
  YYKVStorage is a key-value storage based on sqlite and file system.
+ Typically, you should not use this class directly.
  
  
  @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. 
  @discussion The designated initializer for YYKVStorage is `initWithPath:type:`. 
  After initialized, a directory is created based on the `path` to hold key-value data.
  After initialized, a directory is created based on the `path` to hold key-value data.

+ 0 - 2
YYCache/YYMemoryCache.m

@@ -18,8 +18,6 @@
 
 
 #if __has_include("YYDispatchQueuePool.h")
 #if __has_include("YYDispatchQueuePool.h")
 #import "YYDispatchQueuePool.h"
 #import "YYDispatchQueuePool.h"
-#else
-#import <libkern/OSAtomic.h>
 #endif
 #endif
 
 
 #ifdef YYDispatchQueuePool_h
 #ifdef YYDispatchQueuePool_h