On 06/28/10 21:16, Tom Tromey wrote:
[snip]
>
> I think we should be clear that the need to write a mark function for a
> new type is a drawback of this approach. Perhaps gengtype could still
> write the functions for ordinary types in GCC, just not (templatized)
> containers.
[snip]
An alternate way to generate the needed information is to wrap
each garbage collected pointer within a smart pointer, say
gcptr<T>, and the CTOR for that gcptr<T> was instrumented to report
the offset of it's this pointer w.r.t. some global pointer, say:
char* start_object=0;
and that start_object was pointing to the beginning of the object, say
of type U, containing the gcptr<T>, then that would give you the same
information as currently done by gengtype for a particular type, U.
Of course start_object could be set by some function before
"artificially" creating an object of type U. Say:
template<U>
void artificially_create(void)
{
char buf[sizeof(U)];
start_object=buf;
//Initailize some sort of "data store"
//for recording the location of gcptrs
//pointers in U.
//Call this gcptr_locations<U>.
//
new (buf) U;
//
//Close "data store" gcptr_locations<U>.
//
start_object=0;//indicate to gcptr *not* to record offsets.
}
And gcptr could be something like:
template<T>
struct gcptr
{
T*ptr;
gcptr()
{
if (start_object)
{
void*voidp_me=this;
char*charp_me=static_cast<char*>(voidp_me);
unsigned offset_me=start_object-charp_me;
//
//Store offset_me in gcptr_locations<U>.
//
}
}
...
//other member functions
};
The gcptr_locations<U> could then be used to generate a mark function,
specialized on U:
template<typename T>void mark(T&);
template<>void mark(U& u)
{
// use gcptr_locations<U> to mark gcptr<T>'s within u.
}
Of course, the 'if (start_object){...}' could be surrounded by an:
#if GC_OFFSET_CALC
#endif
which would be disabled during actually running the compiler instead
of calculating the offsets. Of course this would save much time since
it would just eliminate 1 test; however, it might make the code
clearer. This #if .. #endif would also surround the start_object
declaration since that wouldn't be needed at runtime either.
One disadvantage of this (besides the need for the 'if (start_object)'
in all gcptr CTOR's), is that any struct, X, which contains (via
inheritance or member variables) another struct, Y, which contains
gcptrs, would duplicate the gcptr information in Y instead of just
referring to it via some call like:
mark(u.y)
where, within X there's the member declaration:
Y y;
Such a scheme was implemented years ago. Code is located here:
https://svn.boost.org/trac/boost/browser/sandbox-branches/cppljevans/boost/fields_visitor/
However, fields_visitor code does not use gcptr. Instead, IIRC, the
template name is a template parameter. Also, to handle something like
std::vector<T>, which may gcptr's within T, the code in the
container_extern directory would be used.
Unfortunately, the code has not been maintained; however, if there's
any interest, I'd revive it.
-regards,
Larry