繁体   English   中英

静态Objective-C类的记忆

[英]Memoization in static Objective-C class

说我有一个类方法

+ (double)function:(id)param1 :(id)param2
{
   // I want to memoize this like...
   static NSMutableDictionary* cache = nil;
   //
   // test if (param1,param2) is in cache and return cached value, etc. etc
   //
}

谢谢!!

如果要一次创建缓存并进行检查,通常使用+initialize方法。 该方法在发送给该类的第一条消息之前被调用,因此可以在+function:: :(它是一个糟糕的选择器名称)之前创建缓存。 在这种情况下,我通常在.m文件中声明缓存变量,但是在方法定义中声明它也可能起作用。


编辑:在OP的请求下添加一个示例:

// MyClass.m

static NSMutableDictionary* cache;

+ (void) initialize {
    cache = [[NSMutableDictionary alloc] init];
}

+ (double) cachedValueForParam1:(id)param1 param2:(id)param2 {
    // Test if (param1,param2) is in cache and return cached value.
}

显然,如果缓存中不存在任何值,则应该有一些添加该值的代码。 另外,我也不知道您打算如何将param1param2组合为缓存的键,或者如何存储值。 (也许+[NSNumber numberWithDouble:]-[NSNumber doubleValue]吗?)在实现这种策略之前,您需要确保了解字典查询。

我使用类似以下的内容。 与@Quinn Taylor发布的版本不同,此版本具有以下属性:

  • 创建一个NSAutoreleasePool以确保池存在。 最好在处理“启动”之类的代码时假设最坏的情况。 如果池已经存在,则无害。
  • 一次创建一次cache
    • 可以安全地调用+initialize多次+initialize (可能通过子类发生)。
    • 多线程安全。 无论有多少个线程在同一时间并发调用+initialize ,都保证只创建一次cache “赢得”原子CAS的线程保留cache ,“松散”的线程autorelease其尝试。

如果要非常保守,可以添加断言检查,以确保poolinitCache都不为NULL 还要注意,这样做并不能确保cache一旦创建便以多线程安全方式使用。

#include <libkern/OSAtomic.h>

static NSMutableDictionary *cache;

+ (void)initialize
{
  NSAutoreleasePool   *pool      = [[NSAutoreleasePool alloc] init];
  NSMutableDictionary *initCache = [[[NSMutableDictionary alloc] init] autorelease];
  _Bool                didSwap   = false;

  while((cache == NULL) && ((didSwap = OSAtomicCompareAndSwapPtrBarrier(NULL, initCache, (void * volatile)&cache)) == false)) { /* Allows for spurious CAS failures. */ }
  if(didSwap == true) { [cache retain]; }

  [pool release];
  pool = NULL;
}

根据您要执行的操作以及线程安全性是否是一个问题,您可能还想考虑一个单例类,如对此先前问题的回答中所示

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM