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


Reply via email to