🔗 引用计数数据分配器 (仅限 C++)
像 cbdata 使用的手动引用计数很容易出错,并且对程序员来说很耗时。C++ 的运算符重载允许我们创建自动引用计数指针,这些指针将在不再需要对象时释放它们。通过一些谨慎的操作,这些对象可以传递给需要回调数据指针的函数。
🔗 API
自动引用计数涉及两个类 - 一个 RefCountable 类,它为给定派生类的引用计数提供机制。以及一个 ‘RefCount’ 类,它是智能指针,处理 const 正确性,并通知 RefCountable 类引用和取消引用的情况。
🔗 RefCountable
RefCountable 基类定义了一个抽象函数 - deleteSelf()。您必须为每个具体类实现 deleteSelf。deleteSelf() 是对‘operator delete’不是虚函数的一种变通方法。delete Self 通常如下所示:
void deleteSelf() const {delete this;}
🔗 RefCount
RefCount 模板类替换了被引用计数类的参数和变量的指针。通常,人们会创建一个 typedef 来方便用户。
class MyConcrete : public RefCountable {
public:
typedef RefCount<MyConcrete> Pointer;
void deleteSelf() const {delete this;}
};
现在,可以传递 MyConcrete::Pointer 的对象了。
🔗 CBDATA
要创建一个引用计数的 CBDATA 类,您需要重载 new 和 delete,在您的类定义中包含一个宏,并确保任何直接调用您的人(不是作为 cbdata 回调,而是作为正常使用)都持有您对象的 RefCount<> 智能指针。
class MyConcrete : public RefCountable {
public:
typedef RefCount<MyConcrete> Pointer;
void * operator new(size_t);
void operator delete (void *);
void deleteSelf() const {delete this;}
private:
CBDATA_CLASS(MyConcrete);
};
...
/* In your .cc file */
CBDATA_CLASS_INIT(MyConcrete);
void *
MyConcrete::operator new (size_t)
{
CBDATA_INIT_TYPE(MyConcrete);
MyConcrete *result = cbdataAlloc(MyConcrete);
/* Mark result as being owned - we want the refcounter to do the
* delete call
*/
cbdataReference(result);
return result;
}
void
MyConcrete::operator delete (void *address)
{
MyConcrete *t = static_cast<MyConcrete *>(address);
cbdataFree(address);
/* And allow the memory to be freed */
cbdataReferenceDone (t);
}
当不存在 RefCount<MyConcrete> 智能指针时,将调用对象的 delete 方法。这将运行对象析构函数,释放它持有的任何外部资源。然后将调用 cbdataFree,将对象标记为对它可能已排队的任何 cbdata 函数无效。当所有这些都返回后,实际的内存将被返还给池。
🔗 使用引用计数器
引用计数对象的分配和释放(包括 RefCount 模板类的对象)必须通过 new() 和 delete() 来完成。如果一个将持有 RefCount <foo> 变量实例的类不使用 delete(),则在释放该变量之前,您必须将其赋值为 NULL。否则将导致内存泄漏。您已被警告。
切勿在 RefCountable 对象上调用 delete 或 deleteSelf。您将创建大量悬空引用,并且 Squid 最终会发生段错误。
始终创建至少一个 RefCount 智能指针,以便在对象不再需要时,引用计数机制会删除它。
不要将 RefCount 智能指针传递到 Squid 内存空间之外。它们在复制时不可避免地会发生段错误。
如果在某个方法中,所有其他持有智能指针的对象都可能被删除或将其智能指针设置为 NULL,那么您将在方法执行过程中被删除(从而崩溃)。为防止这种情况,请将一个智能指针赋值给自己。
void
MyConcrete::aMethod(){
/* This holds a reference to us */
Pointer aPointer(this);
/* This is a method that may mean we don't need to exist anymore */
someObject->someMethod();
/* This prevents aPointer being optimised away before this point,
* and must be the last line in our method
*/
aPointer = NULL;
}
通过智能指针调用方法很容易,只需使用 -> 进行解引用即可。
void
SomeObject::someFunction() {
myConcretePointer->someOtherMethod();
}
传递 RefCount 智能指针时,始终将它们作为其原生类型传递,切勿作为 ‘*’ 或 ‘&’ 传递。
导航:网站搜索,网站页面,分类,🔼 向上