Caching objects and multithreading

Discussion in 'iOS Programming' started by idelovski, Mar 4, 2012.

  1. macrumors regular

    Joined:
    Sep 11, 2008
    #1
    When I started creating my caching class I was sure I'll use it always on the main thread but it turns out I need it in multiple threads because UIScrollView in tiled mode draws the tiles in background threads. So now I need my cache to be thread safe.

    I had to solve two problems: One, mutable array/dictionary holding cached images, and two, returned objects could dissapear while being used in another thread.

    Am I doing this right?

    Code:
    - (UIImage *)cachedImageForAddress:(NSString *)imgAddress
    {
       UIImage  *retImage = nil;
       
       @synchronized(self)  {
          retImage = [self.imageDictionary objectForKey:imgAddress];
       }
       
       return ([[retImage retain] autorelease]);
    }
    Code:
    - (BOOL)cacheImage:(UIImage *)newImage forAddress:(NSString *)imgAddress
    {
       BOOL  retVal = YES;
          
       @synchronized(self)  {
          
          if (![self.imgDicKeys containsObject:imgAddress])  {
             [self.imageDictionary setObject:newImage forKey:imgAddress];
             [self.imgDicKeys addObject:imgAddress];
    
             // See if thre's too many
             
             [self trimImageDictionary:self.imageDictionary
                              withKeys:self.imgDicKeys
                             toMaxSize:kMaxImagesInCache];
          }
          else  if (![self.imageDictionary objectForKey:imgAddress])
             NSLog (@"Inconsistant image cache!");
          else
             retVal = NO;
       }
       
       return (retVal);
    }
    
     
  2. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    There's a race condition in your getter. The returned value could be invalidated on another thread between the time you get it from the dictionary and when it's retained. I think you need to retain it inside the @synchronized block.

    I don't understand what the keys array is for.
     
  3. thread starter macrumors regular

    Joined:
    Sep 11, 2008
    #3
    Oh, thanks for the tip. Now it looks obvious. ;)

    I wasn't sure if allKeys property of the dictionary would always have the oldest element at zero index so I created my own array. Plus, in few methods I compare counts of objects in dictionary and array just to make sure there wasn't some sort of a mixup.
     

Share This Page