Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Q: infos, articles, faqs about 'volatile'

677 views
Skip to first unread message

Torsten Mohrin

unread,
Apr 9, 2001, 1:08:01 PM4/9/01
to

I've seen from previous discussions that 'volatile' in C++ seems to be
a rather difficult and controversial thing. Do you know any article or
FAQs, etc. with a good summary of the usage and meaning of 'volatile'
in C++? I'm especially interested in the relevance of 'volatile'
regarding MT programming.

Thanks
--Torsten

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]
[ about comp.lang.c++.moderated. First time posters: do this! ]

Carlos Moreno

unread,
Apr 9, 2001, 8:51:21 PM4/9/01
to

> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++? I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

I just typed "C++ volatile" in the Google search and got a bunch of
results.

Basically, volatile means that the value of some object could
unexpectedly change for no apparent reason -- an example of this
would be a global variable that is accessed by other threads or
by interrupt routines (or event handlers).

The main (only?) consequence of this is that the compiler will
not attempt the least bit of optimisation regarding any access
to such qualified object; for instance:

external_signal_received = false;

a = b + c;
if (b > 0) c = 3;
//... etc.

if (! external_signal_received)
{
// ...


Notice that this piece of code could actually make sense; you
want to know if between the instruction a = b+c and the etc.
something happened (thus, the external_signal_received variable
would be global, and some interrupt routine will presumably
set it to true to notify the rest of the code that such
condition just happened).

Ok, what would happen if the optimiser tries to pretend that
it is smarter than you? It will think that you didn't know
what you were doing and that you didn't realize that the value
of external_signal_received, at the point of the if, has to
be false -- so, of course, since the optimiser is conviced
that it is smarter than you, then it will simply optimise
the if away, and it will not read the contents of ext_sig_rcvd;
instead, it will assume or predict what its value would be
(which according to the normal flow of execution of that
fragment of code, it would seem like it has to be `false').

This is one (silly) example of a variable that would have to
be volatile-qualified for this to work as you really wanted
to -- sure, if you make sure that you disable the optimisation
when compiling this, chances that this doesn't work are low;
but then again, it is not a good idea to write code that
relies on what switches are used to compile it; volatile
would override any optimisation settings when it comes to
access that particular object.

HTH,

Carlos
--
PS: Why do you think that this topic is controversial?

Michael Champigny

unread,
Apr 9, 2001, 9:08:50 PM4/9/01
to
Volatile has *no* relavance to MT programming. Volatile tells the compiler
not to optimize away a variable which could have it's value changed outside
the control of the program (ie. a hardware register or port).

I'm not sure where this connection between MT and volatile has come from
lately. I hope that helps!

-Michael


Torsten Mohrin wrote:

> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++? I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Ivan Krivyakov

unread,
Apr 10, 2001, 4:04:15 AM4/10/01
to
> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++? I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

I don't know about such article or FAQ.
I would summarize it like this:

1. Use volatile with PODs (built-in types and simple structs)
in order to prevent optimization. This may be useful when
you access memory-mapped hardware registers.

2. It is possible to declare class instance as volatile, but such object is
almost useless. Volatile objects of class type are very restricted in
what they can do.

3. Don't rely on volatile for MT synchronization. Volatile is only
a way to suppress optimization. It does not guarantee MT safety.
Use operating system specific synchronization mechanisms to protect your data
(i.e. semaphores, events, signals, locked increments/decrements, etc.)
If you want to write (semi-)portable MT code you may take a look
at libraries such as ACE (http://www.cs.wustl.edu/~schmidt/ACE.html)

Regards
Ivan

Carlos Moreno

unread,
Apr 10, 2001, 12:25:30 PM4/10/01
to

Michael Champigny wrote:
>
> Volatile has *no* relavance to MT programming. Volatile tells the compiler
> not to optimize away a variable which could have it's value changed outside
> the control of the program (ie. a hardware register or port).
>
> I'm not sure where this connection between MT and volatile has come from
> lately. I hope that helps!

Huh?? Maybe my knowledge in MT is outdated... But I think the
connection
can't be more obvious! (see the example in my other post).

In MT programming, asynchronous execution of things has to be expected,
and if you're sharing data between two threads, I think you better tell
the compiler that it is volatile (the examples that you give, register
or port, are perfectly valid, but are not the only situations where an
object can "unexpectedly" change its value).

I may be missing something? If so, could you (or someone else) please
show me what I'm missing? How would you handle the type of situation
that I showed in my other post? Or is it fundamentally wrong to do so?
(in that case, what would be the recommended approach to achieve an
equivalent result?)

Cheers,

Carlos
--

Torsten Mohrin

unread,
Apr 10, 2001, 2:14:08 PM4/10/01
to
On 9 Apr 2001 21:08:50 -0400, Michael Champigny
<michael....@compaq.com> wrote:

>Volatile has *no* relavance to MT programming. Volatile tells the compiler
>not to optimize away a variable which could have it's value changed outside
>the control of the program (ie. a hardware register or port).

I understand the usage of volatile for memory mapped I/O register and
stuff like that. But there are some examples in literature and
discussions that explain the usage with interrupt/signal handler
functions that modify a variable. What is the relevant difference
between an interrupt handler and a second thread (on a single
processor system)?

>I'm not sure where this connection between MT and volatile has come from
>lately.

Discussions in several newsgroups (with different opinions about this
subject).

--Torsten

Torsten Mohrin

unread,
Apr 10, 2001, 2:14:54 PM4/10/01
to
On 9 Apr 2001 20:51:21 -0400, Carlos Moreno <mor...@mochima.com>
wrote:

>I just typed "C++ volatile" in the Google search and got a bunch of
>results.

I did it, too. That is the very reason that I'm asking for a good
summary :)

Thanks for your explanation. However, I know the meaning of 'volatile'
with basic C types. I'm just not aware of all the consequences of
volatile objects and volatile member functions. I'm programming in C++
for years and fully understand 'const', but never dealed with
'volatile' before.

--Torsten

TiTi

unread,
Apr 10, 2001, 6:37:47 PM4/10/01
to

Torsten Mohrin <torsten...@gmx.net> schreef in berichtnieuws
3ad18317...@news.randori.com...

> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++? I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

Well, the standard doesn't mention much about the semantics of the keyword
volatile. It does explain how to handle volatile qualified variables and
stuff (and cv-qualified variables in general).
The 'volatile' keyword is a sort of a hint to the compiler to not optimize
any variables that are volatile qualified. The rest of the semantics of the
volatile keyword is implementation dependent. Most of the times, a variable
is volatile qualified if the variable can be changed (eg its value may be
changed) by another process (eg an OS).
TiTi

Anthony DeRobertis

unread,
Apr 10, 2001, 6:53:50 PM4/10/01
to
In <9asvjc$140ig$1...@nose.shr.dec.com>, "Michael Champigny"
<michael....@compaq.com> wrote:


> I'm not sure where this connection between MT and volatile has come
> from lately. I hope that helps!

bool a;
startThread(func, &a);
a = false;
while (!a) {
...
}

void func(bool *completion) {
...
*completion = true;
}

where startThread starts a pre-emptive thread is a good use of
`volatile.' Without volatile, the optimizer can --- and probably will
-- optimize that into a endless loop.

PS: Yes, I know there is a race condition in the above ;-)

Chris Uzdavinis

unread,
Apr 10, 2001, 6:58:25 PM4/10/01
to
Carlos Moreno <mor...@mochima.com> writes:

> In MT programming, asynchronous execution of things has to be
> expected, and if you're sharing data between two threads, I think
> you better tell the compiler that it is volatile (the examples that
> you give, register or port, are perfectly valid, but are not the
> only situations where an object can "unexpectedly" change its
> value).

Wouldn't it be considered an OS bug if the context switch didn't
properly save/restore registers?

(I'm a bit naive when it comes to effective use of "volatile" but I
don't see why it should be necessary to use for additional thread
safety.)

I hope someone will correct me if I'm wrong.

--
Chris

Robert O'Dowd

unread,
Apr 11, 2001, 5:00:13 AM4/11/01
to
Carlos Moreno wrote:
>
> Michael Champigny wrote:
> >
> > Volatile has *no* relavance to MT programming. Volatile tells the compiler
> > not to optimize away a variable which could have it's value changed outside
> > the control of the program (ie. a hardware register or port).
> >
> > I'm not sure where this connection between MT and volatile has come from
> > lately. I hope that helps!
>
> Huh?? Maybe my knowledge in MT is outdated... But I think the
> connection
> can't be more obvious! (see the example in my other post).
>
> In MT programming, asynchronous execution of things has to be expected,
> and if you're sharing data between two threads, I think you better tell
> the compiler that it is volatile (the examples that you give, register
> or port, are perfectly valid, but are not the only situations where an
> object can "unexpectedly" change its value).
>
> I may be missing something? If so, could you (or someone else) please
> show me what I'm missing? How would you handle the type of situation
> that I showed in my other post? Or is it fundamentally wrong to do so?
> (in that case, what would be the recommended approach to achieve an
> equivalent result?)
>

I can see why you'd draw a link between volatile and multi-threaded
code, but tht link is a bit spurious for a few reasons.

1) The C++ standard is silent on multi-threading, so anything
with multi-threading exhibits undefined behaviour.
Any link to the "volatile" keyword is up to interpretation
by compiler and library vendors.

2) Even if we ignore the fact that we're outside the C++ standard....
in multi-threaded code, the result of any access to a value,
object or block of memory while another thread is modifying it
gives indeterminate results or behaviour. That's why
things like synchronisation primitives (mutex's, critical
sections, etc) exist in multithreading libraries: allow a
programmer to serialise access and prevent that sort of thing
happening. The volatile keyword does not magically give a
means of avoiding using those primitives.

3) Assuming we're using synchronisation primitives to correctly
serialise access to some object, then those primitives will
ultimately result in a call to some library or operating
system function. It is unlikely a compiler will arbitrarily
assume an object remains unchanged across those calls.
Even without multithreading support, an aggressive compiler
that assumes an object will not change across an arbitrary
function call runs the risk of that function doing
something (eg doing a typecast to remove const attributes)
that allows the object to be modified. That is the same
concern that arises with multi-threaded code, regardless
of the volatile keyword.

OTOH, use of the volatile keyword can't hurt in this case. But,
IMHO, in multi-threaded code the hint it gives to the compiler
is redundant.

Maciej Sobczak

unread,
Apr 11, 2001, 12:21:27 PM4/11/01
to
Hi,
"Chris Uzdavinis" <ch...@atdesk.com> wrote in message
news:j6u23wd...@explicit.atdesk.com...

> Carlos Moreno <mor...@mochima.com> writes:
>
> > In MT programming, asynchronous execution of things has to be
> > expected, and if you're sharing data between two threads, I think
> > you better tell the compiler that it is volatile (the examples that
> > you give, register or port, are perfectly valid, but are not the
> > only situations where an object can "unexpectedly" change its
> > value).
>
> Wouldn't it be considered an OS bug if the context switch didn't
> properly save/restore registers?
>
> (I'm a bit naive when it comes to effective use of "volatile" but I
> don't see why it should be necessary to use for additional thread
> safety.)
>
> I hope someone will correct me if I'm wrong.

Here is my 0.03 Euro:
As it comes to OS, some of them can use the CPU itself to swap registers, so
it wouldn't be an OS bug, anyway.

What is the problem in volatile/MT subject is that volatile tell the
compiler not to put things into a register as an optimization.
Consider this:

int sum = 0;
int count = 60;
while (count--)
{
sleep(1); // sleep one second
sum += global_variable;
}
// now 'sum' keeps the sum of all the 'probes' of the global_variable, taken
every one second

This code will add up all the values that the global_variable has, every one
second, for one minute.
And let's suppose that global_variable is subject to be changed by another
thread.
We would like the code above to sum up the values of this variable, by
*inspecting* its value every second. The problem is, that the compiler can
make some optimization so that it will copy the value of the global_variable
into one of the CPU registers, 'sum' to another and later, make the addition
only using the registers. This example is quite stupid, because in the loop
we have a function call, which means that such an optimization doesn't make
any sense (unless we have a CPU with function frames kept in the stack of
registers - I forgot the name), but the idea remains.
Such an optimization would just multiplicate the value of the
global_variable as it was at the beginning of the loop. So, we want to tell
the compiler explicitely: "hey, this variable can be changed by other means
that the normal flow of execution, so *always* refer to the original value,
not to any of its copies". And that's why we declare it like here:

volatile int global_variable;

Hope it helps.

Maciej Sobczak, http://www.cern.ch/Maciej.Sobczak
"in theory, there is no difference between theory and practice - but in
practice, there is"

Maciej Sobczak

unread,
Apr 11, 2001, 12:28:31 PM4/11/01
to
Hi,
"Anthony DeRobertis" <anthony.d...@crossmedia.net> wrote in message
news:9av58d$km3$1...@bob.news.rcn.net...

> In <9asvjc$140ig$1...@nose.shr.dec.com>, "Michael Champigny"
> <michael....@compaq.com> wrote:
>
>
> > I'm not sure where this connection between MT and volatile has come
> > from lately. I hope that helps!
>
> bool a;
> startThread(func, &a);
> a = false;
> while (!a) {
> ...
> }
>
> void func(bool *completion) {
> ...
> *completion = true;
> }
>
> where startThread starts a pre-emptive thread is a good use of
> `volatile.' Without volatile, the optimizer can --- and probably will
> -- optimize that into a endless loop.
>
> PS: Yes, I know there is a race condition in the above ;-)

Why?
One thread writes, the other reads.
Putting aside the fact, that Standard tells nothing about the sizeof(bool),
which can be for example bigger than the bus width (which could imply more
than one memory access to set the variable to "true"), we can assume that
setting bool variable is atomic. No races here.
Am I wrong?

Maciej Sobczak, http://www.cern.ch/Maciej.Sobczak
"in theory, there is no difference between theory and practice - but in
practice, there is"

R. Sinoradzki

unread,
Apr 11, 2001, 1:14:13 PM4/11/01
to
Torsten Mohrin wrote:
>
> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++? I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

from the standard clause 1.9

9 When the processing of the abstract machine is interrup-
ted by receipt of a signal, the values of objects
with type other than volatile sig_atomic_t are unspecified,
and the value of any object not of volatile sig_atomic_t
that is modified by the handler becomes undefined.

So I think this is the basic type to work with ...

bye Ralf

Dima Volodin

unread,
Apr 11, 2001, 8:08:19 PM4/11/01
to
Torsten Mohrin wrote:
>
> I've seen from previous discussions that 'volatile' in C++ seems to be
> a rather difficult and controversial thing. Do you know any article or
> FAQs, etc. with a good summary of the usage and meaning of 'volatile'
> in C++?

It's all in 1.9, paragraphs 6 through 11.

> I'm especially interested in the relevance of 'volatile'
> regarding MT programming.

In POSIX threads (that is in a C++ implementation that uses POSIX
threads in a way a C implementation would do it), 'volatile' is
absolutely irrelevant. It may or may not be true for other flavours of
MT.

> --Torsten

Dima

Dima Volodin

unread,
Apr 11, 2001, 8:08:52 PM4/11/01
to
Torsten Mohrin wrote:
>
> Thanks for your explanation. However, I know the meaning of 'volatile'
> with basic C types. I'm just not aware of all the consequences of
> volatile objects and volatile member functions. I'm programming in C++
> for years and fully understand 'const', but never dealed with
> 'volatile' before.

See [7.1.5.1/7], [9.3.2/1] and [9.3.2/3]. The idea is that for volatile
objects, only volatile member functions can produce any meaningful
results.

> --Torsten

Dima

Dima Volodin

unread,
Apr 11, 2001, 8:09:27 PM4/11/01
to
Carlos Moreno wrote:
>
> Huh?? Maybe my knowledge in MT is outdated... But I think the
> connection
> can't be more obvious! (see the example in my other post).
>
> In MT programming, asynchronous execution of things has to be expected,
> and if you're sharing data between two threads, I think you better tell
> the compiler that it is volatile (the examples that you give, register
> or port, are perfectly valid, but are not the only situations where an
> object can "unexpectedly" change its value).
>
> I may be missing something? If so, could you (or someone else) please
> show me what I'm missing? How would you handle the type of situation
> that I showed in my other post? Or is it fundamentally wrong to do so?
> (in that case, what would be the recommended approach to achieve an
> equivalent result?)

I can't believe you've missed the prolonged thread about the relevance
of 'volatile' to multithreading. If you have, you'd better have a look
at deja.com (or whatever its name is). To sum it up - the only things
you can use for data consistency in MT are the primitives that the MT
environment explicitly provides for this purpose, and 'volatile' as
defined by the language is not one of these primitives. In POSIX, the
synchronization primitives are mutexes, and using 'volatile' would gain
you nothing but performance degradation, and accessing shared data
without using mutexes produces undefined results whether these data are
declared volatile or not.

> Carlos

Dima

Carlos Moreno

unread,
Apr 11, 2001, 8:10:17 PM4/11/01
to

Robert O'Dowd wrote:
>
> I can see why you'd draw a link between volatile and multi-threaded
> code, but tht link is a bit spurious for a few reasons.
>
> 1) The C++ standard is silent on multi-threading, so anything
> with multi-threading exhibits undefined behaviour.
> Any link to the "volatile" keyword is up to interpretation
> by compiler and library vendors.

Agreed. But still, the C++ standard doesn't say anything about
variables mapped to a hardware port or anything... Yet the
volatile keyword is there to "help" in that type of situation...

The important thing is that volatile keeps the compiler from
optimizing any access, as you're telling the compiler that
something "external" to the code it has in front could unexpectedly
change its value...

> 2) Even if we ignore the fact that we're outside the C++ standard....
> in multi-threaded code, the result of any access to a value,
> object or block of memory while another thread is modifying it
> gives indeterminate results or behaviour.

Not necessarily. Modifying a boolean flag is an atomic operation;
You may need to check periodically if a certain condition has
happened -- in a real-time (maybe embedded) system, where such
condition will typically be associated to external hardware
events, the system can not be sensible to the fact that the
event was flag half a nanosecond before or after the value is
read by the other thread... Worst case, during the next "tick",
the condition will be detected...

In any case, that could be typical in embedded systems design,
where you typically have a "dual-thread" (as opposed to MT) due
to the interrup-driven approach that is often used.

The thing is, if you don't use volatile in there, the compiler
might indeed break your code -- it is free to assume that it
doesn't need to check the value of the boolean flag because
it predicts its value -- when you tell it that something
external to that piece of code could modify it, then it [the
compiler] will know that it better checks the value, and that
it would be wrong to optimize the access...

> That's why
> things like synchronisation primitives (mutex's, critical
> sections, etc) exist in multithreading libraries: allow a
> programmer to serialise access and prevent that sort of thing
> happening. The volatile keyword does not magically give a
> means of avoiding using those primitives.

No! And I wasn't suggesting otherwise... But you're referring
to more than just sharing data... You're referring to either
sharing data that requires complex operations to update (and
that can't be interrupted in the middle of a "transaction"), or
to properly synchronize threads (which boils down to the above).
Sure you need extra tools/tricks to do that.

> OTOH, use of the volatile keyword can't hurt in this case. But,
> IMHO, in multi-threaded code the hint it gives to the compiler
> is redundant.

I guess the bottom line is that volatile can help in certain
situations that arise in MT programming, but not always. MT
tools can help in situations where volatile would do, as well
as in situations where volatile would not be right.

Maybe, as an extra conclusion I could add that in general, when
working in MT, if you do something that relies on the volatile
keyword, then it is probably a sign that your design is not
quite good?

Cheers,

Carlos
--

David Bradley

unread,
Apr 11, 2001, 8:12:21 PM4/11/01
to
Chris Uzdavinis wrote:

> Carlos Moreno <mor...@mochima.com> writes:
>
> > In MT programming, asynchronous execution of things has to be
> > expected, and if you're sharing data between two threads, I think
> > you better tell the compiler that it is volatile (the examples that
> > you give, register or port, are perfectly valid, but are not the
> > only situations where an object can "unexpectedly" change its
> > value).
>
> Wouldn't it be considered an OS bug if the context switch didn't
> properly save/restore registers?

The registers are saved and then restored. The problem is that you are
dealing with a memory location. If the context switch occurs before the
instruction to store the value occurs, then the other thread would be
working with an old value.

Generally I've used critical sections and never thought about the
volitile issue. I assumed (oh boy) that the register would be stored
before exiting the critical section. Generally when such function calls
are made the registers are stored, so I probably have been dodging that
bullet. On certain CPU's with many registers this could become much less
safe.

In the past I've only used it for memory that can be changed externally,
such as device drivers, memory mapped IO etc.

Larry Brasfield

unread,
Apr 11, 2001, 8:16:31 PM4/11/01
to
"TiTi" <ti...@skynet.be> wrote regarding
Re: infos, articles, faqs about 'volatile':
....

> Well, the standard doesn't mention much about the
> semantics of the keyword volatile. It does explain
> how to handle volatile qualified variables and
> stuff (and cv-qualified variables in general).
> The 'volatile' keyword is a sort of a hint to the
> compiler to not optimize any variables that are
> volatile qualified. The rest of the semantics of
> the volatile keyword is implementation dependent.

I have never considered the C++ standard's treatment
of what 'volatile' means to be anything but clear,
concise, and wholly sufficient to convey its utility.

Section 1.9 Program execution, reads (in part):

6 The observable behavior of the abstract machine
is its sequence of reads and writes to volatile
data and calls to library I/O functions

7 Accessing an object designated by a volatile
lvalue (3.10), modifying an object, calling a
library I/O function, or calling a function
that does any of those operations are all side
effects, which are changes in the state of the
execution environment. ...

Since this "observable behavior" is what the standard
controls (for a conforming implementation), there is
little room to think of 'volatile' as anything other
than a way of designating accesses of certain data
objects as being subject to an ordering constraint
dictated by the program logic visible in its source.

The 'volatile' keyword is certainly not any kind of
'hint' related to optimization. It is likely to act
as a constraint on optimization in environments where
multi-threaded execution might take place, rendering
volatile data observable by other threads, or where
memory mapped I/O is a possibility. As a practical
matter, that encompasses just about all environments.
The effect is that a correct optimizer must include
access ordering requirements arising from volatile
data among its inviolable optimization goals.

-Larry Brasfield
(address munged)

Dennis Yelle

unread,
Apr 11, 2001, 8:17:30 PM4/11/01
to

Yes.

The race is here:

> > startThread(func, &a);
> > a = false;

If func runs to completion (or just far enough
to set 'a' true) before a is set to false, then
the race is lost. To correct it,
just reverse those 2 lines.

MT is very tricky to get exactly right.

Dennis Yelle
--
I am a computer programmer and I am looking for a job.
There is a link to my resume here:
http://table.jps.net/~vert/

Dima Volodin

unread,
Apr 12, 2001, 4:14:57 AM4/12/01
to
Larry Brasfield wrote:
>
> The 'volatile' keyword is certainly not any kind of
> 'hint' related to optimization. It is likely to act
> as a constraint on optimization in environments where
> multi-threaded execution might take place, rendering
> volatile data observable by other threads, or where
> memory mapped I/O is a possibility. As a practical
> matter, that encompasses just about all environments.
> The effect is that a correct optimizer must include
> access ordering requirements arising from volatile
> data among its inviolable optimization goals.

All volatile is saying is that the program should request and present
volatile data from/to the environment in a certain order, and it doesn't
say anything about what the environment should do with this data. In
particular, it doesn't say that the environment should present these
data to other threads in any order or render these data visible to other
threads or processes or I/O devices or whatever else at all.

> -Larry Brasfield

Dima

Kevin Cline

unread,
Apr 12, 2001, 7:17:59 PM4/12/01
to
Carlos Moreno <mor...@mochima.com> writes:

> Not necessarily. Modifying a boolean flag is an atomic operation;

On most multi-processor hardware, it isn't.
--
Kevin Cline

Nicola Musatti

unread,
Apr 13, 2001, 11:11:33 AM4/13/01
to

Dima Volodin wrote:
[...]


> I can't believe you've missed the prolonged thread about the relevance
> of 'volatile' to multithreading. If you have, you'd better have a look
> at deja.com (or whatever its name is). To sum it up - the only things
> you can use for data consistency in MT are the primitives that the MT
> environment explicitly provides for this purpose, and 'volatile' as
> defined by the language is not one of these primitives. In POSIX, the
> synchronization primitives are mutexes, and using 'volatile' would gain
> you nothing but performance degradation, and accessing shared data
> without using mutexes produces undefined results whether these data are
> declared volatile or not.

Except that if I'm not mistaken, Andrei Alexandrescu suggested a
technique which took advantage of "volatile" to obtain support from the
compiler in handling multithreading related issues. The basic idea is to
declare as volatile class instances that must be accessed from multiple
threads, to provide a volatile qualified overload of the requested
member function in which a lock or whatever is acquired before calling
the non volatile version of the same member function by casting
volatileness away.

That is volatile is only used to support overloading and not because it
has thread protection capabilities per se (which it hasn't).

Best regards,
Nicola Musatti

Dima Volodin

unread,
Apr 14, 2001, 11:39:18 AM4/14/01
to
Nicola Musatti wrote:

> Except that if I'm not mistaken, Andrei Alexandrescu suggested a
> technique which took advantage of "volatile" to obtain support from the
> compiler in handling multithreading related issues. The basic idea is to
> declare as volatile class instances that must be accessed from multiple
> threads, to provide a volatile qualified overload of the requested
> member function in which a lock or whatever is acquired before calling
> the non volatile version of the same member function by casting
> volatileness away.
>
> That is volatile is only used to support overloading and not because it
> has thread protection capabilities per se (which it hasn't).

This approach received an extensive criticism, and as far as I remember,
Andrei at the end agreed that 1) it had been a really bad idea to use
'volatile' as an overloading mechanism and 2) excessive use of 'volatile'
usually badly robs compilers of otherwise good optimization possibilities.
Again, see the newsgroup archives for all the gory details.

> Nicola Musatti

Dima

Tom Plunket

unread,
Apr 14, 2001, 2:26:55 PM4/14/01
to
Carlos Moreno wrote:

> external_signal_received = false;
>
> a = b + c;
> if (b > 0) c = 3;
> //... etc.
>
> if (! external_signal_received)
> {
>

> This is one (silly) example of a variable that would have to
> be volatile-qualified for this to work as you really wanted

> to...

Silly as it may be, I will always remember that it was this sort
of thing that first got me to use volatile. ;)


-tom!

--
Tom Plunket to...@fancy.org
PlayStation2/3D Studio geek
The best tagline is the one that you steal.

Andrei Alexandrescu

unread,
Apr 15, 2001, 4:35:25 AM4/15/01
to
"Torsten Mohrin" <torsten...@gmx.net> wrote in message
news:3ad6c349...@news.randori.com...

> Thanks for your explanation. However, I know the meaning of 'volatile'
> with basic C types. I'm just not aware of all the consequences of
> volatile objects and volatile member functions. I'm programming in C++
> for years and fully understand 'const', but never dealed with
> 'volatile' before.

For an overview on how volatile acts on user-defined types, and for an
introduction to volatile correctness, see:

http://www.cuj.com/experts/1902/alexandr.htm

Also see the follow-up:

http://www.cuj.com/experts/1904/alexandr.htm

which also refers to a /very/ long thread on this newsgroup entitled
"volatile, was: memory visibility between threads." I got a lot of info from
following that thread.


Andrei

Andrei Alexandrescu

unread,
Apr 16, 2001, 7:06:21 AM4/16/01
to
"Dima Volodin" <d...@dvv.org> wrote in message
news:3AD75086...@dvv.org...

> This approach received an extensive criticism, and as far as I remember,
> Andrei at the end agreed that 1) it had been a really bad idea to use
> 'volatile' as an overloading mechanism

I still support the use of 'volatile' as described in the article in any
environment except environments that (1) don't provide mutexes and/or (2)
put volatile variables in a special memory area so you cannot cast volatile
away.

> and 2) excessive use of 'volatile'
> usually badly robs compilers of otherwise good optimization possibilities.

This is a moot point. Volatile-correct code *never* uses a volatile variable
directly. It *always* casts it away before using it, and *always* does this
in conjunction with locking an afferent synchronization object.

> Again, see the newsgroup archives for all the gory details.

Fair enough :o).


Andrei

Dima Volodin

unread,
Apr 16, 2001, 11:28:32 AM4/16/01
to
Andrei Alexandrescu wrote:
>
> "Dima Volodin" <d...@dvv.org> wrote in message
> news:3AD75086...@dvv.org...
> > This approach received an extensive criticism, and as far as I remember,
> > Andrei at the end agreed that 1) it had been a really bad idea to use
> > 'volatile' as an overloading mechanism
>
> I still support the use of 'volatile' as described in the article in any
> environment except environments that (1) don't provide mutexes and/or (2)
> put volatile variables in a special memory area so you cannot cast volatile
> away.

Which again comes down to cheating the compiler and relying on something
that neither the language nor the environment guarantee. (Well, some
environments might guarantee that, but I've yet to see such an
environment.) As far as I'm concerned, tricks like this belong to the
same category as using asm(). Besides, in the real life, the interaction
between shared objects is usually more complex than the concept of
"synchronized" objects allows for. It works when all you need is an
atomic update of an object's state, but you'll have to be really
inventive to fit things like hierarchical or chained locking, or
nontrivial use of condition variables into the scheme. In other words,
the approach works when you need to do some quick and dirty retrofit of
some single threaded algorithms into an MT environment, but not when you
do a proper design of an MT application.

> > Again, see the newsgroup archives for all the gory details.
>
> Fair enough :o).
>
> Andrei

Dima

Michael Champigny

unread,
Apr 16, 2001, 10:20:13 PM4/16/01
to
Andrei said:

> I still support the use of 'volatile' as described in the article in any
> environment except environments that (1) don't provide mutexes and/or (2)
> put volatile variables in a special memory area so you cannot cast
> volatile away.

What you are prescribing is a hack. Volatile is not a generic, portable
means of serializing access. It *might* work in a particular environment,
under particular conditions, but cannot be relied upon any more than you
can depend on function pointer casts working portably. Where does it
say volatile implements a memory barrier? How are nested locks handled?
These issues require OS support.

It might be better to recommend that clients write code using POSIX
threads, or at least write jackets around their OS-dependent semaphores
or mutexes. Volatile only clouds and confuses the issue. Say it with me:
Volatile has *NOTHING* to do with MT and does *NOT* allow serialized
access to variables. Period.

-Michael

Andrei Alexandrescu

unread,
Apr 17, 2001, 4:23:33 AM4/17/01
to
"Dima Volodin" <d...@dvv.org> wrote in message
news:3ADB085B...@dvv.org...

> Which again comes down to cheating the compiler and relying on something
> that neither the language nor the environment guarantee. (Well, some
> environments might guarantee that, but I've yet to see such an
> environment.)

If you are keen about reopening the discussion, I'd be glad to. I don't
understand, however, to which part of my post this post was answering. For
the record, I fully agree anyone can have about any opinion about any
technique whatsoever. I even have a colleague who believes real programmers
don't use strings. Much more so, of course, when it comes about
controversial techniques that use 'volatile' (which is nonportable almost by
definition) in yet another way. My post didn't try to shove again my view of
volatile correctness down people's throat; I was just mildly annoyed that
words are put in my mouth and so I restated my point.

> As far as I'm concerned, tricks like this belong to the
> same category as using asm().

I fully understand yet I don't take a second to agree, see above.

> Besides, in the real life, the interaction
> between shared objects is usually more complex than the concept of
> "synchronized" objects allows for.

I'm afraid there is a misunderstanding. Synchronized objects are one aspect
of volatile correctness. Volatile correctness applies to multiple-object
locking, though indeed some extra keywords would help here (to specify which
locks apply to which operations). I believe it's a progress over equivalent
hand-coded routines because the compiler reminds you whenever you forget to
use an object without locking a corresponding lock.

> In other words,
> the approach works when you need to do some quick and dirty retrofit of
> some single threaded algorithms into an MT environment, but not when you
> do a proper design of an MT application.

This conjecture is in direct disagreement with my practical experience. I
have designed one nontrivial application from scratch relying on volatile
correctness. A colleague of mine designed a larger application relying on
the same.

I don't claim to be a multithreading expert, but I can tell a thread from a
1988 Chevrolet Celebrity. From what I see around me and read in books and
magazines, many people's threading needs are much like mine. For those
people, volatile correctness can be of great help. For the minority with
more subtle threading issues and needs going on, volatile correctness might
be useful or not, but that doesn't diminish its helpfulness to the majority.


Andrei

James Dennett

unread,
Apr 17, 2001, 9:25:39 AM4/17/01
to
Michael Champigny wrote:
>
> Andrei said:
>
> > I still support the use of 'volatile' as described in the article in any
> > environment except environments that (1) don't provide mutexes and/or (2)
> > put volatile variables in a special memory area so you cannot cast
> > volatile away.
>
> What you are prescribing is a hack. Volatile is not a generic, portable
> means of serializing access. It *might* work in a particular environment,
> under particular conditions, but cannot be relied upon any more than you
> can depend on function pointer casts working portably. Where does it
> say volatile implements a memory barrier? How are nested locks handled?
> These issues require OS support.

You may have missed the point of Andrei's article and
the thread which followed it on this newsgroup.

>
> It might be better to recommend that clients write code using POSIX
> threads, or at least write jackets around their OS-dependent semaphores
> or mutexes. Volatile only clouds and confuses the issue. Say it with me:
> Volatile has *NOTHING* to do with MT and does *NOT* allow serialized
> access to variables. Period.

You clearly don't have the same understanding of Andrei's
technique that I do. He proposes using the typing properties
of volatile to allow compile-time checking that some mechanism
(such as pthreads or whatever) is used consistently. It is
only the compile-time checking of volatile that is used.
It would be better if we could add a new cv-like qualifier,
to avoid confusion from people who think that the technique
has anything to do with the runtime behaviour of volatile
in C++.

-- James Dennett

Andrei Alexandrescu

unread,
Apr 17, 2001, 9:32:05 AM4/17/01
to
"Michael Champigny" <michael....@compaq.com> wrote in message
news:9bfgpn$15cup$1...@nose.shr.dec.com...

> Andrei said:
>
> > I still support the use of 'volatile' as described in the article in any
> > environment except environments that (1) don't provide mutexes and/or
(2)
> > put volatile variables in a special memory area so you cannot cast
> > volatile away.
>
> What you are prescribing is a hack. Volatile is not a generic, portable
> means of serializing access. It *might* work in a particular environment,
> under particular conditions, but cannot be relied upon any more than you
> can depend on function pointer casts working portably. Where does it
> say volatile implements a memory barrier? How are nested locks handled?
> These issues require OS support.
>
> It might be better to recommend that clients write code using POSIX
> threads, or at least write jackets around their OS-dependent semaphores
> or mutexes. Volatile only clouds and confuses the issue. Say it with me:
> Volatile has *NOTHING* to do with MT and does *NOT* allow serialized
> access to variables. Period.

I love it when people comment on articles, and so confidently, without
having read one line of them. Semicolon.

Andrei

------------------
"It is better to keep your mouth closed and let people think you are a fool
than to open it and remove all doubt." -- Mark Twain

Gerhard Menzl

unread,
Apr 20, 2001, 3:43:32 PM4/20/01
to
Torsten Mohrin wrote:

> I understand the usage of volatile for memory mapped I/O register and
> stuff like that. But there are some examples in literature and
> discussions that explain the usage with interrupt/signal handler
> functions that modify a variable. What is the relevant difference
> between an interrupt handler and a second thread (on a single
> processor system)?

The relevant difference may differ between platforms. This is the nature
of the problem.

Gerhard Menzl

Gerhard Menzl

unread,
Apr 20, 2001, 4:57:57 PM4/20/01
to
"R. Sinoradzki" wrote:

> > I've seen from previous discussions that 'volatile' in C++ seems to
> > be a rather difficult and controversial thing. Do you know any
> > article or FAQs, etc. with a good summary of the usage and meaning
> > of 'volatile' in C++? I'm especially interested in the relevance of
> > 'volatile' regarding MT programming.
>
> from the standard clause 1.9
>
> 9 When the processing of the abstract machine is interrup-
> ted by receipt of a signal, the values of objects
> with type other than volatile sig_atomic_t are unspecified,
> and the value of any object not of volatile sig_atomic_t
> that is modified by the handler becomes undefined.

Did you notice that this clause, like the rest of the entire standard,
does not address multithreading at all?

> So I think this is the basic type to work with ...

There is no portable guarantee that volatile will buy you anything as
far as thread synchronization is concerned. It might, or it might not.
This is totally implementation-dependent.

Gerhard Menzl

Dima Volodin

unread,
Apr 20, 2001, 4:59:56 PM4/20/01
to
Andrei Alexandrescu wrote:
>
> "Dima Volodin" <d...@dvv.org> wrote in message
> news:3ADB085B...@dvv.org...
> > Which again comes down to cheating the compiler and relying on something
> > that neither the language nor the environment guarantee. (Well, some
> > environments might guarantee that, but I've yet to see such an
> > environment.)
>
> If you are keen about reopening the discussion, I'd be glad to. I don't
> understand, however, to which part of my post this post was answering.

This was an answer more to the sequence of your posts, or even to your
failure to recignize that using 'volatile' in the way you recommend is a
_bad_ thing. It was bad enough when you used it to control the
overloading, but it got absolutely awful when you started to cast
'volatile' away, which is in fact a head-on collision with [7.1.5.1/7],
which is very blunt on the subject:

If an attempt is made to refer to an object defined with a
volatile qualified type through the use of an lvalue with a
non-volatile-qualified type, the program behaviour is undefined.

And your recommendation all of a sudden gives a very particular
definition to this kind of reference. Note that there's no such
definition in the POSIX environment (the one with mutexes), so your
recommendation cannot be applied to programming in such an environment
with any definitive results.

> I'm afraid there is a misunderstanding. Synchronized objects are one aspect
> of volatile correctness. Volatile correctness applies to multiple-object
> locking, though indeed some extra keywords would help here (to specify which
> locks apply to which operations). I believe it's a progress over equivalent
> hand-coded routines because the compiler reminds you whenever you forget to
> use an object without locking a corresponding lock.

You lost me here. The way you recommend to use 'volatile' is in pretty
much direct contradiction with the definition of 'volatile' in the
language, what "volatile correctness" are you refering here to?

> > In other words,
> > the approach works when you need to do some quick and dirty retrofit of
> > some single threaded algorithms into an MT environment, but not when you
> > do a proper design of an MT application.
>
> This conjecture is in direct disagreement with my practical experience. I
> have designed one nontrivial application from scratch relying on volatile
> correctness. A colleague of mine designed a larger application relying on
> the same.

To rely on something, you've got to have it defined in the language
and/or the environment. In our case, it's not in the language (and,
AFAIK, it's never been there), did you have it defined in your
environment?

> I don't claim to be a multithreading expert, but I can tell a thread from a
> 1988 Chevrolet Celebrity. From what I see around me and read in books and
> magazines, many people's threading needs are much like mine. For those
> people, volatile correctness can be of great help. For the minority with
> more subtle threading issues and needs going on, volatile correctness might
> be useful or not, but that doesn't diminish its helpfulness to the majority.

The problem here is that the C++ keyword and notion of 'volatile' is
almost as irrelevant to multithreading as it is to 1988 Chevrolet
Celebrity. One thing though: I must admit that I'm not too familiar with
1988 Chevrolet Celebrity, so 'volatile' might be much more relevant to
it than I think it is.

> Andrei

Dima

Michael Champigny

unread,
Apr 20, 2001, 10:51:38 PM4/20/01
to
> You clearly don't have the same understanding of Andrei's
> technique that I do. He proposes using the typing properties
> of volatile to allow compile-time checking that some mechanism
> (such as pthreads or whatever) is used consistently. It is
> only the compile-time checking of volatile that is used.
> It would be better if we could add a new cv-like qualifier,
> to avoid confusion from people who think that the technique
> has anything to do with the runtime behaviour of volatile
> in C++.

That's funny, because I have no idea who Andrei is or what he wrote,
nor do I care. I was commenting on the note that started this thread.
Notably, he wanted to know the relevance of volatile to MT programming.
There is none.

-Michael

Michael Champigny

unread,
Apr 20, 2001, 10:51:56 PM4/20/01
to
> I love it when people comment on articles, and so confidently, without
> having read one line of them. Semicolon.

I love it when people assume you've read a particular article, and so
arrogantly. I have no idea what you are talking about. Read the original
post.

-Michael

Andrei Alexandrescu

unread,
Apr 21, 2001, 1:41:09 PM4/21/01
to
"Michael Champigny" <michael....@compaq.com> wrote in message
news:9bkqfe$1bj08$2...@nose.shr.dec.com...

> > I love it when people comment on articles, and so confidently, without
> > having read one line of them. Semicolon.
>
> I love it when people assume you've read a particular article, and so
> arrogantly. I have no idea what you are talking about. Read the original
> post.

I was answering to a post that in turn replies, and even quotes, a post of
mine. That post addresses to me directly and is a direct reply to my
affirmations that in turn refer to an article. So if the poster had no idea
what another poster is talking about, he better doesn't engage in a
conversation with him. Fair enough?

I reproduce that post below.


Andrei

******************************

Andrei said:

> I still support the use of 'volatile' as described in the article in any
> environment except environments that (1) don't provide mutexes and/or (2)
> put volatile variables in a special memory area so you cannot cast
> volatile away.

What you are prescribing is a hack. Volatile is not a generic, portable
means of serializing access. It *might* work in a particular environment,
under particular conditions, but cannot be relied upon any more than you
can depend on function pointer casts working portably. Where does it
say volatile implements a memory barrier? How are nested locks handled?
These issues require OS support.

It might be better to recommend that clients write code using POSIX
threads, or at least write jackets around their OS-dependent semaphores
or mutexes. Volatile only clouds and confuses the issue. Say it with me:
Volatile has *NOTHING* to do with MT and does *NOT* allow serialized
access to variables. Period.

-Michael

Andrei Alexandrescu

unread,
Apr 21, 2001, 11:11:54 PM4/21/01
to
"Dima Volodin" <d...@dvv.org> wrote in message
news:3ADC5693...@dvv.org...

> Andrei Alexandrescu wrote:
> >
> > "Dima Volodin" <d...@dvv.org> wrote in message
> > news:3ADB085B...@dvv.org...
> > > Which again comes down to cheating the compiler and relying on
something
> > > that neither the language nor the environment guarantee. (Well, some
> > > environments might guarantee that, but I've yet to see such an
> > > environment.)
> >
> > If you are keen about reopening the discussion, I'd be glad to. I don't
> > understand, however, to which part of my post this post was answering.
>
> This was an answer more to the sequence of your posts, or even to your
> failure to recignize that using 'volatile' in the way you recommend is a
> _bad_ thing.

My post was simply stating that the words you put in my mouth did not belong
to me. Ah, I'll drop this.

> It was bad enough when you used it to control the
> overloading, but it got absolutely awful when you started to cast
> 'volatile' away, which is in fact a head-on collision with [7.1.5.1/7],
> which is very blunt on the subject:

[snip]

You can apply volatile correctness without breaking 7.1.5.1/7, so the rest
of your conjecture is based on a wrong hypothesis.

What you have to do to be politically correct wrt 7.1.5.1/7 is to define
your shared data as non-volatile, then initialize a volatile reference to
it. Then you can cast volatile away with guaranteed results.


Andrei

Dima Volodin

unread,
Apr 22, 2001, 1:11:02 PM4/22/01
to
In message <9bqipc$ajm8j$1...@ID-14036.news.dfncis.de>, "Andrei
Alexandrescu" <andre...@hotmail.com> wrote:

>"Dima Volodin" <d...@dvv.org> wrote in message
>news:3ADC5693...@dvv.org...
>> Andrei Alexandrescu wrote:
>> >
>> > "Dima Volodin" <d...@dvv.org> wrote in message
>> > news:3ADB085B...@dvv.org...
>> > > Which again comes down to cheating the compiler and relying on
>something
>> > > that neither the language nor the environment guarantee. (Well, some
>> > > environments might guarantee that, but I've yet to see such an
>> > > environment.)
>> >
>> > If you are keen about reopening the discussion, I'd be glad to. I don't
>> > understand, however, to which part of my post this post was answering.
>>
>> This was an answer more to the sequence of your posts, or even to your
>> failure to recignize that using 'volatile' in the way you recommend is a
>> _bad_ thing.
>
>My post was simply stating that the words you put in my mouth did not belong
>to me. Ah, I'll drop this.

Hold on a sec. Exactly what were the words I put in your mouth that
didn't belong to you?

>> It was bad enough when you used it to control the
>> overloading, but it got absolutely awful when you started to cast
>> 'volatile' away, which is in fact a head-on collision with [7.1.5.1/7],
>> which is very blunt on the subject:
>[snip]
>
>You can apply volatile correctness without breaking 7.1.5.1/7, so the rest
>of your conjecture is based on a wrong hypothesis.

Define "volatile correctness" as something derivable from the language
definition, please.

>What you have to do to be politically correct wrt 7.1.5.1/7 is to define
>your shared data as non-volatile, then initialize a volatile reference to
>it. Then you can cast volatile away with guaranteed results.

When you define a "volatile reference", you define that the datum
referenced by this reference is a volatile datum, so again when you cast
'volatile' away from this reference, you mess with [7.1.5.1/7]. Besides,
I don't quite catch the concept of "political correctness" as applied to
a programming language - could you elaborate what it is, please? Based
on the definition of the language, of course?

>Andrei

Dima

James Dennett

unread,
Apr 22, 2001, 4:34:09 PM4/22/01
to
Michael Champigny wrote:
>
> > You clearly don't have the same understanding of Andrei's
> > technique that I do. He proposes using the typing properties
> > of volatile to allow compile-time checking that some mechanism
> > (such as pthreads or whatever) is used consistently. It is
> > only the compile-time checking of volatile that is used.
> > It would be better if we could add a new cv-like qualifier,
> > to avoid confusion from people who think that the technique
> > has anything to do with the runtime behaviour of volatile
> > in C++.
>
> That's funny, because I have no idea who Andrei is or what he wrote,
> nor do I care.

Odd, if you bear in mind that you were replying to Andrei's
message.

Andrei is a C++ user of considerable knowledge and with
a justifiably good reputation. His first book, "Modern
C++ Design," is one of the most interesting C++-based
books published recently, IMO.

> I was commenting on the note that started this thread.
> Notably, he wanted to know the relevance of volatile to MT programming.
> There is none.

I doubt that you'll drop your erroneous assertion, but for
one last time I will mention that Andrei's article pointed
out a way to use the compile-time properties of volatile
to assist in producing correct MT code. Before stating
that there is *no* relevance of volatile to MT programming,
you might wish to read the literature which demonstrates
that relevance certainly exists, even if controversy goes
along with it.

It is true to state that the Standard says nothing about
MT programming, but other things stated by the Standard
enable (compile-time) MT techniques. There is, however,
little (but not *no*) relevance of volatile to MT code
at run-time.

And now I bow out of this painful thread.

-- James Dennett

Tom Plunket

unread,
Apr 23, 2001, 10:02:07 AM4/23/01
to
Dima Volodin wrote:

> When you define a "volatile reference", you define that the datum
> referenced by this reference is a volatile datum, so again when you cast
> 'volatile' away from this reference, you mess with [7.1.5.1/7].

Is this somehow different than defining a "const reference" and
knowing with 100% certainty that it isn't *actually* const,
therefore knowing that it's safe to cast const away?

-tom!

--
Tom Plunket to...@fancy.org
PlayStation2/3D Studio geek

What do you mean, it doesn't work? It worked fine yesterday...

Anthony Williams

unread,
Apr 23, 2001, 12:40:04 PM4/23/01
to
"Dima Volodin" <d...@dvv.ru> wrote in message
news:3b195ea6....@news-server.cox.rr.com...

> In message <9bqipc$ajm8j$1...@ID-14036.news.dfncis.de>, "Andrei
> Alexandrescu" <andre...@hotmail.com> wrote:
>
> >"Dima Volodin" <d...@dvv.org> wrote in message
> >news:3ADC5693...@dvv.org...
> >> Andrei Alexandrescu wrote:
> >> It was bad enough when you used it to control the
> >> overloading, but it got absolutely awful when you started to cast
> >> 'volatile' away, which is in fact a head-on collision with [7.1.5.1/7],
> >> which is very blunt on the subject:
> >[snip]
> >
> >You can apply volatile correctness without breaking 7.1.5.1/7, so the
rest
> >of your conjecture is based on a wrong hypothesis.
>
> Define "volatile correctness" as something derivable from the language
> definition, please.

I will jump in here on Andrei's side, as I originally criticised his article
for breaking 7.1.5.1/7, and am quite happy with his solution.

The language lets you qualify the type of variables with "volatile", just as
you can qualify them with "const". If you try and bind a volatile object to
a non-volatile reference or pointer without a cast, then a compile-time
error occurs, just as if you try and bind a const object to a non-volatile
reference or pointer without a cast. In fact, const and volatile have
identical rules in that respect. For classes, you can also qualify member
functions with volatile, just as you can qualify them with const. If you
have a volatile object, or a volatile reference to an object, then you can
only use member functions qualified with volatile. Again, this is identical
to the rules for const. The major differences between const and volatile are
that you cannot modify const objects of built-in type, though you can modify
volatile ones, and you cannot bind a temporary to a reference that is
non-const, irrespective of whether or not it is volatile.

Since the rules for volatile are the same as for const,
"volatile-correctness" is akin to "const-correctness". Note that this is
merely using volatile as a type qualifier, and does not assume anything else
about the implications of volatile with respect to multi-threading, or
anything else.

> >What you have to do to be politically correct wrt 7.1.5.1/7 is to define
> >your shared data as non-volatile, then initialize a volatile reference to
> >it. Then you can cast volatile away with guaranteed results.
>
> When you define a "volatile reference", you define that the datum
> referenced by this reference is a volatile datum, so again when you cast
> 'volatile' away from this reference, you mess with [7.1.5.1/7]. Besides,
> I don't quite catch the concept of "political correctness" as applied to
> a programming language - could you elaborate what it is, please? Based
> on the definition of the language, of course?
>

volatile int i;
int j;

volatile int& rv1=i;
volatile int& rv2=j;
int& nvr1=const_cast<int&>(rv1);
int& nvr2=const_cast<int&>(rv2);

int & nvr3=j;

i is a volatile object, j is non-volatile. vr1 is a volatile reference to a
volatile object, vr2 is a volatile reference to a non-volatile object.

nvr1 is a non-volatile reference to the object referred to by vr1 (i), which
is a volatile object.
nvr2 is a non-volatile reference to the object referred to by vr2 (j), which
is a non-volatile object.

Thus any use of nvr1 is undefined by 7.1.5.1p7, but use of nvr2 is legal,
defined and works exactly like nvr3 - a non-volatile reference to a
non-volatile object (j).

This is Andrei's solution - declare a non-volatile object (j), and a
volatile reference to it (rv2). Then only refer to the object via the
volatile reference. Any code which expects a non-volatile reference will not
compile without a cast (thus highlighting that code), but such a cast is
legal, and can therefore be done where we know it is OK to do so.

On the majority of platforms, volatile qualifiers do not actually affect the
storage of the object in any way, since the object can still be modified,
just the optimisations that the compiler assumes are OK or not. Therefore on
these platforms, it is generally safe to cast away volatile (as with nvr1),
even though it is strictly undefined. However, on some platforms this is not
OK (hence the behaviour is undefined). Thus, although we have a solution
which works on the majority of platforms, in order to work on ALL platforms
we have to be "poltically correct" and stick to the letter of the standard,
rather than relying on implementation-specific details.

Anthony
--
Anthony Williams
Software Engineer, Nortel Networks Optoelectronics
The opinions expressed in this message are not necessarily those of my
employer

Marwijn Christiaans

unread,
Apr 23, 2001, 2:16:32 PM4/23/01
to

"Dima Volodin" <d...@dvv.ru> wrote in message
news:3b195ea6....@news-server.cox.rr.com...

I don't really understand the last part here. Does making a reference
volatile
or constant make the datum pointed to const/volatile ? I Always believed
that
the following was legal:

int a;
const int& b = a;
int&c = const_cast<int&> b;

as well as:

int a
volatile int &b =a;
int&c = const_cast<int&> b;

And that the only thing that is not allowed:

const a;
int& b=const_cast<int& a> // oops a was in ROM.

Could you elaborate a bit please ?

> >Andrei
>
> Dima

Thanx,

Marwijn.

Gerhard Menzl

unread,
Apr 23, 2001, 3:31:54 PM4/23/01
to
Dima Volodin wrote:

> >What you have to do to be politically correct wrt 7.1.5.1/7 is to
> >define your shared data as non-volatile, then initialize a volatile
> >reference to it. Then you can cast volatile away with guaranteed
> >results.
>
> When you define a "volatile reference", you define that the datum
> referenced by this reference is a volatile datum, so again when you
> cast 'volatile' away from this reference, you mess with [7.1.5.1/7].

Are you seriously claiming that

int i;
int volatile& ri = i;

makes i volatile? If so, we must be talking about different languages
here.

Gerhard Menzl

James Kanze

unread,
Apr 23, 2001, 4:13:42 PM4/23/01
to
Maciej Sobczak wrote:

> "Chris Uzdavinis" <ch...@atdesk.com> wrote in message
> news:j6u23wd...@explicit.atdesk.com...
> > Carlos Moreno <mor...@mochima.com> writes:

> > > In MT programming, asynchronous execution of things has to be
> > > expected, and if you're sharing data between two threads, I
> > > think you better tell the compiler that it is volatile (the
> > > examples that you give, register or port, are perfectly valid,
> > > but are not the only situations where an object can
> > > "unexpectedly" change its value).

> > Wouldn't it be considered an OS bug if the context switch didn't
> > properly save/restore registers?

> > (I'm a bit naive when it comes to effective use of "volatile" but
> > I don't see why it should be necessary to use for additional
> > thread safety.)

> > I hope someone will correct me if I'm wrong.

> Here is my 0.03 Euro:
> As it comes to OS, some of them can use the CPU itself to swap
> registers, so it wouldn't be an OS bug, anyway.

In the end, all OS's use the CPU to swap registers. There isn't
anything else which can do it. I presume you mean that the CPU may
contain multiple register banks, and can swap which one is currently
active. But whether it does this, or copies the registers to memory
and restores them from somewhere else in memory changes nothing.

> What is the problem in volatile/MT subject is that volatile tell the
> compiler not to put things into a register as an optimization.

More or less. The problem is that this is *all* it does.

> Consider this:

> int sum = 0;
> int count = 60;
> while (count--)
> {
> sleep(1); // sleep one second
> sum += global_variable;
> }
> // now 'sum' keeps the sum of all the 'probes' of the global_variable, taken
> every one second

> This code will add up all the values that the global_variable has,
> every one second, for one minute.

> And let's suppose that global_variable is subject to be changed by
> another thread.

Then the code is no longer thread safe. If this is the case, *all*
accesses to the variable must, in the general case, be protected by a
mutex lock. Depending on the processor, it may be possible to avoid
the lock by using some processor specific access barriers; this will
typically require some very processor specific assembler, and is not
for the faint of heart.

Declaring any (or all) of the variables volatile will NOT make this
code thread safe. Using the lock (or the access barriers) will,
without the volatile declaration, provided the compiler is made aware
that the lock or access barriers are being used. (Generally, if you
use the lock, there should be no problem. The lock is an external
function; either the compiler doesn't know its semantics, and must
assume that it might modify any or all of the variables in question,
or it knows the semantics of the function, and will take the
appropriate steps. If you're playing around with inline assembler,
however, you'll have to read the compiler documentation *very*
carefully in order to figure out how to inhibit the optimizations.)

> We would like the code above to sum up the values of this variable,
> by *inspecting* its value every second. The problem is, that the
> compiler can make some optimization so that it will copy the value
> of the global_variable into one of the CPU registers, 'sum' to
> another and later, make the addition only using the registers. This
> example is quite stupid, because in the loop we have a function
> call, which means that such an optimization doesn't make any sense
> (unless we have a CPU with function frames kept in the stack of
> registers - I forgot the name), but the idea remains.

The problem is that declaring global_variable volatile doesn't solve
the problem. The compiler will, of course, re-read it each time
through the loop, but there is still no guarantee that the read is
atomic, and that the code won't see part of the variable before the
update, and part after.

> Such an optimization would just multiplicate the value of the
> global_variable as it was at the beginning of the loop. So, we want
> to tell the compiler explicitely: "hey, this variable can be changed
> by other means that the normal flow of execution, so *always* refer
> to the original value, not to any of its copies". And that's why we
> declare it like here:

> volatile int global_variable;

For this to work, you must also guarantee that the accesses are
atomic. Not just here, of course, but also the writes. And in a
multiprocessor environment, even this may not be sufficient; volatile
will ensure that the processor reloads the register, but it won't
purge the cache, and thus might not see writes from other processors.

Volatile was designed with one thing in mind: memory mapped IO. It
was extended slightly to provide defined behavior for certain values
after a longjmp, and implementations are required to provide a type
sigatomic_t, of which a volatile instance can be written (but not
read/modified/written) in a signal handler. And it is part of the
type system.

That's all. Nothing about MT in there.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 4:19:46 PM4/23/01
to
Carlos Moreno wrote:

> Basically, volatile means that the value of some object could
> unexpectedly change for no apparent reason -- an example of this
> would be a global variable that is accessed by other threads or by
> interrupt routines (or event handlers).

The classical example, for which volatile was originally invented, is
memory mapped IO, e.g.:

char
getChar()
{
static unsigned char const charAvail = 0x01 ;
volatile unsigned char* pStatus = (unsigned char*)0x1234 ;
volatile char* pData = (char*)0x1230 ;

while ( (*pStatus & charAvail) == 0 ) {
}
return *pData ;
}

Without the volatile, any good compiler will simply read pStatus once,
and test a copy in a register on each pass through the loop.

The fact that the value can change behind the compiler's back sounds
like volatile would also be relevant for threading. In fact, per se,
it isn't; volatile doesn't guarantee atomicity, for example. (In the
above case, it is the data types themselves which guarantee atomicity.
This is, of course, implementation defined, but since all memory
mapped IO is implementation defined, no extra dependancies are
introduced.) In general, thread safety requires more than volatile
imposes; it requires various implementation specific write and read
barriers. Normally, these will be contained in the calls to lock and
unlock the mutex used to protect the critical area, so volatile
becomes irrelevant.

Andrei Alexandrescu did publish an article about using volatile to
ensure thread safety. In this case, however, he did NOT use any of
the normal semantics of volatile; he simply exploited the fact that
volatile is part of the type system, and that the compiler will
enforce volatile safety in much the same way it enforces const
safety. The idea is interesting, and I'd like to see it pursued
further, but it is orthogonal with the actual semantics of volatile,
according to the intent of the C/C++ standards.

James Kanze

unread,
Apr 23, 2001, 4:20:05 PM4/23/01
to
Andrei Alexandrescu wrote:

> "Torsten Mohrin" <torsten...@gmx.net> wrote in message
> news:3ad6c349...@news.randori.com...
> > Thanks for your explanation. However, I know the meaning of
> > 'volatile' with basic C types. I'm just not aware of all the
> > consequences of volatile objects and volatile member
> > functions. I'm programming in C++ for years and fully understand
> > 'const', but never dealed with 'volatile' before.

> For an overview on how volatile acts on user-defined types, and for
> an introduction to volatile correctness, see:

> http://www.cuj.com/experts/1902/alexandr.htm

Careful, Andrei. That is NOT an explination of the language imposed
semantics of volatile on user-defined types. It is a very clever
trick to get some compile-time checking which wouldn't otherwise be
possible by exploiting the the fact that volatile is part of the type
system, but that its actual semantics aren't very useful for most user
defined types. You (ab)use the type system, but you don't use any of
the actual semantics of volatile.

> Also see the follow-up:

> http://www.cuj.com/experts/1904/alexandr.htm

> which also refers to a /very/ long thread on this newsgroup entitled
> "volatile, was: memory visibility between threads." I got a lot of
> info from following that thread.

Which really only concerned the crux of your article: threading.

Except for special cases like yours, where only the type checking on
volatile is exploited, volatile is pretty much irrelevant with regards
to threading. Most of the actual uses I've seen have involved memory
mapped IO on embedded processors. In such cases, volatile is really
only relevant on built-in types, and in even then, only on types which
have atomic access on the machine in question.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 4:20:24 PM4/23/01
to
Carlos Moreno wrote:

> Michael Champigny wrote:

> > Volatile has *no* relavance to MT programming. Volatile tells the
> > compiler not to optimize away a variable which could have it's
> > value changed outside the control of the program (ie. a hardware
> > register or port).

> > I'm not sure where this connection between MT and volatile has
> > come from lately. I hope that helps!

> Huh?? Maybe my knowledge in MT is outdated... But I think the
> connection can't be more obvious! (see the example in my other
> post).

> In MT programming, asynchronous execution of things has to be
> expected, and if you're sharing data between two threads, I think
> you better tell the compiler that it is volatile (the examples that
> you give, register or port, are perfectly valid, but are not the
> only situations where an object can "unexpectedly" change its
> value).

Not at all. Volatile doesn't guarantee enough, and it imposes too
many restraints, to be systematically used for multiple threading.

Standard C++ doesn't define anything which is relevant to MT; it
doesn't even acknowledge that MT exists. The most widespread (and
only standardized?) MT specification, pthreads, defines a small number
of primitives which should be used, along with a certain number of
restrictions for the compiler/library. I presume that other MT
specificatons (Windows threads, etc.) do likewise.

In order to write a MT program, you must go beyond C++, and use these
functions. They will automatically provide the required protection,
provided they are used correctly, without the slightest need for
volatile.

Andrei Alexandrescu proposed a solution based on volatile to allow the
compiler to detect certain misuses of these primitives, which would
violate MT safety. His use of volatile, however, does not depend on
the semantics of volatile, but only on the fact that it is an
attribute whose use will be checked for consistency by the type
system.

> I may be missing something? If so, could you (or someone else)
> please show me what I'm missing?

Well, you seem to have missed one of the longest threads I've ever
seen, not too long ago:-).

> How would you handle the type of situation that I showed in my other
> post? Or is it fundamentally wrong to do so? (in that case, what
> would be the recommended approach to achieve an equivalent result?)

In general, you need to use mutex locks. In this particular case, if
you can be sure that the variable has atomic access (which bool
DOESN'T on certain Windows implementations, but char almost always
does), then you can probably get away with just read and write
barriers around the accesses. This will almost certainly require a
bit of assembler, however. And the case is very untypical; generally,
you don't want to just if, you want to wait until the other operation
has finished.

James Kanze

unread,
Apr 23, 2001, 8:53:19 PM4/23/01
to
Carlos Moreno wrote:

> Robert O'Dowd wrote:

> > I can see why you'd draw a link between volatile and
> > multi-threaded code, but tht link is a bit spurious for a few
> > reasons.

> > 1) The C++ standard is silent on multi-threading, so anything
> > with multi-threading exhibits undefined behaviour.
> > Any link to the "volatile" keyword is up to interpretation
> > by compiler and library vendors.

> Agreed. But still, the C++ standard doesn't say anything about
> variables mapped to a hardware port or anything... Yet the volatile
> keyword is there to "help" in that type of situation...

> The important thing is that volatile keeps the compiler from
> optimizing any access, as you're telling the compiler that something
> "external" to the code it has in front could unexpectedly change its
> value...

It helps for certain things. A compiler *could* extend its meaning to
include whatever is necessary to make MT code work. I don't know of
any which do, however.

> > 2) Even if we ignore the fact that we're outside the C++ standard....
> > in multi-threaded code, the result of any access to a value,
> > object or block of memory while another thread is modifying it
> > gives indeterminate results or behaviour.

> Not necessarily. Modifying a boolean flag is an atomic operation;

Could you please show me where you got that information. Modifying a
boolean flag may be an atomic operation, under certain conditions. A
simple write to a variable of type bool *IS* an atomic operation on my
compiler.

> You may need to check periodically if a certain condition has
> happened -- in a real-time (maybe embedded) system, where such
> condition will typically be associated to external hardware events,
> the system can not be sensible to the fact that the event was flag
> half a nanosecond before or after the value is read by the other
> thread... Worst case, during the next "tick", the condition will be
> detected...

> In any case, that could be typical in embedded systems design, where
> you typically have a "dual-thread" (as opposed to MT) due to the
> interrup-driven approach that is often used.

OK. Now we are in a specific context. We have a very specific
processor, which we know something about. It offers some additional
guarantees to the standard. Typically, it has no cache memory, no
multi-processor, etc. It is a small (and simple) embedded processor.

In this case, volatile probably is a solution. But this is far from
what most people think of when they think of threads. I've worked on
such processors, so I know what you are talking about. But I imagine
that when you say threads, most people imagine pthreads or Windows
threads. On typical PC's or workstations (and a typical workstation
is likely multiprocessor these days).

There are specific cases where volatile is relevant. Except for
longjmp, and possibly in signal handlers, all relevance is
implementation defined, and typically machine specific. (Is ++i safe
if i is volatile int? On some machines, it is, on others, no.)

In the general case, however, volatile is irrelevant to threading.

> The thing is, if you don't use volatile in there, the compiler might
> indeed break your code -- it is free to assume that it doesn't need
> to check the value of the boolean flag because it predicts its value
> -- when you tell it that something external to that piece of code
> could modify it, then it [the compiler] will know that it better
> checks the value, and that it would be wrong to optimize the
> access...

Agreed, to a point. Let's agree that if you don't do anything to
inhibit it, this sort of optimization is valid.

For large scall applications, on modern PC's, work stations or
mainframes, the cost of inhibiting such optimization just because the
variable might be shared between more than one thread is prohibitive.
And simply inhibiting the optimization doesn't actually buy us
anything anyway, because of all the other things going on behind the
compiler's back (cached memory, non-atomic accesses, etc.).

> > That's why
> > things like synchronisation primitives (mutex's, critical
> > sections, etc) exist in multithreading libraries: allow a
> > programmer to serialise access and prevent that sort of thing
> > happening. The volatile keyword does not magically give a
> > means of avoiding using those primitives.

> No! And I wasn't suggesting otherwise... But you're referring to
> more than just sharing data... You're referring to either sharing
> data that requires complex operations to update (and that can't be
> interrupted in the middle of a "transaction"), or to properly
> synchronize threads (which boils down to the above). Sure you need
> extra tools/tricks to do that.

But that is what you almost always have to do on a modern processor,
PC and up. Can you show me one application which uses pthreads or
their Windows equivalent that can get by with just boolean flags to
communicate between threads?

And of course, volatile, as implemented in the compilers for these
machines, doesn't ensure cache coherence, so you still have problems
with multiprocessor systems, even if you only need bool. You might
argue that this is a violation of the spirit of volatile, but its the
way it is. The implementations provide other means of
synchronization. The other means are normally necessary anyway. So
it does seem a little odd to require that volatile overlap these other
means.

> > OTOH, use of the volatile keyword can't hurt in this case. But,
> > IMHO, in multi-threaded code the hint it gives to the compiler is
> > redundant.

> I guess the bottom line is that volatile can help in certain
> situations that arise in MT programming, but not always. MT tools
> can help in situations where volatile would do, as well as in
> situations where volatile would not be right.

> Maybe, as an extra conclusion I could add that in general, when
> working in MT, if you do something that relies on the volatile
> keyword, then it is probably a sign that your design is not quite
> good?

Again, it depends on what you expect from the keyword. Andrei
Alexandrescu developped a way of obtaining some compile time checking
of MT safety using volatile. All he relied on is that the compiler
check volatile correctness. Which it is required to do. So what he
did is valid (although without special comments, it will certainly
mislead someone used to the "standard" meaning of volatile:-).

James Kanze

unread,
Apr 23, 2001, 8:55:19 PM4/23/01
to
Dima Volodin wrote:

> Nicola Musatti wrote:

> > Except that if I'm not mistaken, Andrei Alexandrescu suggested a
> > technique which took advantage of "volatile" to obtain support
> > from the compiler in handling multithreading related issues. The
> > basic idea is to declare as volatile class instances that must be
> > accessed from multiple threads, to provide a volatile qualified
> > overload of the requested member function in which a lock or
> > whatever is acquired before calling the non volatile version of
> > the same member function by casting volatileness away.

> > That is volatile is only used to support overloading and not
> > because it has thread protection capabilities per se (which it
> > hasn't).

> This approach received an extensive criticism, and as far as I
> remember, Andrei at the end agreed that 1) it had been a really bad

> idea to use 'volatile' as an overloading mechanism and 2) excessive


> use of 'volatile' usually badly robs compilers of otherwise good

> optimization possibilities. Again, see the newsgroup archives for
> all the gory details.

I don't think that the consensus went that far. My take is:

1. It is certainly an abuse of the type system, and the keyword
volatile is not used for its semantics, but only as a sort of flag
recognized by the type system. As such, it is likely to confuse
people familiar with multithreading and/or volatile, unless the
documentation and comments contain big warnings about this. (I
know that my first reaction was also that he didn't understand
anything about multithreading or volatile. In the end, I don't
know how much he understands either, because they are both really
only tangential to what he is doing: tricking the type system to
control the coherence of certain types of accesses.)

2. It does offer some compile time checking. Maybe not as much as
Andrei initially thought, but thread safety is something where
every little bit of help is important. I've not examined the
actual implementation in enough detail to say whether it is, in
its presented form, really usable and useful or not. But it
certainly isn't a bad idea to try and get some support from the
compiler, even if it does mean stretching the meaning of a few
keywords. The idea is worth pursuing. (IMHO, of course.)

3. Consdering 2: it is important that all of the essential
functionality within the volatile functions occur through
non-volatile references to the object, precisely because we
neither need nor want the actual semantics of volatile. If I
understood the final consensus correctly, the volatile function
would normally just acquire the mutex (using RAII), then cast away
volatile on the this pointer to call a non-volatile function which
contained the actual code.

Finally, of course, it must be stressed that whatever his code might
achieve, it can at best only control that a proper design has been
adhered too. That proper design, which takes MT issues into account,
still has to be done before anything else.

James Kanze

unread,
Apr 23, 2001, 8:56:07 PM4/23/01
to
Dima Volodin wrote:

> Andrei Alexandrescu wrote:

> > "Dima Volodin" <d...@dvv.org> wrote in message
> > news:3AD75086...@dvv.org...
> > > This approach received an extensive criticism, and as far as I
> > > remember, Andrei at the end agreed that 1) it had been a really
> > > bad idea to use 'volatile' as an overloading mechanism

> > I still support the use of 'volatile' as described in the article
> > in any environment except environments that (1) don't provide
> > mutexes and/or (2) put volatile variables in a special memory area
> > so you cannot cast volatile away.

> Which again comes down to cheating the compiler and relying on
> something that neither the language nor the environment guarantee.

Well, the principal point that it relies on is that the compiler
enforces volatile correctness, which is guaranteed by the standard.
As to what he "requires": if you don't have some sort of mutex, you're
not going to be doing multithreading (in the usual sense, at least),
so the requirement is irrelevant. And I've yet to see an
implementation which actually did put volatile variables in special
memory. (I don't actually think that this is even necessary for
Andrei's code.)

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 8:56:41 PM4/23/01
to
Dima Volodin wrote:

> >What you have to do to be politically correct wrt 7.1.5.1/7 is to
> >define your shared data as non-volatile, then initialize a volatile
> >reference to it. Then you can cast volatile away with guaranteed
> >results.

> When you define a "volatile reference", you define that the datum
> referenced by this reference is a volatile datum, so again when you
> cast 'volatile' away from this reference, you mess with [7.1.5.1/7].

No. The undefined behavior only comes into play if the actual object
is volatile. This is the same rule for const: if the actual object is
not const/volatile, you can still have a const/volatile pointer or
reference to it, and you can in this case legally cast const/volatile
away with defined behavior.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 8:57:52 PM4/23/01
to
Michael Champigny wrote:

> Andrei said:

> > I still support the use of 'volatile' as described in the article
> > in any environment except environments that (1) don't provide
> > mutexes and/or (2) put volatile variables in a special memory area
> > so you cannot cast volatile away.

> What you are prescribing is a hack. Volatile is not a generic,
> portable means of serializing access.

And he's not using it as such. It is a hack, in that it blatantly
abuses the type system. But it relies on behavior fully specified by
the standard: a non-volatile function cannot be called through a
volatile reference or pointer, and to attempt to do so is an error
requiring a compiler diagnostic.

[...]


> It might be better to recommend that clients write code using POSIX
> threads, or at least write jackets around their OS-dependent
> semaphores or mutexes. Volatile only clouds and confuses the
> issue. Say it with me: Volatile has *NOTHING* to do with MT and does
> *NOT* allow serialized access to variables. Period.

And therein lies the problem. The issue is clouded by the use of
volatile, because Andrei didn't make it fully clear enough up front
that his technique is only based on the fact that volatile is a type
attribute enforced by the C++ type system, and that it doesn't rely on
any of the normal characteristics of volatile variables. (I think
that there was even one post in the thread which suggested extending
the language to allow the programmer to define arbitrary
cv-qualifiers. Because all Andrei is doing is exploiting the typing
involved with cv-qualifiers. He uses volatile because it is almost
unthinkable that a class doesn't need const with its usual meaning,
but almost no class will need volatile in this way.)

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 8:59:03 PM4/23/01
to
James Dennett wrote:

[...]


> > I was commenting on the note that started this thread. Notably,
> > he wanted to know the relevance of volatile to MT programming.
> > There is none.

> I doubt that you'll drop your erroneous assertion, but for one last
> time I will mention that Andrei's article pointed out a way to use
> the compile-time properties of volatile to assist in producing
> correct MT code. Before stating that there is *no* relevance of
> volatile to MT programming, you might wish to read the literature
> which demonstrates that relevance certainly exists, even if
> controversy goes along with it.

The assertion isn't totally erroneous, just overstated. Volatile is
about as relevant to MT programming as const, perhaps less so. Andrei
could have just as easily used const for what he did, instead of
volatile. Except that most classes need const in the classical use.
One could almost argue that it is precisely the irrelevance of
volatile to MT that makes it appropriate in this case; in the
classical MT environment (pthreads, etc.), there is NO legitimate use
of the semantics of volatile. Which means that no class will need to
have volatile functions. Which means that the type attribute is free
to be exploited for other purposes. Which is exactly what Andrei did.

The fact that the other purpose just happened to involve MT-safety is
incidental, except for the fact that it confuses people who know that
volatile is irrelevant to MT, but who are used to seeing it misused
for such. Their immediate reaction is that this is just another such
case, since they see volatile and MT used together.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 23, 2001, 9:02:44 PM4/23/01
to
Andrei Alexandrescu wrote:

> "Michael Champigny" <michael....@compaq.com> wrote in message
> news:9bkqfe$1bj08$2...@nose.shr.dec.com...

> > > I love it when people comment on articles, and so confidently,
> > > without having read one line of them. Semicolon.

> > I love it when people assume you've read a particular article, and
> > so arrogantly. I have no idea what you are talking about. Read the
> > original post.

> I was answering to a post that in turn replies, and even quotes, a
> post of mine. That post addresses to me directly and is a direct
> reply to my affirmations that in turn refer to an article. So if the
> poster had no idea what another poster is talking about, he better
> doesn't engage in a conversation with him. Fair enough?

The problem is that the post he was replying to is embedded in the
middle of a thread where a number of very naïve statements about
volatile and MT safety have been made. That it refers in fact not to
these statements, but to your article in CUJ and the thread that
followed it is clear to me, and to others who have both read the
article and the thread and who recognize the people involved by name.
To others, I'm not so sure.

It's clear that Michael was replying to your post. But from his
following reply, it is equally clear that what he had in mind where
the naïve assertions made earlier, and not your very special use. He
may or may not approve of your bending the type system so much. But
that is not really the question he was addressing.

His comments are obviously not really relevant to what you are
proposing, but within the context of this thread, I can understand his
reaction: after seeing three or four really naïve assertions
concerning volatile and MT, he saw another post referring vaguely to
an article which suggests using volatile to solve MT problems.
Without more context, it is easy to understand the reaction.

So let's try not to take it personally. I'm sure he didn't mean you
specifically, but rather an all too prevelant attitude. It was just
chance that it was your post that triggered the reaction.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 24, 2001, 4:20:07 AM4/24/01
to
Dima Volodin wrote:

> Larry Brasfield wrote:

> > The 'volatile' keyword is certainly not any kind of 'hint' related
> > to optimization. It is likely to act as a constraint on
> > optimization in environments where multi-threaded execution might
> > take place, rendering volatile data observable by other threads,
> > or where memory mapped I/O is a possibility. As a practical
> > matter, that encompasses just about all environments. The effect
> > is that a correct optimizer must include access ordering
> > requirements arising from volatile data among its inviolable
> > optimization goals.

> All volatile is saying is that the program should request and
> present volatile data from/to the environment in a certain order,
> and it doesn't say anything about what the environment should do
> with this data. In particular, it doesn't say that the environment
> should present these data to other threads in any order or render
> these data visible to other threads or processes or I/O devices or
> whatever else at all.

The operative sentence in the (C) standard is (ISO/IEC 9899:1999,
6.7.3, last sentence in paragraph 6): "What constitutes an access to
an object that has volatile-qualified type is implementation defined."

If a compiler is targetting development of low-level systems, which
actually might do memory-mapped IO, it will certainly define access to
a volatile type so that it will work with memory-mapped IO. If you
are writing programs where you are actually programming memory-mapped
IO, you will use such a compiler.

I think we should keep the level at which we are working clear. An
application under Unix or Windows will NOT be doing memory-mapped IO;
the system won't allow it. A compiler which is designed for compiling
such applications, with support for pthreads or its equivalent in the
library, will probably not be of much use for an application doing
memory-mapped IO.

That doesn't mean that people who need to do memory mapped IO are not
going to be supported, and it is definitly the intend of the standard
that volatile be part of that support.

James Kanze

unread,
Apr 24, 2001, 4:21:35 AM4/24/01
to
Dima Volodin wrote:

> Torsten Mohrin wrote:

> > I've seen from previous discussions that 'volatile' in C++ seems
> > to be a rather difficult and controversial thing. Do you know any
> > article or FAQs, etc. with a good summary of the usage and meaning
> > of 'volatile' in C++?

> It's all in 1.9, paragraphs 6 through 11.

> > I'm especially interested in the relevance of 'volatile' regarding
> > MT programming.

> In POSIX threads (that is in a C++ implementation that uses POSIX
> threads in a way a C implementation would do it), 'volatile' is
> absolutely irrelevant. It may or may not be true for other flavours
> of MT.

Not only is it irrelevant with regards to threading, in a C++
application (which doesn't use longjmp), the semantics of volatile is
irrelevant to everything except signal handlers (which need a volatile
sigatomic_t).

Because it is irrelevant, and has no actual use, it is free for
certain people to use and abuse in ways that don't count on its
semantics, but only the fact that it is verified by the type
system:-).

Dima Volodin

unread,
Apr 24, 2001, 1:14:04 PM4/24/01
to
James Kanze wrote:

> Andrei Alexandrescu did publish an article about using volatile to
> ensure thread safety. In this case, however, he did NOT use any of
> the normal semantics of volatile; he simply exploited the fact that
> volatile is part of the type system, and that the compiler will
> enforce volatile safety in much the same way it enforces const
> safety. The idea is interesting, and I'd like to see it pursued
> further, but it is orthogonal with the actual semantics of volatile,
> according to the intent of the C/C++ standards.

Andrei coud have used 'const' to achieve the same goal, I suppose. And,
IMHO, it would have been much clearer approach just because the uninteded
use of the qualifier would've been more apparent.

> James Kanze mailto:ka...@gabi-soft.de

Dima

John Mullins

unread,
Apr 24, 2001, 2:50:14 PM4/24/01
to

"James Kanze" <James...@dresdner-bank.com> wrote in message
news:3AE4559A...@dresdner-bank.com...

> Dima Volodin wrote:
>
> > Andrei Alexandrescu wrote:
> > > I still support the use of 'volatile' as described in the article
> > > in any environment except environments that (1) don't provide
> > > mutexes and/or (2) put volatile variables in a special memory area
> > > so you cannot cast volatile away.
>
> > Which again comes down to cheating the compiler and relying on
> > something that neither the language nor the environment guarantee.
>
> Well, the principal point that it relies on is that the compiler
> enforces volatile correctness, which is guaranteed by the standard.
> As to what he "requires": if you don't have some sort of mutex, you're
> not going to be doing multithreading (in the usual sense, at least),
> so the requirement is irrelevant. And I've yet to see an
> implementation which actually did put volatile variables in special
> memory. (I don't actually think that this is even necessary for
> Andrei's code.)

The second point is moot anyway, since the actual variables themselves
should not be defined as volatile (since casting away volatile produces
undefined behaviour) and they should be accessed via volatile references,
which can then safely have the volatile attribute removed. Andrei regards
this approach as being overly politically correct. me, I just regard as
being correct.

JM

Gabriel Dos Reis

unread,
Apr 24, 2001, 7:28:31 PM4/24/01
to
James Kanze <James...@dresdner-bank.com> writes:

| > Which again comes down to cheating the compiler and relying on
| > something that neither the language nor the environment guarantee.
|
| Well, the principal point that it relies on is that the compiler
| enforces volatile correctness, which is guaranteed by the standard.

And what *precisely* is guaranteed by the Standard and how *much* is
guaranteed by the Standard need to be clarified.

--
Gabriel Dos Reis, dos...@cmla.ens-cachan.fr

James Kanze

unread,
Apr 25, 2001, 12:30:22 PM4/25/01
to
Dima Volodin wrote:

> James Kanze wrote:

> > Andrei Alexandrescu did publish an article about using volatile to
> > ensure thread safety. In this case, however, he did NOT use any
> > of the normal semantics of volatile; he simply exploited the fact
> > that volatile is part of the type system, and that the compiler
> > will enforce volatile safety in much the same way it enforces
> > const safety. The idea is interesting, and I'd like to see it
> > pursued further, but it is orthogonal with the actual semantics of
> > volatile, according to the intent of the C/C++ standards.

> Andrei coud have used 'const' to achieve the same goal, I
> suppose. And, IMHO, it would have been much clearer approach just
> because the uninteded use of the qualifier would've been more
> apparent.

He could have -- const would certainly work the same as volatile
here. However, most C++ classes already use const, in its intended
way. So a conflict occurs. One of the advantages of volatile here is
precisely that it has absolutely NO use otherwise in a Unix/Windows
non-root program (except with sigatomic_t). So there cannot
reasonably be a conflict due to e.g. the actual class overloading on
volatile.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 25, 2001, 12:32:16 PM4/25/01
to
Gabriel Dos Reis wrote:

> James Kanze <James...@dresdner-bank.com> writes:

> | > Which again comes down to cheating the compiler and relying on
> | > something that neither the language nor the environment
> | > guarantee.

> | Well, the principal point that it relies on is that the compiler
> | enforces volatile correctness, which is guaranteed by the
> | standard.

> And what *precisely* is guaranteed by the Standard and how *much* is
> guaranteed by the Standard need to be clarified.

In the case of Andrei's use of volatile, all that is needed is
guaranteed by the standard, and there is no need for clarification.
The semantics of volatile are very vague in the standard.
Intentionally; any use of the volatile semantics is implementation
defined anyway. But the syntax and the typing rules are exactly the
same as for const (which doesn't seem to pose any particular
problems), and all Andrei is using are the typing rules.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Gerhard Menzl

unread,
Apr 25, 2001, 5:01:15 PM4/25/01
to
Dima Volodin wrote:

> > Andrei Alexandrescu did publish an article about using volatile to
> > ensure thread safety. In this case, however, he did NOT use any of
> > the normal semantics of volatile; he simply exploited the fact that
> > volatile is part of the type system, and that the compiler will
> > enforce volatile safety in much the same way it enforces const
> > safety. The idea is interesting, and I'd like to see it pursued
> > further, but it is orthogonal with the actual semantics of volatile,
> > according to the intent of the C/C++ standards.
>
> Andrei coud have used 'const' to achieve the same goal, I suppose.
> And, IMHO, it would have been much clearer approach just because the
> uninteded use of the qualifier would've been more apparent.

It would have caused confusion without end because const is used
universally and in a standardized fashion for achieving, well, const
correctness. On the other hand, volatile is hardly used because its
semantics are implementation-defined, and probably also because most
people don't understand what it's for. It's more or less an abandoned
qualifier, which is why Andrei gave it a new meaning. Whether redefining
a little used concept is okay may be debatable; to change the meaning of
something that is widely and unambiguously agreed upon is
counterproductive.

Gerhard Menzl

Dima Volodin

unread,
Apr 25, 2001, 9:59:51 PM4/25/01
to
James Kanze wrote:
>
> The operative sentence in the (C) standard is (ISO/IEC 9899:1999,
> 6.7.3, last sentence in paragraph 6): "What constitutes an access to
> an object that has volatile-qualified type is implementation defined."

Exactly. What we have here is a language construct whose interpretation
is strictly implementation defined. What's the point in having it in the
language at all?

> If a compiler is targetting development of low-level systems, which
> actually might do memory-mapped IO, it will certainly define access to
> a volatile type so that it will work with memory-mapped IO. If you
> are writing programs where you are actually programming memory-mapped
> IO, you will use such a compiler.
>
> I think we should keep the level at which we are working clear. An
> application under Unix or Windows will NOT be doing memory-mapped IO;
> the system won't allow it.

Unless, of course, you do mmap() tricks or whatever its Windows
counterpart is.

> A compiler which is designed for compiling
> such applications, with support for pthreads or its equivalent in the
> library, will probably not be of much use for an application doing
> memory-mapped IO.

Why not? You can always use implementation specific functions to do
implementation specific tasks, C++ lets you make it with all the
syntactical sugar you want even without 'volatile', and 'inline' and
asm() can be used with devastating success when a non-inlined function
call becomes a problem.

> That doesn't mean that people who need to do memory mapped IO are not
> going to be supported, and it is definitly the intend of the standard
> that volatile be part of that support.

MHO is that 'volatile' is nothing but a historical kludge that harkens
back to the times of the original Unix and C, and it simply doesn't
belong in the language today. We should either get rid of it completely
or generalise the mechanism of implementation specific object and class
attributes by something along the lines of gcc's __attribute__().

> James Kanze mailto:ka...@gabi-soft.de

Dima

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

Andrei Alexandrescu

unread,
Apr 26, 2001, 4:24:57 AM4/26/01
to
"James Kanze" <James...@dresdner-bank.com> wrote in message
news:3AE67FA5...@dresdner-bank.com...
[snip]

> But the syntax and the typing rules are exactly the
> same as for const (which doesn't seem to pose any particular
> problems), and all Andrei is using are the typing rules.

Indeed, yet there is one difference: const does not discriminate between
primitives and user-defined types, volatile does.

Andrei

James Kanze

unread,
Apr 26, 2001, 12:01:14 PM4/26/01
to
Gerhard Menzl wrote:

> > Andrei coud have used 'const' to achieve the same goal, I suppose.
> > And, IMHO, it would have been much clearer approach just because the
> > uninteded use of the qualifier would've been more apparent.

> It would have caused confusion without end because const is used
> universally and in a standardized fashion for achieving, well, const
> correctness. On the other hand, volatile is hardly used because its
> semantics are implementation-defined, and probably also because most
> people don't understand what it's for.

I'm not sure that it is "hardly used"; I've used it extensively in
certain types of applications. And apparently, some people are trying
to use it (incorrectly) for reasons involving thread safety.

The important point is that in a C++ program running under Unix or
Windows, it has NO legitimage use except applied to sig_atomic_t. Not
hardly used, but NO possible correct use.

(Note that I'm actually agreeing with your comment. I just feel that
it wasn't strong enough.)

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

James Kanze

unread,
Apr 26, 2001, 12:11:23 PM4/26/01
to
Dima Volodin wrote:

> James Kanze wrote:

> > The operative sentence in the (C) standard is (ISO/IEC 9899:1999,
> > 6.7.3, last sentence in paragraph 6): "What constitutes an access
> > to an object that has volatile-qualified type is implementation
> > defined."

> Exactly. What we have here is a language construct whose
> interpretation is strictly implementation defined. What's the point
> in having it in the language at all?

So that the relevant type rules can be defined? (So that Andrei could
use it for something totally different?:-)

> > If a compiler is targetting development of low-level systems,
> > which actually might do memory-mapped IO, it will certainly define
> > access to a volatile type so that it will work with memory-mapped
> > IO. If you are writing programs where you are actually
> > programming memory-mapped IO, you will use such a compiler.

> > I think we should keep the level at which we are working clear.
> > An application under Unix or Windows will NOT be doing
> > memory-mapped IO; the system won't allow it.

> Unless, of course, you do mmap() tricks or whatever its Windows
> counterpart is.

That's not quite the type of memory mapped IO I was thinking about.

At the hardware level, a lot of processors simply reserve a block of
memory addresses for IO ports, etc. Most processors have a separate
IO address space, with special hardware instructions to access it, but
it is not universal (PDP-11 didn't, for example), and even when
present, the hardware implementors may prefer to put the IO ports in
the memory address space, for any number of reasons. I doubt that
anyone does this with 80x86 architecture -- other addressing
constraints make it extremely difficult. I have seen it with 8080,
and it was the most frequent solution with the old TI 9900. And it
was the only way to implement IO with the PDP-11 instruction set;
there just wasn't a separate IO address space. (I think that this was
true of the VAX as well. And let's not forget that much of the early
work in C was on these two processors.)

Now consider one of the early serial ports I used: the Intel 8051.
The normal way to initialize it started by writing 0 three times to
the control port. If you have memory mapped IO, the C code would look
something like:

unsigned char* pControl = 0xff24 ;
*pControl = 0 ;
*pControl = 0 ;
*pControl = 0 ;

Which worked fine with the early C compilers. But you can surely
imagine what even the simplest optimization would do with this.
Whence the volatile keyword, to inform the compiler NOT to optimize.

It's obvious that such code is by its very nature unportable; none of
my current processors has an 8051 at address 0xff24, and even if they
did, I certainly couldn't access it in this way from a user
application. On the other hand, it isn't unreasonable to imagine a
more or less portable implementation of driver code for a memory
mapped 8051, which would receive the port addresses as arguments, and
could be compiled by different compilers. While the standard doesn't
require semantics of volatile that would make this work, it is
expressedly the intent (at least in C90).

Whether volatile is the perfect solution or not is not the question.
It is the standard C/C++ solution. It works, in practice. And
personally, I see no real reason to change it.

So much for background. As you (and others) have very correctly
pointed out, volatile is irrelevant to multi-threading. Which is fine
by me; it wasn't designed as a solution to multi-threading either.
Volatile achieves what it was designed to achieve. If someone finds a
way to make it achieve something else, so much the better, but it
isn't essential to justify the keyword.

> > A compiler which is designed for compiling such applications,
> > with support for pthreads or its equivalent in the library, will
> > probably not be of much use for an application doing memory-mapped
> > IO.

> Why not? You can always use implementation specific functions to do
> implementation specific tasks, C++ lets you make it with all the
> syntactical sugar you want even without 'volatile', and 'inline' and
> asm() can be used with devastating success when a non-inlined
> function call becomes a problem.

This is the way I've always done it. Most of the systems I've worked
on have used a separate IO address space, rather than memory mapped
IO. So I either have to use compiler extensions, or assembler, to
address the ports anyway.

But just because I've always done it this way doesn't mean that I'm
going to insist that others may not do it their way.

> > That doesn't mean that people who need to do memory mapped IO are
> > not going to be supported, and it is definitly the intend of the
> > standard that volatile be part of that support.

> MHO is that 'volatile' is nothing but a historical kludge that
> harkens back to the times of the original Unix and C, and it simply
> doesn't belong in the language today.

I don't know. It certainly isn't relevant for user applications under
Unix or Windows. But I suspect that there are processors (maybe some
DSP's) where it is relevant.

--
James Kanze mailto:ka...@gabi-soft.de
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
Ziegelhüttenweg 17a, 60598 Frankfurt, Germany Tel. +49(069)63198627

Dima Volodin

unread,
Apr 26, 2001, 5:44:07 PM4/26/01
to
Andrei Alexandrescu wrote:
>
> "James Kanze" <James...@dresdner-bank.com> wrote in message
> news:3AE67FA5...@dresdner-bank.com...
> [snip]
> > But the syntax and the typing rules are exactly the
> > same as for const (which doesn't seem to pose any particular
> > problems), and all Andrei is using are the typing rules.
>
> Indeed, yet there is one difference: const does not discriminate between
> primitives and user-defined types, volatile does.

How does it do it?

> Andrei

Dima

Dima Volodin

unread,
Apr 26, 2001, 7:42:12 PM4/26/01
to
James Kanze wrote:

> Dima Volodin wrote:
>
> > James Kanze wrote:
>
> > > The operative sentence in the (C) standard is (ISO/IEC 9899:1999,
> > > 6.7.3, last sentence in paragraph 6): "What constitutes an access
> > > to an object that has volatile-qualified type is implementation
> > > defined."
>
> > Exactly. What we have here is a language construct whose
> > interpretation is strictly implementation defined. What's the point
> > in having it in the language at all?
>
> So that the relevant type rules can be defined? (So that Andrei could
> use it for something totally different?:-)

Yep.

> > > I think we should keep the level at which we are working clear.
> > > An application under Unix or Windows will NOT be doing
> > > memory-mapped IO; the system won't allow it.
>
> > Unless, of course, you do mmap() tricks or whatever its Windows
> > counterpart is.
>
> That's not quite the type of memory mapped IO I was thinking about.

Strike this out, I forgot about msync().

> At the hardware level, a lot of processors simply reserve a block of
> memory addresses for IO ports, etc. Most processors have a separate
> IO address space, with special hardware instructions to access it, but
> it is not universal (PDP-11 didn't, for example), and even when
> present, the hardware implementors may prefer to put the IO ports in
> the memory address space, for any number of reasons. I doubt that
> anyone does this with 80x86 architecture -- other addressing
> constraints make it extremely difficult.

Unless you do video frame buffer access.

> I have seen it with 8080,
> and it was the most frequent solution with the old TI 9900. And it
> was the only way to implement IO with the PDP-11 instruction set;
> there just wasn't a separate IO address space. (I think that this was
> true of the VAX as well. And let's not forget that much of the early
> work in C was on these two processors.)

That's what I referred to later in my posting.

> Now consider one of the early serial ports I used: the Intel 8051.
> The normal way to initialize it started by writing 0 three times to
> the control port. If you have memory mapped IO, the C code would look
> something like:
>
> unsigned char* pControl = 0xff24 ;
> *pControl = 0 ;
> *pControl = 0 ;
> *pControl = 0 ;
>
> Which worked fine with the early C compilers. But you can surely
> imagine what even the simplest optimization would do with this.
> Whence the volatile keyword, to inform the compiler NOT to optimize.

Guess what - I did some work with drivers on both PDP-11/VAX-11 and x86
based architectures, so your explanations while welcome, weren't really
necessary :-)

> It's obvious that such code is by its very nature unportable; none of
> my current processors has an 8051 at address 0xff24, and even if they
> did, I certainly couldn't access it in this way from a user
> application. On the other hand, it isn't unreasonable to imagine a
> more or less portable implementation of driver code for a memory
> mapped 8051, which would receive the port addresses as arguments, and
> could be compiled by different compilers. While the standard doesn't
> require semantics of volatile that would make this work, it is
> expressedly the intent (at least in C90).
>
> Whether volatile is the perfect solution or not is not the question.
> It is the standard C/C++ solution. It works, in practice. And
> personally, I see no real reason to change it.

The background is very much understood. My point is that it doesn't look
very logical to drag some very implementation specific concepts all the
way from the early 1970s. Or rather - why there's just this one kind of
'special' memory in the language? Why don't we have a generic way to
specify that this particular object should reside or this particular
pointer should point to an object in this particular implementation
specific kind of memory? Be it a memory-mapped file or a part of the
x86-like IO space or an object in x86's 'far' memory or some specific
area of a microcontroller's memory or even some special registers of a
CPU. MHO is that 'volatile' should go the same way 'register' went
(another keyword I'd like to see made invalid).

> > MHO is that 'volatile' is nothing but a historical kludge that
> > harkens back to the times of the original Unix and C, and it simply
> > doesn't belong in the language today.
>
> I don't know. It certainly isn't relevant for user applications under
> Unix or Windows. But I suspect that there are processors (maybe some
> DSP's) where it is relevant.

Same point - there's a _special implementation specific_ kind of memory
to deal with, and, potentially, more than one special type.

> James Kanze mailto:ka...@gabi-soft.de

Dima


Gerhard Menzl

unread,
Apr 27, 2001, 10:09:07 AM4/27/01
to
James Kanze wrote:

> > It would have caused confusion without end because const is used
> > universally and in a standardized fashion for achieving, well, const
> > correctness. On the other hand, volatile is hardly used because its
> > semantics are implementation-defined, and probably also because most
> > people don't understand what it's for.
>
> I'm not sure that it is "hardly used"; I've used it extensively in
> certain types of applications. And apparently, some people are trying
> to use it (incorrectly) for reasons involving thread safety.
>
> The important point is that in a C++ program running under Unix or
> Windows, it has NO legitimage use except applied to sig_atomic_t. Not
> hardly used, but NO possible correct use.

What I meant to say is: volatile is used by orders of magnitude more
rarely than const, and when it is used at all, it is for declaring
variables volatile. Before Andreis article, I have never come across a
piece of code that would use volatile as a qualifier for member
functions.

I think his "abuse" of the type system can be considered as an act of
language feature squatting. <g>

Gerhard Menzl

Dima Volodin

unread,
Apr 27, 2001, 12:26:24 PM4/27/01
to
James Kanze wrote:
>
> The important point is that in a C++ program running under Unix or
> Windows, it has NO legitimage use except applied to sig_atomic_t. Not
> hardly used, but NO possible correct use.

Some Unix systems actually allowed to map video buffers into a process
address space.

> James Kanze mailto:ka...@gabi-soft.de

Dima

[ Send an empty e-mail to c++-...@netlab.cs.rpi.edu for info ]

David Bradley

unread,
Apr 27, 2001, 9:47:26 PM4/27/01
to
"Dima Volodin" <d...@dvv.org> wrote in message
news:3AE963B5...@dvv.org...

> Some Unix systems actually allowed to map video buffers into a process
> address space.

I would expect that the assumption here is applications. Device drivers and
the like would very likely encounter the use of volatile, dealing with port
address and such.

t...@cs.ucr.edu

unread,
Jul 14, 2001, 3:21:40 PM7/14/01
to
Gerhard Menzl <gerhar...@sea.ericsson.se> wrote:
: "R. Sinoradzki" wrote:
[..]
:>
:> from the standard clause 1.9
:>
:> 9 When the processing of the abstract machine is interrup-
:> ted by receipt of a signal, the values of objects
:> with type other than volatile sig_atomic_t are unspecified,
:> and the value of any object not of volatile sig_atomic_t
:> that is modified by the handler becomes undefined.

Hmmmmm. I'm pleasantly surprised by the words "the value of
... becomes undefined." In C89 and my understanding of earlier drafts
of the C++ standards, it was the behavior of the program rather than
the value of the object that became undefined. Does C++ now allow
a signal handler to read static variable and get only undefined value
rather than undefined behavior?

Tom Payne

0 new messages