[contract] the volatile issue

Hello all, N1962 does not indicate that contracts for volatile members should be handled in any special way (in fact, volatile is not discussed at all in N1962). My library does the following for volatile members: 1) The object `this` is const volatile (and not just const) while checking preconditions, postconditions, and invariants for a volatile member. 2) By default, class invariants of volatile members are the same as for non-volatile members. However, programmers can specify a different set of class invariants for volatile and non-volatile members if they wish to do so. The reason for 2) is that when programming a volatile member that overloads a non-volatile member, programmers can already specify a different set of preconditions and postconditions. Therefore, it seemed reasonable to give the option to also specify a different set of class invariants for volatile and non-volatile members (otherwise why would the pre/postcondition of a volatile member be different from the ones of its non-volatile version while the class invariants are forced to remain the same?). For example, consider a very strange number class which is non-negative (>= 0) when used in non-volatile context but it is non-positive (<= 0) when used in volatile context (probably not a real-life example but still...). The contracts could read: #include <contract.hpp> CONTRACT_CLASS( class (num) ) { CONTRACT_CLASS_INVARIANT( get() >= 0, // (1) volatile class( get() <= 0 ) // (2) ) public: CONTRACT_FUNCTION( public void (set) ( int x ) precondition( x >= 0 ) // 3) postcondition( get() == x ) ) { x_ = x; } CONTRACT_FUNCTION( public void (set) ( int x ) volatile precondition( x <= 0 ) // (4) postcondition( get() == x ) ) { x_ = x; } CONTRACT_FUNCTION( public int (get) ( void ) const ) { return x_; } CONTRACT_FUNCTION( public int (get) ( void ) const volatile ) { return x_; } num ( ) : x_(0) {} private: int x_; }; int main ( ) { num p; p.set(3); num volatile v; v.set(-3); return 0; } Note that via function overloading it is automatically possible to specify a different set of preconditions (and eventually postconditions) for the volatile member (4) than for the non-volatile member (5). Therefore, my library also allows to specify a different set of class invariants for volatile members (2) than for non-volatile members (1) so that the entire contract (including class invariants) can be programmed differently for volatile members if programmers wish to do so. However, if `volatile class(...)` is not used (default) the class invariants: CONTRACT_CLASS_INVARIANT( get() >= 0 ) are applied by the library to all members volatile and non-volatile. (In this case, this invariant is compiled in const volatile context iff the class has one or more volatile functions so a volatile verion of get() is only requirement if a volatile version of set() is introduced.) What do you think? Thanks, --Lorenzo

On 1 October 2011 13:47, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
N1962 does not indicate that contracts for volatile members should be handled in any special way (in fact, volatile is not discussed at all in N1962).
In practical terms, I'm not sure I want checkable contracts for volatile members. volatile roughly means that if I need it for my program to work, something outside of the normal flow of execution will happen to the object. Either it will have side effects when I access it, or its value can be changed out from under me. Given those two situations, how do you envision checkable contracts to work? There is also the idea that Andrei Alexandrescu put forth in <http://drdobbs.com/cpp/184403766> to use volatile member functions for other purposes. Is that the kind of thing you envision applying contracts to? The uses I've seen of volatile on non-primitive types is almost always a programming error. Do you have practical examples where this is not the case? -- Nevin ":-)" Liber <mailto:nevin@eviloverlord.com> (847) 691-1404

On Sat, Oct 1, 2011 at 3:43 PM, Nevin Liber <nevin@eviloverlord.com> wrote:
On 1 October 2011 13:47, Lorenzo Caminiti <lorcaminiti@gmail.com> wrote:
N1962 does not indicate that contracts for volatile members should be handled in any special way (in fact, volatile is not discussed at all in N1962).
In practical terms, I'm not sure I want checkable contracts for volatile members.
volatile roughly means that if I need it for my program to work, something outside of the normal flow of execution will happen to the object.
Either it will have side effects when I access it, or its value can be changed out from under me. Given those two situations, how do you envision checkable contracts to work?
Yep, I agree. I have two alternative: (1) I generate a compile-time error if you contract a volatile member or (2) I support volatile contracts as best as I can given that volatile is part of C++ and leave it to programmers to contract or not their volatile code. Now, assume I want to take option (2), I'm hinting that it makes sense to allow programmers to specify different class invariants for volatile members given that programmers can already specify different pre/postconditions for volatile members (in case they overload a non-volatile member). What do you think?
There is also the idea that Andrei Alexandrescu put forth in <http://drdobbs.com/cpp/184403766> to use volatile member functions for other purposes. Is that the kind of thing you envision applying contracts to?
[side note Cool trick! BTW, on the concurrency + Contract Programming (CP) topic, Meyer goes a long way discussing concurrency and the challenges it poses to Contract Programming (especially postconditions) in his book Object-Oriented Software Construction-- finally he ends up with SCOOP: http://se.inf.ethz.ch/old/people/nienaltowski/papers/scoop_easy_draft.pdf AFAIK, SCOOP was never actually fully implemented and much less used in real code. Plus it's just one way to sync stuff (and as long as you sync before checking contracts when necessary, you can use any synchronization method you want). I myself once implemented a primitive C++ version of SCOOP that used a smart pointer separate_ptr<C> where C is an object that is accessed by multiple threads (maybe I can go back and apply Andrei's LockingPtr volatile trick to my separate_ptr...). ]
The uses I've seen of volatile on non-primitive types is almost always a programming error. Do you have practical examples where this is not the case?
Nope, I have _no_ practical example :( I've never ever used volatile in my real projects. In all the CP references I have studied I've never seen volatile used: http://svn.boost.org/svn/boost/sandbox/contract/libs/contract/doc/html2/cont... Nevertheless, given that I'm trying to implement CP for C++, I need to address how CP will/should work with volatile just because volatile is part of C++. If anyone from Boost has a real-life example of a volatile type that could benefit from contracts, it'd be great to see it! Thanks, --Lorenzo
participants (2)
-
Lorenzo Caminiti
-
Nevin Liber