为什么有人可能将缓存实现为
void DoSomethingWith(CGColorRef color)
{
static CGColorRef cachedColor = NULL;
static int cachedColorID = 0;
if (color == cachedColor && color->colorID == cachedColorID)
{
UseCachedColorTransformations();
}
else
{
cachedColor = color;
cachedColorID = color->colorID;
CalculateColorTransformations();
CacheColorTransformations();
}
...
}
而不是仅仅比较 colorID?
void DoSomethingWith(CGColorRef color)
{
static CGColorRef cachedColor = NULL;
static int cachedColorID = 0;
if (color->colorID == cachedColorID)
{
UseCachedColorTransformations();
}
else
{
cachedColor = color;
cachedColorID = color->colorID;
CalculateColorTransformations();
CacheColorTransformations();
}
...
}
请注意,color->colorID 值是一个从 1 开始的增量值,并在创建时安全地将线程(来自全局计数器的 InterlockedIncrement)分配给颜色。
删除某些颜色并且颜色未在内存中移动或复制时,全局计数器不会递减。因此,每种颜色都有一个唯一的 colorID 值,一个 colorID 只能由一个地址处的一种颜色使用。可以删除某些颜色,并在同一地址创建另一种颜色,因此在同一地址处会有一种具有不同 colorID 的颜色,我们可以使用它来确定它是否是相同的颜色或在该地址重新创建的另一种颜色。
因此,没有必要比较引用,比较 colorID 就足够了;它们是独一无二的,并且在其唯一地址处准确识别一种颜色。
它结合使用
color
指针比较和 colorID
比较进行缓存。这就是为什么可以使用这两种方法来实现缓存,而不是仅仅依赖于colorID
:
确保颜色识别准确性:
cachedColor == color
):这可确保相关颜色对象与内存中当前缓存的实例完全相同。由于颜色可能具有不同的属性,但如果重复使用 colorID
(尽管不太可能),理论上最终可能会得到相同的 colorID
,因此比较指针可以保证您正在使用完全相同的对象。colorID
比较 (color->colorID == cachedColorID
):这可确保缓存的颜色对应于具有相同唯一标识符的颜色。这通常比比较指针更快,并且对于快速检查很有用。处理颜色重用或删除:
colorID
是唯一且递增的,但如果删除颜色并在同一内存地址创建新颜色,则单独的颜色 ID 可能无法保证颜色实例的身份。使用这两种比较可确保如果使用相同的 colorID
但在不同的地址创建新颜色,它不会错误地匹配缓存的颜色。指针比较可确保保留缓存颜色的准确内存位置。针对内存管理问题的鲁棒性:
colorID
不足以保证给定地址处的颜色符合您的预期。通过检查 colorID
和指针,您可以添加一层安全性来处理内存管理或颜色创建中的意外问题。性能权衡:
colorID
比较更昂贵,但它提供了有关颜色标识的明确答案。colorID
比较:这更快,但如果相同的内存地址重复用于不同的颜色,则单独使用可能还不够。总之,双重检查方法提供了一种强大的机制,可确保缓存的颜色数据准确且最新,尽管颜色管理或内存重用存在潜在的复杂性。这在可能动态创建、删除和重用颜色的系统中,或者在缓存数据的完整性对于性能或正确性至关重要的情况下尤其重要。