March 31, 2008
Kevin Bealer Wrote:

> Simen Kjaeraas Wrote:
> 
> > On Mon, 31 Mar 2008 05:13:50 +0200, Kevin Bealer <kevinbealer@gmail.com> wrote:
> > 
> > > In languages like D and C++, the garbage collection is conservative, and this means that any pointer-sized block will be considered a pointer if it contains a value that is an address of any area that might still be live.
> > >This means that a few "garbage" blocks can be kept around because they
> > > are in a memory area which is pointed to by some random integer. This also means that in practice, even for sets of memory blocks that are not circular and might have an obvious destruction order could not be guaranteed to be destroyed in the right order, because a random integer in any of them might make them seem circular, so relying on any policy that tried to detect circularity would be unreliable at best.
> > 
> > In D, an allocated block can be marked as containing no pointers, and thus will not be scanned for things looking pointers. I don't know how good the GC/compiler is at understanding these things on its own, but at least a programmer can make it more informed.
> > 
> > --Simen
> 
> Yes, and I forgot to mention that at one point the D compiler got an upgrade that made it more "precise" (the opposite of "conservative" in GC jargon).  It now knows that a dynamically allocated array of a primitive type (such as an int[] array or one of the string types) is not a pointer.

Oops -- I meant the data in the array -- the array actually is a pointer/length.

> So if you are dealing with lots of large matrices or lots of string data, you should suffer much less from the effects of the accidental retention of blocks. I don't think it affects for structures, classes, or stack data, though it would probably be straightforward to do this for structures that had no pointers.
> 
> Kevin
> 

March 31, 2008
Kevin Bealer a écrit :
> There are some ways to work around this though -- If object A needs
> to call B.close(), then a reference to object B can be stored in a
> global (or static) variable as well as in object A.  After object A's
> destructor calls B.close(), then it should remove B from the global
> table, thus making B garbage (B will not actually get freed until the
> next GC cycle.)  (Make sure the table doesn't need to synchronize for
> the "remove" step since that could cause deadlock, so an associative
> array is probably a bad idea.)

What about this solution:

class Parent
{
	private Child mychild;

	this()
	{
		mychild = new Child();
		addRoot(mychild);
	}

	~this()
	{
		mychild.close();
		removeRoot(mychild);
	}
}

That would not destroy mychild until the Parent object destructor is called. One could even add "delete mychild" at the end of ~this to make it even more efficient, if we suppose that mychild is useless anyway without its Parent (which is often the case, consider a I/O object, i.e. a socket, attached to a "parent" that control it).

The downside of this solution is that you're basically falling back to manual memory management (sort of), but I don't think it is avoidable.

By the way, I never understood why the I/O objets in Phobos and Tango (i.e. FileConduit) do not automatically close() themselves in their destructors... that would solve the problem in the majority of cases.
March 31, 2008
Walter Bright wrote:
> 
> http://reddit.com/r/programming/info/6d210/comments/

I think the real paradigm shift will come from 'pure', not from 'safe D' (or even const).
I'd love to be able to mark most of my functions as pure right now (even before it's enforced by the compiler).
March 31, 2008
== Quote from Kevin Bealer (kevinbealer@gmail.com)'s article
> Mark/sweep doesn't have the problem of circular reference counts, but on the other hand, there is no way to figure out which blocks were parents of which others, so that destruction order is essentially random.  There is no way to fix this reliably, especially since the circular links can mean that the objects are both parents of each other -- so what order do they get destroyed in?

This should probably be qualified by saying that there is no efficient way to
find the parent object, and in the case of circular chains, there may not even
be a parent object.  However, in the general case the GC could theoretically
maintain enough bookkeeping information to destroy objects hierarchically
when possible.  But I suspect that doing so would greatly increase both the
memory needed for a scan and the time involved.  Thus, guaranteeing in-
order destruction simply isn't practical, even when it's possible.


Sean
March 31, 2008
Sean Kelly Wrote:

> == Quote from Kevin Bealer (kevinbealer@gmail.com)'s article
> > Mark/sweep doesn't have the problem of circular reference counts, but on the other hand, there is no way to figure out which blocks were parents of which others, so that destruction order is essentially random.  There is no way to fix this reliably, especially since the circular links can mean that the objects are both parents of each other -- so what order do they get destroyed in?
> 
> This should probably be qualified by saying that there is no efficient way to
> find the parent object, and in the case of circular chains, there may not even
> be a parent object.  However, in the general case the GC could theoretically
> maintain enough bookkeeping information to destroy objects hierarchically
> when possible.  But I suspect that doing so would greatly increase both the
> memory needed for a scan and the time involved.  Thus, guaranteeing in-
> order destruction simply isn't practical, even when it's possible.
> 
> Sean

Yes -- especially for a precise collector in a language like Java, but I'd be
reluctant to make assumptions about the data in this way in a conservative
collector;  I think the bookkeeping you mention would require the GC to
have nearly perfect type information, which would make it impossible to
do many things.

If object A has noisy data that happens to point into B's area, then you have a relationship from A to B.  If B also has a relationship to A, then you get a cycle, and the GC has to fall back on unordered destruction.  If B expects the GC to make sure that A still exists this could be a problem.

Unless the user specifically marks these relationships, it seems difficult to do this reliably.  This could be done of course, but as long as we need to change B, why not make B handle cleanup in its own destructor?

For extra control over B's behavior, the B object could take a function pointer (not a delegate) that told it how to clean itself up.  I think we can assume that function pointers won't point to anything collectable.  Maybe something like this:

class B {
    // I don't remember the function pointer syntax...
    void setDestructHandler(void (*foo)(B*));
};

Kevin

April 03, 2008
Don Clugston wrote:
> I think the real paradigm shift will come from 'pure', not from 'safe D' (or even const).
> I'd love to be able to mark most of my functions as pure right now (even before it's enforced by the compiler).

Pure is coming!
April 26, 2008
Op Tue, 25 Mar 2008 11:18:22 -0700, schreef Walter Bright:

> Features from Modula-3 make me nervous, as Modula-3 was an abject failure. I don't know why M3 failed, so I am suspicious of adopting features without thoroughly understanding why M3 failed.

<http://en.wikipedia.org/wiki/Modula-3#Historical_development>

According to this Wikipedia article, it might have something to do with it being designed by DEC and then DEC practically dying...


-- 
JanC
1 2 3 4 5 6
Next ›   Last »