Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
November 11, 2001 Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
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 |
November 11, 2001 Re: Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Nagle | 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 |
November 11, 2001 Re: Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | 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
|
November 12, 2001 Re: Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Nagle | 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: > > > > 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 |
November 12, 2001 Re: Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
Posted in reply to John Nagle |
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
|
November 12, 2001 Re: Design by contract - detecting reentrancy | ||||
---|---|---|---|---|
| ||||
Posted in reply to Russell Borogove | "Russell Borogove" <kaleja@estarcion.com> wrote in message news:3BF010A6.9EEE7EAD@estarcion.com... > 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. 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. |
Copyright © 1999-2021 by the D Language Foundation