Thread overview
Assuring resource usage protocols
Aug 02, 2005
Manfred Nowak
Aug 02, 2005
pragma
Aug 02, 2005
AJG
August 02, 2005
A decade ago I detected that in layered software products the layer higher in the hierarchy implements a protocol on the resource usage of the lower layer.

In terms of encapsulation I emphasized this as a principal design flaw.

The discussion on the "destructor bug" reminded me of those thaughts: http://www.digitalmars.com/drn-bin/wwwnews?digitalmars.D.bugs/4636

From this discussion one can conclude also, that the behaviour of destructors in D is not in accordance with the developers thinking of them:

| bypass the normal destructor restrictions, which shouldn't be
| there in the first place.
(AJG in the thread mentioned above)

Therefore I see a danger, that D will be considered as a broken language in terms of developers relying on the "normal" behaviour of destructors.

In type theory protocols on resource usage seem to get awareness: "An Effective Theory of Type Refinements" http://www-2.cs.cmu.edu/~rwh/papers/effref/icfp03.pdf

My idea a decade ago was to interpret the functional elements of an implementation as an alphabet and the protocol as a language over this alphabet. Thus a resource usage assurance can be interpreted as an LALR(1)-parser controlling the accesses to the resource.

Furthermore a parser can be used to automatically repair violations of the protocol by means of an error recovery.

At that time I experimented with an LALR-parser driven by the elements of the alphabet, i.e. functions and procedures, and the grammar, i.e. protocol. The result was, that the idea wasnt wrong in general but would not succeed because the developer community was used to this habit of developing.

The same argument now holds with D to implement it.

-manfred
August 02, 2005
In article <dcn4en$194a$1@digitaldaemon.com>, Manfred Nowak says...
>
>A decade ago I detected that in layered software products the layer higher in the hierarchy implements a protocol on the resource usage of the lower layer.
>
>In terms of encapsulation I emphasized this as a principal design flaw.
>
> <snip>
>
>Therefore I see a danger, that D will be considered as a broken language in terms of developers relying on the "normal" behaviour of destructors.

I'm almost certainly missing the boat here (with respect to language, grammar and protocol layering), so please forgive my ignorance as I dive into the topic. Will the below help, or compound the problem of abnormal destructor behavior?

While I cannot speak to how D's grammar may apply to this issue, I do feel that D's constructor behavior is indeed a flaw with D's implementation, not its design.  The bigger question is: can we get a behavior change out of the D language that will satisfy a more "normal" design?  All I can think of is the impact on the GC, and how it may be more costly at runtime than its worth.

Anyway, the example you cited could be helped with a shim, say something like
"GC.isValid(Object ptr)" or "GC.exists(void* ptr)" that would check to make sure
that a reference is still valid.  It may not be pretty, but its well beyond what
C and C++ gives us for the same problem (AFAIK, nothing).

> class Foo{
>   Bar myref;
>   Foo(){ myref = new Foo(); }
>   ~Foobar(){ if(GC.isValid(myref)) myref.cleanup(); }
> }

'isValid' would simply check an Object's destructor or typeinfo address to ensure that its still within reachable memory.

Also, the issue with destructors can manifest itself in another, much more infurating, way.

If you create an object inside a Dll, using the shared-GC technique, the GC blindly assumes that the object's destructor will be reachable at program termination.  If you then unload that Dll before program termination, your good programming pracitce is rewarded with a GPF/segfault all becuase you (unknowingly) assasinated that object's destrctor before it was collected.

Like above the GC could just simply check for a pointer's validity

- EricAnderton at yahoo
August 02, 2005
Hi,

>I'm almost certainly missing the boat here (with respect to language, grammar and protocol layering), so please forgive my ignorance as I dive into the topic. Will the below help, or compound the problem of abnormal destructor behavior?

It doesn't really solve the problem I originally stated (parents that need to cleanup after children that don't cleanup after themselves). I don't think it will compound the problem either. It would be more of an improvement to the GC (a kind of fine tuning), since it would provide more information.

>While I cannot speak to how D's grammar may apply to this issue, I do feel that D's constructor behavior is indeed a flaw with D's implementation, not its design.

I assume you mean destructors here? If so, I agree it's a problem with the implementation (more specifically, of the GC implementation).

>The bigger question is: can we get a behavior change out of the D
>language that will satisfy a more "normal" design?  All I can think of is the
>impact on the GC, and how it may be more costly at runtime than its worth.

>Anyway, the example you cited could be helped with a shim, say something like
>"GC.isValid(Object ptr)" or "GC.exists(void* ptr)" that would check to make sure
>that a reference is still valid.  It may not be pretty, but its well beyond what
>C and C++ gives us for the same problem (AFAIK, nothing).

IIRC this is not true. C++ let's you access (as it should) children in the destructor. C doesn't have OO so I think the point is moot.

>> class Foo{
>>   Bar myref;
>>   Foo(){ myref = new Foo(); }
>>   ~Foobar(){ if(GC.isValid(myref)) myref.cleanup(); }
>> }
>
>'isValid' would simply check an Object's destructor or typeinfo address to ensure that its still within reachable memory.

This would be useful to prevent a segmentation fault if the child is indeed gone (collected by the GC). But if it's gone, then that child is un-cleanable and you're left with an open database, uncommitted changes, locked hardware, unreleased mutex, or what have you.

>Also, the issue with destructors can manifest itself in another, much more infurating, way.
>
>If you create an object inside a Dll, using the shared-GC technique, the GC blindly assumes that the object's destructor will be reachable at program termination.  If you then unload that Dll before program termination, your good programming pracitce is rewarded with a GPF/segfault all becuase you (unknowingly) assasinated that object's destrctor before it was collected.

Yeah. It'd be nice if the GC could collect everything in a module properly (and call destructors) when it's unloaded dynamically.

Cheers,
--AJG.