好的,所以我想在C ++中编写一个精确的'标记和扫描'垃圾收集器。我希望做出一些可以帮助我的决定,因为我的所有指针都将包含在'RelocObject'中,并且我将为堆提供单个内存块。这看起来像这样:
// This class acts as an indirection to the actual object in memory so that it can be
// relocated in the sweep phase of garbage collector
class MemBlock
{
public:
void* Get( void ) { return m_ptr; }
private:
MemBlock( void ) : m_ptr( NULL ){}
void* m_ptr;
};
// This is of the same size as the above class and is directly cast to it, but is
// typed so that we can easily debug the underlying object
template<typename _Type_>
class TypedBlock
{
public:
_Type_* Get( void ) { return m_pObject; }
private:
TypedBlock( void ) : m_pObject( NULL ){}
// Pointer to actual object in memory
_Type_* m_pObject;
};
// This is our wrapper class that every pointer is wrapped in
template< typename _Type_ >
class RelocObject
{
public:
RelocObject( void ) : m_pRef( NULL ) {}
static RelocObject New( void )
{
RelocObject ref( (TypedBlock<_Type_>*)Allocator()->Alloc( this, sizeof(_Type_), __alignof(_Type_) ) );
new ( ref.m_pRef->Get() ) _Type_();
return ref;
}
~RelocObject(){}
_Type_* operator-> ( void ) const
{
assert( m_pRef && "ERROR! Object is null\n" );
return (_Type_*)m_pRef->Get();
}
// Equality
bool operator ==(const RelocObject& rhs) const { return m_pRef->Get() == rhs.m_pRef->Get(); }
bool operator !=(const RelocObject& rhs) const { return m_pRef->Get() != rhs.m_pRef->Get(); }
RelocObject& operator= ( const RelocObject& rhs )
{
if(this == &rhs) return *this;
m_pRef = rhs.m_pRef;
return *this;
}
private:
RelocObject( TypedBlock<_Type_>* pRef ) : m_pRef( pRef )
{
assert( m_pRef && "ERROR! Can't construct a null object\n");
}
RelocObject* operator& ( void ) { return this; }
_Type_& operator* ( void ) const { return *(_Type_*)m_pRef->Get(); }
// SS:
TypedBlock<_Type_>* m_pRef;
};
// We would use it like so...
typedef RelocObject<Impl::Foo> Foo;
void main( void )
{
Foo foo = Foo::New();
}
因此,当我在'RelocObject :: New'中分配时,为了找到'root'RelocObjects,我将RelocObject的'this'指针传递给allocator(垃圾收集器)。然后,分配器检查“this”指针是否在堆的内存块范围内,如果是,那么我可以认为它不是根。
因此,当我想使用位于每个子对象内的零个或多个RelocObjects从子对象跟踪子对象时,问题就出现了。
我想使用'精确'方法在类(即子对象)中找到RelocObjects。我可以使用反射方法并使用户在每个类中注册他或她的RelocObjects。然而,这将非常容易出错,因此我想自动执行此操作。
所以我希望在编译时使用Clang在类中找到RelocObjects的偏移量,然后在程序启动时加载这些信息,并在垃圾收集器的标记阶段使用它来跟踪并标记儿童物品。
所以我的问题是Clang可以帮忙吗?我听说你可以使用编译时钩子在编译期间收集各种类型的信息。如果是这样,我应该在Clang中寻找什么,即有没有做过这种事情的例子?
只是为了明确:我想使用Clang在FooB中自动找到'Foo'的偏移量(这是RelocObject的typedef)而用户没有提供任何“提示”,即他们只是写:
class FooB
{
public:
int m_a;
Foo m_ptr;
};
提前感谢您的帮助。
答案 0 :(得分:1)
每当RelocObject
被实例化时,其地址都可以与RelocObject
一起记录在sizeof(*derivedRelocObject)
所有权数据库中,这将立即识别哪个Foo
属于哪个FooB
}}。你不需要Clang。此外,由于Foo
将在FooB
之后不久创建,所以您的所有权数据库系统可以非常简单,因为“我已经创建,这里是我的地址和大小”调用将直接在其拥有的RelocObject
实例之前显示拥有RelocObject
记录。
每个RelocObject
都有一个ownership_been_declared
标志,在第一次使用时初始化为false(在构造函数完成之后,因为在构造函数中不应该进行任何实际的工作),所以当任何一个那些新创建的对象首先被用来请求数据库更新它的所有权,数据库通过它的记录地址队列,并且可以识别哪些对象属于哪个,从它的列表中清除一些,将它们的ownership_been_declared
标志设置为true并且你也会有偏移(如果你还需要它们)。
P.S。如果你愿意我可以分享我多年前写的增量垃圾收集器的代码,你可能会觉得它很有用。