Why use volatile anyway?

44 views
Skip to first unread message

John Torjo

unread,
May 22, 2002, 6:18:03 PM5/22/02
to
Hi all,

As we know, the volatile keyword is used to specify that a variable
may be modified by external processes. However, when I asked senior
programmers, they all told me "Don't use volatile, eventually use a
Critical Section instead".

That's because, if a variable is volatile, and it's changed by another
thread while you're reading it, you could still wind up with a bad
value (a partially written value).

I understood that a good use for volatile is when IMPLEMENTING
Critical Sections, Mutexes, Semaphors, etc. But this happens very
rarely, and you should use the primitives provided by your OS.


So, finally, is there any use for volatile in real-life applications
(except for the one I already mentioned)?
Are there any types that it's safe to be used with? (for instance, I
assume it should be used safely with 'char's, since they should be
atomic - am I wrong?)

Thanks to those who answer,
John

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

Mat Noguchi

unread,
May 22, 2002, 8:07:49 PM5/22/02
to
Memory mapped io, for one.

MSN

Mike Schilling

unread,
May 23, 2002, 4:40:43 AM5/23/02
to
"John Torjo" <jto...@yahoo.com> wrote in message
news:c638aac5.02052...@posting.google.com...

> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).
>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.
>
>
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?
> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

volatile is not useful in portable code; as you point out, it's not
specified fully enough to guarantee any useful behavior.

In a particular C++ implementation, though, volatile may be exactly what you
need to access a hardware register, or a region of shared memory, or
communicate between multiple threads in a single process. (Likewise, there
are implementations of C in which volatile is what's needed to give an
automatic variable a predictable value after longjump, but AFAIK that's not
portably true.)

Rob

unread,
May 23, 2002, 4:43:11 AM5/23/02
to
"John Torjo" <jto...@yahoo.com> wrote in message
news:c638aac5.02052...@posting.google.com...
> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).

True. But the point of volatile is to give a hint to the compiler that
a variable could be changed in a way the compiler can't predict.

If your compile/library/environment supports synchronisation primitives,
then those are provided as a means for the programmer to exercise
explicit control over how other threads of execution modify a given
variable. Of course, since the C++ standard doesn't address
multithreading (and hence synchronisation) at all, this argument is
rather moot.

>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.
>

I would hope not. Implementation of an operating system means that
the operating system (or its source code) must explicitly control how
it does things. For example, when a thread enters a critical section
execution must stop until the thread holding that critical section releases
it. The volatile keyword is for things that occur outside control of
the program. If synchronisation primitives were not explicitly controlled
by the operating system, there would be no point in using them for
mutithreaded programming.

>
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?

Memory mapped I/O between processes on separate machines is
one example. If a process on machine A can change a memory
location, then code on machine B that accesses it can not afford
to optimise away multiple accesses of that memory.

Another example I've seen on a couple of occasions is working
around obscure bugs with an aggressive compiler/optimiser.
That is obviously very compiler (even compiler version) specific.
Obviously not a recommended course of action: the cases in
questions were quick fixes and associated with loud bug reports
to compiler vendors.

> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)
>

That depends on the operating system and hardware. On preemptive
operating systems, for example, it is not even safe to assume that
"primitive" operations like setting a char are atomic, unless you've
explicitly bypassed operating system and are talking to the hardware
(eg in a device driver).

Serve Laurijssen

unread,
May 23, 2002, 4:45:58 AM5/23/02
to

"John Torjo" <jto...@yahoo.com> wrote in message
news:c638aac5.02052...@posting.google.com...
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?

I use it often when debugging. If I want a loop to break when it iterates
10000 times I insert a statement
volatile int count = 0;
if( count == 10000 )
count = count; <-- breakpoint here.

Sometimes, if the variable wasn't volatile, the compiler optimizes count
away and conditional breakpoints are very slow in my compiler.

I know, not really real-life, but it does work

Michiel Salters

unread,
May 23, 2002, 8:03:03 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...

> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".

Critical sections do something entirely different: they make sure you
won't be interrupted when you read a variable. volatile makes sure you
actually /read/ the variable.

> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).

Right; and with volatile this is even more likely to happen. Without
volatile you have a chance of getting a cached (old) copy - which
doesn't make things a lot better. So you need a critical section.

> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.

or the boost libraries.

> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?

Memory mapped I/O needs it. With I/O registers, *a == *a may be false;
without volatile the compiler probably optimizes it to true.

> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

You're wrong. The type most likely to be atomic is int, but you can't
rely on 'likely' in real life programming. But atomic and volatile
are also unrelated.

Regards,
--
Michiel Salters

Cyril Schmidt

unread,
May 23, 2002, 8:07:54 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?

You may want to use a volatile variable if you need to use memory-mapped
registers where it matters how many times you *read* them. With volatiles,
the compiler is not allowed to optimise away the reading of the variable.

For instance, if you have a status register that is reset to zero every
time it is read, you should use something like this to address it:

const volatile int* status = STATUS_REG_ADDRESS;

(it make sense to use const if it is a read-only register).

As regards using volatile with non-primitive types, you may take a look
at http://www.cuj.com/experts/1902/alexandr.htm?topic=experts

Kind regards,

Cyril

Daniel

unread,
May 23, 2002, 8:13:24 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...
> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).
>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.

You can use it in your own classes in conjunction with OS threading
primatives, to get the compiler to help you ensure that you lock data
before you access it.

Good article here:

http://www.cuj.com/experts/1902/alexandr.htm?topic=articles

Carl Muller

unread,
May 23, 2002, 9:57:53 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).
>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.
>
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?
> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

My current uses of volatile:

(1) reading and writing a hardware register:
unsigned short value = (volatile unsigned short*) 0x04000000;
This is because (a) I don't want the value cached when I am reading
a loop, since the hardware may change it, and also it may have side-effects.
(b) reading and writing hardware registers often needs to be done
in a specific order.

(2) implementing locking between threads, similar to implementing
a mutex (except in an adhoc way unfortunately).
This is because when implementing a locking algorithm, even if
you can assume atomic access for reading or writing a machine word,
you want to tell the compiler not to jumble up the order you are
doing this in.

(3) Telling the compiler that I really mean it when I write inline
assembly. Otherwise it tends to remove the assembly because it can't
see the point of it :-)
asm volatile ("mov r2,lr");

Bonus points to people who've worked out what system I am coding on :-)

Carl.

Carl Muller

unread,
May 23, 2002, 9:58:52 AM5/23/02
to
Oops, I forgot one thing:

jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...

> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

I am not sure, but I think if you store to a volatile (8bit) char
or (16 bit) short on a 32bit machine, it may well not be atomic -
e.g. it may load the value, and it with 0xffffff00, or it with
the new value, then store it.
If an interrupt happens halfway through this, problems may occur.
You should look through the generated machine code
(and your architectures documentation) to see if that is the case.

Carl

Shane Beasley

unread,
May 23, 2002, 11:23:48 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...

> So, finally, is there any use for volatile in real-life applications


> (except for the one I already mentioned)?

The general rule is that, if an variable can be atomically read and
written and is read- or write-only (e.g., a timer is read-only; an
output register is write-only), then you can rely exclusively on
volatile.

There's a special case for this rule, as per this article:

http://www.cuj.com/experts/1902/alexandr.htm?topic=experts

If a variable is designed to be set once and later altered by a
concurrent process (e.g., a thread or signal handler), it should be
viewed as read-only (after initialization), and thus it should be
declared volatile. Observe:

extern bool stillGoing; // in a header included by all threads

int i = 0;
bool stillGoing = true;
while (stillGoing) { ++i; }

If threads didn't exist, this would be an infinite loop. As it
happens, as far as C++ is concerned, threads don't exist -- the
language isn't constructed to take concurrency into account, except
for the 'volatile' keyword. Without the keyword, the compiler can
optimize this code so that stillGoing is kept in a register, and thus
never notices that stillGoing changes in main memory. It might even be
able to optimize stillGoing out of the loop altogether, sort of like a
while (true) loop.

On the other hand, if you declare stillGoing as volatile, you are
instructing the compiler not to optimize dealings with that variable.
It will always refer to the One True stillGoing, and thus will always
notice if it changes.

> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

The only guarantee in C++ is that std::sig_atomic_t in <csignal> is
atomic. Of course, it's probably the case that other types are atomic
as well, but that is entirely platform-dependent.

Finally, we've covered this before:

http://groups.google.com/groups?threadm=3B79B924...@hotmail.com

Perhaps that discussion will help a bit, too.

- Shane

Bing Xiao

unread,
May 23, 2002, 11:37:23 AM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...
> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).
>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.
>
>
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?
> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)
>
>
Even if you use critical sections, you will still need to use volatile
to qualify variables shared by multiple threads/processes. The reason
is that by declaring a variable "volatile", you tell the compiler not to
perform some optimizations. Consider the following sequence regarding
reading a variable x:
1. Enter critical section;
2. Read x;
3. Leave critical section;
4. Enter critical section;
5. Read x;
6. Leave critical section;

If x is not declared volatile, during optimazation, the compiler may
discover that statement 2 and statement 5 are reading the same
variable, thus it may generate code like this:

1. Enter critical section;
2. Load x to a register r;
3. Read register r;
4. Leave critical section;
5. Enter critical section;
6. Read register r;
7. Leave critical section;

If another thread modified x between instructions 4 and 5, instruction 6
still read back the original value!! So you see critical section alone
does not provide enough protection.

Also the value of a volatile variable is immediately written on assignment
(instead of being kept in registers and flush to memory later). This is also
important in mutithread/multiprocess environment.

Bing Xiao

Kevin Cline

unread,
May 23, 2002, 9:54:36 PM5/23/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...
> Hi all,
>
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value).
>
> I understood that a good use for volatile is when IMPLEMENTING
> Critical Sections, Mutexes, Semaphors, etc. But this happens very
> rarely, and you should use the primitives provided by your OS.
>
>
> So, finally, is there any use for volatile in real-life applications
> (except for the one I already mentioned)?
> Are there any types that it's safe to be used with? (for instance, I
> assume it should be used safely with 'char's, since they should be
> atomic - am I wrong?)

You're wrong. You can not portably synchronize threads except by
using the facilities of the threading library. There was a long
thread on this topic in c.l.c++ last year.

Ron

unread,
May 23, 2002, 11:33:42 PM5/23/02
to
> As we know, the volatile keyword is used to specify that a variable
> may be modified by external processes. However, when I asked senior
> programmers, they all told me "Don't use volatile, eventually use a
> Critical Section instead".
>
> That's because, if a variable is volatile, and it's changed by another
> thread while you're reading it, you could still wind up with a bad
> value (a partially written value)....

Both volatile and proper use of synchronization primitives are
(generally) necessary to insure that multiple threads see and act upon
a consistent set of data. Here's an example of two threads that use a
mutex to synchronize access to the integer 'i', which is not volatile.
In this example, i's initial value is 0:

Time Thread 1 Thread 2
---- -------- --------

T1 lock mutex wait for mutex
T2 ++i; // local copy of i == 1, wait for mutex
// but copy in memory not
// guaranteed to be 1
T3 release mutex * wait for mutex
T4 ... lock mutex
T5 ... ++i; // Does this yield 1
or 2?
// Unless i is
volatile,
// it's
unpredictable.

-- Ron

* In most mutex implementations, releasing the mutex does not
guarantee that protected variables, like i, are written to memory. In
fact, in most implementations, the OS has no way to know which
variables you're protecting with a given mutex.

John Torjo

unread,
May 24, 2002, 7:22:07 PM5/24/02
to
Hi all,

Thanks to all who answered. You've been a great help. I've compiled
what I have understood.

[1]
Uses of volatile

You use volatile for:
- hardware/ memory mapped registers
- memory mapped I/O
- get around some some compiler bugs
- debugging tricks


[2]
About the article (http://www.cuj.com/experts/1902/alexandr.htm?topic=experts)

I have read Andrei's article, which was very helpful. So, in order to
prevent bugs, you should use volatile keyword to ALL of your shared
data (that is, data that can be used from multiple threads).

Then, within critical sections, use the LockingPtr (as described in
the article).

What I did not understand was: why can't you assign a non-volatile
object to a volatile object?
Eventually, could you not override operator= that it takes a
non-volatile object?
Something like
class custom_class
{
...
void operator=( custom_class & object) volatile;
};

However, after thinking a bit about the article, you should not need
volatile at all (Andrei, forgive me if I'm totally wrong here).
This is because of the following:
- suppose you have a resource (variable) that needs to be accessed
thread-safe
- you have a mutex associated with the resource
- accessing this resource must be done only while the resource is
locked; therefor, no need for volatile.

If you were to have a variable and you accessed it while the mutex is
not locked, even if the variable is volatile, the code is not
thread-safe anymore. Therefor, no need for volatile.

However, after reading Ron's post, I am quite confused.
And Ron, I think you are quite right.
However, there is (I think) a way to avoid use of volatile.
All the thread-safe code should be embodied in a block, and an
automatic Lock/ Unlock resource class should exist (mostly like
LockingPtr class presented in the article), like this:
{
CAutoLockUnlockResource locker(mutex);
// ... thread safe code
}
In this case you are guaranteed that any possibly cached variables are
written into memory.
Also, in a function, there should not be two parts of code that need
locking. If there are, volatile must be used, and Andrei's LockingPtr
class.

Can I make the above assumtion, or not?

Another question is:
Is there a big difference from
(1) - when using both volatile and critical sections
(2) - when using only critical sections?


[3]
Atomic behaviour

You cannot rely that any type is atomically read/ written. This
confuses me a bit, since Shane Beasey said that "The only guarantee in


C++ is that std::sig_atomic_t in <csignal> is

atomic". I looked this up, and yes, this is guaranteed to be atomic
(MSDN sais "Type of object that can be modified as atomic entity, even
in presence of asynchronous interrupts").

This would make me believe that this type should be atomically read/
written, and used in correlation with volatile could allow
implementations for:
- access to shared memory, and even
- a custom (most likely slow) critical section class.


Also Shane, in the other thread
(http://groups.google.com/groups?threadm=3B79B924...@hotmail.com),
you said:
the only safe, portable type of volatile object (well, as
portable as a volatile can get :P) uses a read-only or write-only
std::sig_atomic_t (from <csignal>).
What use would a read-only volatile std::sig_atomic_t object be?

Thanks again,

Andrei Alexandrescu

unread,
May 25, 2002, 9:17:45 AM5/25/02
to
"John Torjo" <jto...@yahoo.com> wrote in message
news:c638aac5.02052...@posting.google.com...
> [2]
> About the article
(http://www.cuj.com/experts/1902/alexandr.htm?topic=experts)
>
> I have read Andrei's article, which was very helpful. So, in order to
> prevent bugs, you should use volatile keyword to ALL of your shared
> data (that is, data that can be used from multiple threads).

Not quite. Posix-compliant compilers make the use of volatile unnecessary.
You may want to read the flurry of messages on this newsgroup and on
comp.threads after the article was out. I learn a lot from those. (See my
article that followed the article on volatile.)

But beware that many of those messages were caused by a misunderstanding;
the techniques presented in that article are valid and recommendable to the
best of my knowledge.

> What I did not understand was: why can't you assign a non-volatile
> object to a volatile object?

The rule is different for primitive and non-primitive types.

> Eventually, could you not override operator= that it takes a
> non-volatile object?

You can.

> However, after thinking a bit about the article, you should not need
> volatile at all (Andrei, forgive me if I'm totally wrong here).
> This is because of the following:
> - suppose you have a resource (variable) that needs to be accessed
> thread-safe
> - you have a mutex associated with the resource
> - accessing this resource must be done only while the resource is
> locked; therefor, no need for volatile.

Yes, provided that the compiler ensures that registers are flushed across
the mutex.lock() calls.

> If you were to have a variable and you accessed it while the mutex is
> not locked, even if the variable is volatile, the code is not
> thread-safe anymore. Therefor, no need for volatile.

Correct. The whole point of the article was to use volatile /exactly/ to
make illegal code illegal at compile time. The techniques in the article do
not use the original semantics of volatile at all.

> Another question is:
> Is there a big difference from
> (1) - when using both volatile and critical sections
> (2) - when using only critical sections?

There's no difference on most systems. Notably pthreads makes it clear
there's no difference.

> You cannot rely that any type is atomically read/ written. This
> confuses me a bit, since Shane Beasey said that "The only guarantee in
> C++ is that std::sig_atomic_t in <csignal> is
> atomic". I looked this up, and yes, this is guaranteed to be atomic
> (MSDN sais "Type of object that can be modified as atomic entity, even
> in presence of asynchronous interrupts").

Asynchronous interrupts are different from threads, notably in
multiprocessor systems. There's code that works fine on one processor and
does not on dual-processor machines.

> This would make me believe that this type should be atomically read/
> written, and used in correlation with volatile could allow
> implementations for:
> - access to shared memory, and even
> - a custom (most likely slow) critical section class.

This is a path to avoid. Best use some threading library with well-defined
semantics.


Andrei

Shane Beasley

unread,
May 25, 2002, 9:12:53 PM5/25/02
to
jto...@yahoo.com (John Torjo) wrote in message news:<c638aac5.02052...@posting.google.com>...

> Also Shane, in the other thread


> (http://groups.google.com/groups?threadm=3B79B924...@hotmail.com),
> you said:
>
> > the only safe, portable type of volatile object (well, as
> > portable as a volatile can get :P) uses a read-only or write-only
> > std::sig_atomic_t (from <csignal>).
>
> What use would a read-only volatile std::sig_atomic_t object be?

"Read-only" doesn't mean "never changes"; that would be useless. :)

I was referring to the use of a volatile variable as a broadcast
medium, where a writer thread sends data to a reader thread and never
gets anything back -- the variable would be write-only in one thread
and read-only in the other. Such a variable could be used as a flag,
as when the writer transmits information about its current state
(e.g., a boolean indicating its status, a counter of some kind, the
current value of its computation, etc.).

Of course, more complex transmissions, like sending streams of data,
require bidirectional communication -- the reader needs to tell the
writer when it's okay to send the next block of data. I suppose you
could do this using a ::gasp:: read-write volatile variable:

volatile std::sig_atomic_t data;
volatile std::sig_atomic_t dataReady = false;

std::sig_atomic_t doRead () {
while (!dataReady) { } // reads from dataReady
std::sig_atomic_t n = data; // data is read-only
dataReady = false; // writes to dataReady
return n;
}

void doWrite (std::sig_atomic_t n) {
while (dataReady) { } // reads from dataReady
data = n; // data is write-only
dataReady = true; // writes to dataReady
}

>From a practical perspective, however, spinlocks are a waste of
resources and would be better implemented by using techniques
supported by the operating system. In other words, a read-write
scenario like this one would be better handled with a
read-only/write-only (like "data" above) and a semaphore.

In the case where you want true bidirectional transmission -- that is,
there is no "reader" or "writer," but only two peers -- you could use
one read-write variable and figure out how to keep the threads from
colliding, or you could use two variables modeled after the one-way
code posted above. (Either might very well work better than the other;
I'll leave that as an exercise for the reader.)

Of course, I can't foresee all possible uses for volatile variables;
YMMV. I'm just saying that I'm not as crazy as I look. :)

- Shane

Allan W

unread,
May 29, 2002, 7:54:28 AM5/29/02
to
sbea...@cs.uic.edu (Shane Beasley) wrote

> "Read-only" doesn't mean "never changes"; that would be useless. :)

Literals are read-only, and they never change during the course of
execution.

AFAIK, all computers today come with ROMS. For instance, PC's come
with a BIOS in ROM. This is read-only, and never changes.

I would never declare either of these volatile, of course...

Ron

unread,
May 30, 2002, 11:11:36 AM5/30/02
to
> However, after thinking a bit about the article, you should not need
> volatile at all (Andrei, forgive me if I'm totally wrong here). This
> is because of the following:
> - suppose you have a resource (variable) that needs to be accessed
> thread-safe
> - you have a mutex associated with the resource
> - accessing this resource must be done only while the resource is
> locked; therefor, no need for volatile.
>
> If you were to have a variable and you accessed it while the mutex is
> not locked, even if the variable is volatile, the code is not
> thread-safe anymore. Therefor, no need for volatile.
>
> However, after reading Ron's post, I am quite confused.
> And Ron, I think you are quite right.

Let's summarize, then, what we know. While it's incorrect to access a
shared variable without synchronization, it's equally incorrect to
access one without, er, insuring the variable's unity. Without volatile,
different threads may see different pictures of your variable (it lacks
"unity"), much as if you had failed to use proper synchronization. I
think my previous example illustrated this.

> However, there is (I think) a way to avoid use of volatile. All the
> thread-safe code should be embodied in a block, and an automatic Lock/

> Unlock resource class should exist (mostly like LockingPtr class
> presented in the article), like this: {
> CAutoLockUnlockResource locker(mutex);
> // ... thread safe code
> }
> In this case you are guaranteed that any possibly cached variables are
> written into memory.

Not really. Even if the Standard required automatics to be written to
memory at block exit (and I don't believe it does), that would
accomplish little. Unless you do something odd, automatics have only
thread scope; they aren't shared between threads at all. Furthermore,
the Standard certainly does not require that objects pointed to by
automatics be written to memory at block exit, nor does it require that
member variables or globals be so written.

-- Ron

Francis Glassborow

unread,
May 30, 2002, 11:18:52 AM5/30/02
to
In article <23b84d65.02052...@posting.google.com>, Allan W
<All...@my-dejanews.com> writes

>sbea...@cs.uic.edu (Shane Beasley) wrote
> > "Read-only" doesn't mean "never changes"; that would be useless. :)
>
>Literals are read-only, and they never change during the course of
>execution.
>
>AFAIK, all computers today come with ROMS. For instance, PC's come with

>a BIOS in ROM. This is read-only, and never changes.

Well, that has not been true of BIOSs for a very long time. However the
real point is that if storage is immutable then it is necessarily read
only, but being read only does not make something immutable. We actually

do not have a mechanism in C++ for marking something as physically
immutable, only conceptually so.


--
Francis Glassborow ACCU
64 Southfield Rd
Oxford OX4 1PA +44(0)1865 246490
All opinions are mine and do not represent those of any organisation

Reply all
Reply to author
Forward
0 new messages