The RKCache class declares the programmatic interface for the RKRegex framework caching feature.
Some of the features provided by the RKCache class are:
While a RKCache will permit any type of object to be added, as a pragmatic limitation only immutable objects should be added to a cache. In essence, a RKCache is a multithreading safe NSMutableSet. The cache can only ensure that an object retrieved from the cache will not be deallocated before the retrieving thread has finished with the object and released it properly. Once an object has been retrieved, the retrieved object must provide any concurrent modification safety mechanisms. Since immutable objects can not be modified by definition, this greatly simplifies concurrent access to objects and is the reason why only immutable objects should be added in general.
A RKCache is best applied to situations in which a result can take an appreciable amount of time to prepare, but once computed, the result can be used again and again. For example, the RegexKit.framework must compile a regular expression to an internal format before it can perform any matches with it. The compiled regular expression does not change, and can be reused again and again. While compiling a regular expression is relatively quick, it can still be an order of magnitude slower than a cache lookup.
When an object is added to the cache, it is sent a retain message just as if it were being added to any other type of collection. Similarly, when an object is removed from the cache, it is sent a release message. Adding or removing objects from the cache requires the thread to obtain the exclusive use write lock on the cache. There can be any number of simultaneous threads with a read lock, but the write lock guarantees that the write lock owner is the only thread accessing the cache.
The cache takes certain steps to ensure that objects are not deallocated while in use even if another thread immediately clears the cache after the requesting thread has retrieved an object. To do this, the cache obtains a read lock on the NSMapTable and performs a lookup. If there is a match, the cache sends a retain message to the retrieved object while it still has the cache read locked and then releases its read lock. A different thread might immediately obtain a write lock on the cache and clear it, causing the cache to release ownership of the just retrieved object. Since the cache sent a retain message to the just retrieved object, it is not immediately deallocated. If the caller requests it, the cache sends an autorelease to the object before returning it.
Each thread is required to have at least one NSAutoreleasePool. Since the autorelease is registered with the retrieving threads NSAutoreleasePool, this ensures that the object will not be deallocated until the requesting threads NSAutoreleasePool is released. A caller might request that an autorelease not be sent automatically after the object was retrieved because it will be returning the result as part of an init... method and would have to counter the autorelease with another retain message immediately, wasting effort.
This method may be used in place of addObjectToCache: when either the hash value is already computed and available, or to override the default value that would be returned by [object hash].
Reasons for returning NO and not adding an object to the cache include:
Creates a new, autoreleased NSSet by adding all of the objects currently in the cache to a new NSSet. This is done while the cache is locked, and once all the current objects are added, the cache is unlocked. Therefore it is possible that the objects in the returned NSSet and the objects in the cache are no longer the same as another thread may have added, removed, or cleared the cache by the time the caller receives the NSSet result. It is, in essence, a snapshot of contents of the cache at the instant in time it was created.
The objects in the returned NSSet have their retain count incremented by being included in the NSSet. Therefore, even if the cache is cleared by another thread, it is still safe to use the objects contained in the returned NSSet.
Example:
Example usage with %@ format specifier:
Invokes objectForHash:description:autorelease: with objectHash, descriptionString, and YES for autorelease.
This method is used in cases such as returning a cached object from an init... method to avoid adding the object unnecessarily to the current NSAutoreleasePool which would result in wasted work because init... would require sending a retain to counter the autorelease.
Invokes removeObjectWithHash: with the value of [object hash].
The returned object may not be the same object as object. The returned object is the instantiated object that was originally added to the cache, but will have the same hash value as object and [object isEqual:theRemovedObject] == YES.
The object to be removed, if any, is sent both a retain and autorelease while the cache is locked. This ensures that the object returned remains live in the callers thread for the duration of the callers current NSAutoreleasePool pool. If you wish to use the object past that point, you must take ownership of it by sending a retain message. This is similar to various convenience functions, such as [NSString stringWithFormat:@"Hello"].
Includes information about the cache, such as the number of objects currently cached and cache effectiveness.
Example: