It seems to me that there are definitely cases where things like this
make sense. But it probably doesn't belong in the collector
distribution
itself. Once you have to wrap an array in this manner, the result
invariably doesn't quite behave like an array, so it really
becomes another library layer, with its own interface that needs to be
reasonably carefully specified.
And there are many possible tradeoffs in the design here. If
performance
is an issue, you would almost certainly prefer an explicit clean-up
function to an extra level of indirection on array accesses. (Why do
you add two levels of indirection?)
A much simpler and less invasive alternative might be a template
that just constructs an array cleanup function for an array of
N elements of type T, so that it becomes easier to use the alternative
currently suggested in gc_cpp.h.
Hans
> -----Original Message-----
> From: gc-bounces at napali.hpl.hp.com> [mailto:gc-bounces at napali.hpl.hp.com] On Behalf Of Neil Toronto
> Sent: Tuesday, April 19, 2005 3:04 AM
> To: gc at napali.hpl.hp.com> Subject: [Gc] Correct, portable array cleanup?
>>> Okay, so I'm new and spamming the list already, but I think I may be
> onto something. From gc_cpp.h:
>> "Implementing clean-up of arrays correctly, portably, and in
> a way that
> preserves the correct exception semantics requires a language
> extension,
> e.g. the 'gc' keyword."
>> I've made a stab, and I don't know enough about exception
> semantics to
> say this is correct, but I think it is. (What ARE correct exception
> semantics during garbage collection?)
>> I've put the first draft online here:
>>https://axon.cs.byu.edu/~neil/array.h>>> Usage:
>> array<A> a(10); // allocates an array of 10 elements, handle
> is 'a' array<B> b(5, "Ha ha"); // allocates an array of 5
> elements, handle 'b',
> calls B::B(const char*) for each
>> for (int i = 0; i < a.size(); i++)
> {
> a[i] = ...
> ... = b[i];
> }
>>> Advantages over naked pointers:
>> - Objects in the array have destructors called when the array is GCd.
>> - Can't point at an array of descendants with a base pointer.
> For example:
>> class A;
> class B : public A;
>> A* p = new B[20]; // compiles fine - icky, bad and evil
> array<A> p = array<B>(20); // illegal - can't convert from
> array<B> to
> array<A>
>> - Bounds-checked access and NULL-pointer check when NDEBUG
> isn't defined.
>> - Exception-safe allocation (can safely use "array<T_>(...)" as a
> function parameter - see https://www.gotw.ca/gotw/056.htm -
> "Exception-Safe Function Calls").
>> - Takes as much space as a naked pointer (sizeof(array<T_>)
> == sizeof(T_*)).
>>> Disadvantages:
>> - Extra level of indirection - access is slower (working on
> this with a
> placement-new solution - hopefully I can make it portable)
>> - Contained object constructors are limited to 20 arguments (can be
> expanded to arbitrary numbers using recursion a la Boost)
>>> Since I haven't played with the collector much, comments are
> very welcome.
>> Neil
>>> _______________________________________________
> Gc mailing list
>Gc at linux.hpl.hp.com>https://www.hpl.hp.com/hosted/linux/mail-archives/gc/>