Source/TNLLRUCache.h (35 lines of code) (raw):
//
// TNLLRUCache.h
// TwitterNetworkLayer
//
// Created on 10/27/15.
// Copyright © 2020 Twitter. All rights reserved.
//
#import <Foundation/Foundation.h>
@protocol TNLLRUCacheDelegate;
@protocol TNLLRUEntry;
NS_ASSUME_NONNULL_BEGIN
/**
`TNLLRUCache` is a collection object that maintains a set of `TNLLRUEntry` objects.
You can look up an entry by identifier in constant time and it maintains the entries so that you
can remove the least-recently-used (LRU) entry.
@warning This class is exposed as a convenience to consumers that might be able to take advantage
of an LRU collection.
It is not permanent though and may eventually move to a shared core utilities library that TNL
will depend on.
It is recommended to NOT use this class unless you are prepared to migrate to a shared core
utilities library if one is created.
*/
@interface TNLLRUCache : NSObject <NSFastEnumeration>
/** Optional delegate */
@property (nonatomic, weak, nullable) id<TNLLRUCacheDelegate> delegate;
/**
The head entry of the cache, most recently used entry.
`nil` if the cache is empty.
Accessing does not mutate this LRU cache.
*/
@property (nonatomic, readonly, nullable) id<TNLLRUEntry> headEntry;
/**
The tail entry of the cache, least recently used entry.
`nil` if the cache is empty.
Accessing does not mutate this LRU cache.
*/
@property (nonatomic, readonly, nullable) id<TNLLRUEntry> tailEntry;
/** the number of entries in the manfiest. Execution time is constant, O(1) */
- (NSUInteger)numberOfEntries;
/** designted initializer */
- (instancetype)initWithEntries:(nullable NSArray<id<TNLLRUEntry>> *)arrayOfLRUEntries
delegate:(nullable id<TNLLRUCacheDelegate>)delegate NS_DESIGNATED_INITIALIZER;
/**
Access an entry by identifier.
If entry is found, it is moved to head if _canMutate_ is `YES` and the entry's
`shouldAccessMoveLRUEntryToHead` value is `YES`.
Returns `nil` if no entry was found.
Execution time is constant, O(1)
*/
- (nullable id<TNLLRUEntry>)entryWithIdentifier:(NSString *)identifier canMutate:(BOOL)moveToHead;
/**
Same as `entryWithIdentifier:canMutate:` with _canMutate being `YES`
*/
- (nullable id<TNLLRUEntry>)entryWithIdentifier:(NSString *)identifier;
/**
Copy all entries as an `NSArray` (does not count as an access that would affect order in LRU cache).
Execution time is linear, O(n)
*/
- (NSArray<id<TNLLRUEntry>> *)allEntries;
/**
Sets the given _entry_ as the head entry.
If _entry_ was not in the cache, it is added to the cache.
If _entry_ was in the cache, it is just moved to the head if
`[TNLLRUEntry shouldAccessMoveLRUEntryToHead]` returns `YES`.
Execution time is constant, O(1)
*/
- (void)addEntry:(id<TNLLRUEntry>)entry;
/**
Adds the given _entry_ as the tail entry.
Execution time is constant, O(1)
@note this circumvents the value of the LRU cache, so it is recommended that only `addEntry:` is used.
Using this method only really makes sense during `TNLLRUCache` set up time and not beyond that.
*/
- (void)appendEntry:(id<TNLLRUEntry>)entry;
/**
Removes the specified _entry_.
Execution time is constant, O(1)
@note This does will trigger the `[TNLLRUCacheDelegate tnl_cache:didEvictEntry:]` callback if then
entry was in the cache
*/
- (void)removeEntry:(nullable id<TNLLRUEntry>)entry;
/**
Remove the tail entry (least-recently-used) if the cache is not empty.
Execution time is constant, O(1)
@return the entry removed or `nil` if no entry was removed.
@note This does will trigger the `[TNLLRUCacheDelegate tnl_cache:didEvictEntry:]` callback if an
entry was removed
*/
- (nullable id<TNLLRUEntry>)removeTailEntry;
/**
Clear all entries in the cache.
Execution time is linear, O(n). This is because each value has to dealloc.
@note This does NOT trigger the `[TNLLRUCacheDelegate tnl_cache:didEvictEntry:]` callback
*/
- (void)clearAllEntries;
@end
/**
Delegate protocol for `TNLLRUCache`
*/
@protocol TNLLRUCacheDelegate <NSObject>
@optional
/**
Optional callback for when a specific _entry_ is evicted from the _cache_.
@note This method is NOT called on cache `dealloc` nor when `[TNLLRUCache clearAllEntries]` is called.
*/
- (void)tnl_cache:(TNLLRUCache *)cache
didEvictEntry:(id<TNLLRUEntry>)entry;
/**
Optional callback to check if a specific _entry_ can be evicted from the _cache_.
Return `NO` to prevent eviction.
Default when unimplemented is `YES`.
Only used in conjuction with `removeTailEntry`.
*/
- (BOOL)tnl_cache:(TNLLRUCache *)cache
canEvictEntry:(id<TNLLRUEntry>)entry;
@end
/**
Protocol for `TNLLRUCache` support.
*/
@protocol TNLLRUEntry <NSObject>
@required
/** The unique identifier for the entry */
- (NSString *)LRUEntryIdentifier;
/**
Return `YES` to update the entry as most-recently-used when it is accessed.
Otherwise, return `NO`.
*/
- (BOOL)shouldAccessMoveLRUEntryToHead;
/**
A property to store the strong reference to the next entry.
This property will be managed by the `TNLLRUManfiest` and should not be manipulated.
*/
@property (nonatomic, nullable) id<TNLLRUEntry> nextLRUEntry;
/**
A property to store the weak reference to the previous entry.
This property will be managed by the `TNLLRUManfiest` and should not be manipulated.
*/
@property (nonatomic, nullable, weak) id<TNLLRUEntry> previousLRUEntry;
@end
NS_ASSUME_NONNULL_END