TITLE: the meaning of const volatile

(Newsgroups: comp.lang.c++.moderated, 5 Oct 96)

CUTHBERT: dacut@ugcs.caltech.edu (David A. Cuthbert)

> Antonio Fatela <afatela@marktest.pt> wrote:
> >At 10.3 of April DWP, there is a reference to 'const volatile'
> >cv-qualifier. Whats the meaning of declaring an object as const volatile?
> 
> My understanding of it is to provide read-only access to a
> memory-based register.

KANZE: kanze@gabi-soft.fr (J. Kanze)

This is one of the principal uses.  It is not really the meaning, as
such.

CUTHBERT:

> For example, let a communications read port exist at 0x300; writing to
> the port will change the status of the port (link rate, etc.), and
> would probably corrupt the stream.  Therefore, some read function
> might contain:
> 
> const volatile char p = *(char *)(0x300);
> 
> The catch is that every time I do an access on p another character is
> removed from the port.  In other words, code like:
>  
> 	if(p == 'a') cout << "a ";
> 	else cout << "!a ";
> 
> 	if(p == 'a') cout << "a ";
> 	else cout << "!a ";
> 
> is *not* guaranteed to print out "a a" or "!a !a", but can print 
> "a !a" or "!a a".
> 
> To the compiler, volatile directs it to make no optimization
> assumptions on that variable.  In my experience, there is rarely a
> need for it except on embedded systems.

KANZE:

This is a good example.  More precisely: in a const volatile, both const
and volatile have their full meaning.

Strictly speaking, the exact meaning of volatile is implementation
dependant; the intent is to tell the compiler that the variable may
change in ways not visible to it.  (Memory mapped IO ports are a good
example.  So are variables that may be modified by asynchronous events,
e.g. in signals or by another process or thread.)  The effect is (or
should be), exactly what you say: the compiler will not optimize code
using that variable.  (In standardese: there should be a one to one
correspondance between the abstract machine and the actual semantics.)

Adding const does not change the meaning of volatile in any way.  It
does mean that the compiler will consider the variable non-modifiable,
and will generate an error on any attempt by the program to modify it.
It doesn't remove the effect of volatile, however.  The compiler should
still consider that the value of the variable may change in ways unknown
to it.

Variants on the above example (memory mapped IO) probably account for
99% of its use; another possible use would be in shared memory (between
processes) where the memory is mapped read only for one of the
processes.  Although the typical low level use makes such occasions
rare, any time you have a function which takes a X const&, and the value
of the parameter may change asynchronously (in a signal handler or
another thread), you should declare it X const volatile&.  In practice,
such cases don't occur in threads because if X is a simple type, you
will use pass by value, and if it is a complex type, you will use some
sort of external locking to ensure that it doesn't change when you are
in the middle of accessing it.

