D - Design by contract - detecting reentrancy
- John Nagle (35/35) Nov 10 2001 There's been some interest in what's usually called "design by
- Walter (4/39) Nov 10 2001 The class invariant is called at the entry and exit of each public membe...
- John Nagle (13/62) Nov 11 2001 If you really know when control is outside the object, you
- Walter (6/68) Nov 12 2001 But another thread getting into the object must necessarilly pass throug...
- Russell Borogove (5/11) Nov 12 2001 It seems to me that checking the invariant on entry, while
- Walter (6/15) Nov 12 2001 Yes. After all, D does have pointers, and you can still have pointer bug...
There's been some interest in what's usually called "design by contract", with "entry", "exit", and "class invariant" assertions. The class invariants are supposed to be true whenever control is not within the object. If you take that seriously, you have to be explicit about when control leaves the object. That's rarely done. The difficult problem in the single-thread case is deciding when control has left the via a call, rather than a return. If a call out of an object results in entering the object reentrantly, the assumption that the object is in a valid (invariant=true) state at entry is violated. This often leads to errors. (It's a common problem inside GUI libraries.) Does D deal with this problem at all? I haven't seen any indication that it does. A starting point would be to provide a way to indicate that you're leaving an object. I'd once suggested using "public" for this in C++, so that you'd write a member function like void foo() { x = 1; public { /* control has left the object */ } y = 2; } Within a "public" block, you can't access private members of the object. But you can call public methods of the object. The "public" block is thus "outside" the object. The class invariant has to be true at the start of a public block. If you call a function outside an object from within a member function, without using a "public" block, then somehow it must be determined that object-reentry via recursion is imposible. This is easy to check at run time, but hard to detect at compile time. It's worth thinking about conservative compile-time detection of recursion. Comments? John Nagle Animats
Nov 10 2001
The class invariant is called at the entry and exit of each public member function. I do not see how this can be evaded in the scenario you described. "John Nagle" <nagle animats.com> wrote in message news:3BEDDB78.4517D814 animats.com...There's been some interest in what's usually called "design by contract", with "entry", "exit", and "class invariant" assertions. The class invariants are supposed to be true whenever control is not within the object. If you take that seriously, you have to be explicit about when control leaves the object. That's rarely done. The difficult problem in the single-thread case is deciding when control has left the via a call, rather than a return. If a call out of an object results in entering the object reentrantly, the assumption that the object is in a valid (invariant=true) state at entry is violated. This often leads to errors. (It's a common problem inside GUI libraries.) Does D deal with this problem at all? I haven't seen any indication that it does. A starting point would be to provide a way to indicate that you're leaving an object. I'd once suggested using "public" for this in C++, so that you'd write a member function like void foo() { x = 1; public { /* control has left the object */ } y = 2; } Within a "public" block, you can't access private members of the object. But you can call public methods of the object. The "public" block is thus "outside" the object. The class invariant has to be true at the start of a public block. If you call a function outside an object from within a member function, without using a "public" block, then somehow it must be determined that object-reentry via recursion is imposible. This is easy to check at run time, but hard to detect at compile time. It's worth thinking about conservative compile-time detection of recursion. Comments? John Nagle Animats
Nov 10 2001
If you really know when control is outside the object, you don't have to check the invariant at entry, just at exit. Even better, you only have to check the parts of the invariant that mention variables changed in the function. This allows big invariants with less overhead. The other case where control "leaves" the object is when a thread unlocks a "synchronized" object in the Java sense. That's "leaving the object", since some other thread can get in. If the language knows about synchronization, it needs to know about that. John Nagle Animats Walter wrote:The class invariant is called at the entry and exit of each public member function. I do not see how this can be evaded in the scenario you described. "John Nagle" <nagle animats.com> wrote in message news:3BEDDB78.4517D814 animats.com...There's been some interest in what's usually called "design by contract", with "entry", "exit", and "class invariant" assertions. The class invariants are supposed to be true whenever control is not within the object. If you take that seriously, you have to be explicit about when control leaves the object. That's rarely done. The difficult problem in the single-thread case is deciding when control has left the via a call, rather than a return. If a call out of an object results in entering the object reentrantly, the assumption that the object is in a valid (invariant=true) state at entry is violated. This often leads to errors. (It's a common problem inside GUI libraries.) Does D deal with this problem at all? I haven't seen any indication that it does. A starting point would be to provide a way to indicate that you're leaving an object. I'd once suggested using "public" for this in C++, so that you'd write a member function like void foo() { x = 1; public { /* control has left the object */ } y = 2; } Within a "public" block, you can't access private members of the object. But you can call public methods of the object. The "public" block is thus "outside" the object. The class invariant has to be true at the start of a public block. If you call a function outside an object from within a member function, without using a "public" block, then somehow it must be determined that object-reentry via recursion is imposible. This is easy to check at run time, but hard to detect at compile time. It's worth thinking about conservative compile-time detection of recursion. Comments? John Nagle Animats
Nov 11 2001
But another thread getting into the object must necessarilly pass through an invariant first. "John Nagle" <nagle animats.com> wrote in message news:3BEED746.2D5B90F5 animats.com...If you really know when control is outside the object, you don't have to check the invariant at entry, just at exit. Even better, you only have to check the parts of the invariant that mention variables changed in the function. This allows big invariants with less overhead. The other case where control "leaves" the object is when a thread unlocks a "synchronized" object in the Java sense. That's "leaving the object", since some other thread can get in. If the language knows about synchronization, it needs to know about that. John Nagle Animats Walter wrote:memberThe class invariant is called at the entry and exit of each publicdescribed.function. I do not see how this can be evaded in the scenario you"John Nagle" <nagle animats.com> wrote in message news:3BEDDB78.4517D814 animats.com...There's been some interest in what's usually called "design by contract", with "entry", "exit", and "class invariant" assertions. The class invariants are supposed to be true whenever control is not within the object. If you take that seriously, you have to be explicit about when control leaves the object. That's rarely done. The difficult problem in the single-thread case is deciding when control has left the via a call, rather than a return. If a call out of an object results in entering the object reentrantly, the assumption that the object is in a valid (invariant=true) state at entry is violated. This often leads to errors. (It's a common problem inside GUI libraries.) Does D deal with this problem at all? I haven't seen any indication that it does. A starting point would be to provide a way to indicate that you're leaving an object. I'd once suggested using "public" for this in C++, so that you'd write a member function like void foo() { x = 1; public { /* control has left the object */ } y = 2; } Within a "public" block, you can't access private members of the object. But you can call public methods of the object. The "public" block is thus "outside" the object. The class invariant has to be true at the start of a public block. If you call a function outside an object from within a member function, without using a "public" block, then somehow it must be determined that object-reentry via recursion is imposible. This is easy to check at run time, but hard to detect at compile time. It's worth thinking about conservative compile-time detection of recursion. Comments? John Nagle Animats
Nov 12 2001
John Nagle wrote:If you really know when control is outside the object, you don't have to check the invariant at entry, just at exit. Even better, you only have to check the parts of the invariant that mention variables changed in the function. This allows big invariants with less overhead.It seems to me that checking the invariant on entry, while redundant in the general case, can also help determine if some bug has trashed the object between calls. =RB
Nov 12 2001
"Russell Borogove" <kaleja estarcion.com> wrote in message news:3BF010A6.9EEE7EAD estarcion.com...John Nagle wrote:Yes. After all, D does have pointers, and you can still have pointer bugs <g>. Also, entry invariant checking when combined with the memory stomping of the delete operator should detect detect dangling reference bugs.If you really know when control is outside the object, you don't have to check the invariant at entry, just at exit. Even better, you only have to check the parts of the invariant that mention variables changed in the function. This allows big invariants with less overhead.It seems to me that checking the invariant on entry, while redundant in the general case, can also help determine if some bug has trashed the object between calls.
Nov 12 2001