By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,033 Members | 1,020 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,033 IT Pros & Developers. It's quick & easy.

Is assignment to C++ int and pointer variables atomic?

P: n/a
Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

I have a multi-threaded Windows application in which certain
variables/object fields are shared: one thread may write the variable,
and the other thread read it. The variables in question may have int or
int* types. Question: Is it safe to do this? Or is it possible a read
that happens at the same time as a write may retrieve a scrambled value,
in which, say, two of the bytes are from the old value and two of the
bytes from the new value?

In Java I know that such atomicity is guaranteed for ints, but not for
longs or doubles. So, perhaps I shouldn't assume it in a less
well-standardized environment

The application, btw, is a circular buffer with a read pointer and a
write pointer, which are moved forward by their respective threads. The
read thread needs to check to make sure that the read pointer is not on
the write pointer before reading. Using mutexes right now, but I worry
about their overhead...

Dave

Jan 3 '07 #1
Share this Question
Share on Google+
9 Replies


P: n/a
Dave Stallard wrote:
Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.
It's beyond the scope. The Standard doesn't specify threading behavior,
therefore any answer is implementation specific. You might want to ask
in a newsgroup dedicated to your platform.

http://www.parashift.com/c++-faq-lit...t.html#faq-5.9

That said, I believe int is defined as the native integral type for an
implementation. So it *could* most likely be atomic. But then there's
alignment issues.

So the answer is "it depends, and check your compiler documentation".

Sorry we can't be more help.
Jan 3 '07 #2

P: n/a

red floyd wrote:
That said, I believe int is defined as the native integral type for an
implementation. So it *could* most likely be atomic. But then there's
alignment issues.

While int *could* be atomic on a given platform, it is certainly not
required. Consider, for example, an implementation of C on a typical
8-bit CPU - all ints will have to be accessed with a pair of loads or
stores.

Jan 3 '07 #3

P: n/a
Dave Stallard wrote:
Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

I have a multi-threaded Windows application in which certain
variables/object fields are shared: one thread may write the variable,
and the other thread read it. The variables in question may have int or
int* types. Question: Is it safe to do this? Or is it possible a read
that happens at the same time as a write may retrieve a scrambled value,
in which, say, two of the bytes are from the old value and two of the
bytes from the new value?

In Java I know that such atomicity is guaranteed for ints, but not for
longs or doubles. So, perhaps I shouldn't assume it in a less
well-standardized environment

The application, btw, is a circular buffer with a read pointer and a
write pointer, which are moved forward by their respective threads. The
read thread needs to check to make sure that the read pointer is not on
the write pointer before reading. Using mutexes right now, but I worry
about their overhead...

Dave
As others have mentioned, C++ doesn't make any such guarantees.
However, since you mention you are running on Windows, you might look up
the InterlockedExchange, InterlockedExhangePointer,
InterlockedCompareExchange, etc. They can give you some guarantees at
the cost of portability between OSes.

See http://msdn2.microsoft.com/en-us/library/ms686360.aspx for details.

--
Alan Johnson
Jan 3 '07 #4

P: n/a

Note that I have added comp.programming.threads to this post.

Dave Stallard wrote:
Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

I have a multi-threaded Windows application in which certain
variables/object fields are shared: one thread may write the variable,
and the other thread read it. The variables in question may have int or
int* types. Question: Is it safe to do this? Or is it possible a read
that happens at the same time as a write may retrieve a scrambled value,
in which, say, two of the bytes are from the old value and two of the
bytes from the new value?

comp.programming.threads is probably the right place to ask such questions.

Sharing variables like this depends on "visibility". Modern CPU's
heavily depend on cache and out of order execution for performance.
Normally, these effects are undetectable in a single threaded program
but they become critical when you're dealing with multi-threaded code.

So, once, a long long time ago if you wrote :

char ring_buffer[1024];
int wloc;
int rloc;

....writer...
ring_buffer[wloc] = ch; // S1
++wloc; // S2

....reader...
if ( wloc rloc )
{
val = ring_buffer[rloc]; //S3
++rloc; //S4
}

you could be guarenteed that effects of S1 would be visible before S2 to
the other thread. This is not the case now. S2 MAY be visible before
S1 which means that S3 may not see the value in "ch".

There are two reasons this may happen, one is the hardware (CPU) and the
other is the optimizing compiler using the volatile keyword. The second
is to make sure that the hardware compiles. This is totally hardware
dependant - no standard exists yet.

First thing to do is tell the compiler to not mess with the order:

volatile char ring_buffer[1024];
volatile int wloc;
volatile int rloc;

....writer...
ring_buffer[wloc] = ch; // S1
FENCE(); // make sure that S1 is visible
++wloc; // S2

....reader...
FENCE(); // make sure we see everything first
if ( wloc rloc )
{
val = ring_buffer[rloc]; //S3
++rloc; //S4
}

An excellent paper on the issues involved in standardizing a solution:
http://www.hpl.hp.com/techreports/20...-2004-209.html

Wikipedia gives an excellent high level perspective.
http://en.wikipedia.org/wiki/Memory_barrier

So, most code uses mutexes and these generally guarentee a memory
barrier, so if you use mutexes, you don't run into sequencing issues,
however they can be a significant performance hit. Having said that,
many and quite probably most applications will never need to worry about
the performance hit of mutexes.
>
In Java I know that such atomicity is guaranteed for ints, but not for
longs or doubles. So, perhaps I shouldn't assume it in a less
well-standardized environment

The application, btw, is a circular buffer with a read pointer and a
write pointer, which are moved forward by their respective threads. The
read thread needs to check to make sure that the read pointer is not on
the write pointer before reading. Using mutexes right now, but I worry
about their overhead...

Dave
Jan 3 '07 #5

P: n/a
red floyd wrote:
Dave Stallard wrote:
>Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

It's beyond the scope. The Standard doesn't specify threading behavior,
therefore any answer is implementation specific. You might want to ask
in a newsgroup dedicated to your platform.

http://www.parashift.com/c++-faq-lit...t.html#faq-5.9

That said, I believe int is defined as the native integral type for an
implementation. So it *could* most likely be atomic. But then there's
alignment issues.
Another thing that you probably need to worry about are caches on a
multiprocessor/multicore system. If you write an int in one thread, even
after the write operation is finished, the other thread might still see the
old value if it runs on the other CPU core because the change hasn't
propagated from one cache through RAM into the other cache.

Jan 3 '07 #6

P: n/a
On 2007-01-03 05:54, Dave Stallard wrote:
Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

I have a multi-threaded Windows application in which certain
variables/object fields are shared: one thread may write the variable,
and the other thread read it. The variables in question may have int or
int* types. Question: Is it safe to do this? Or is it possible a read
that happens at the same time as a write may retrieve a scrambled value,
in which, say, two of the bytes are from the old value and two of the
bytes from the new value?
I can give you no guarantees but I'm sure it's quite safe to assume that
both reading and writing to an int (getting and setting its value) is
atomic. That, however, have very few applications, only when one thread
is writing only and the other thread is reading only. In most practical
applications you'll what to have a thread to first read the value, then
perhaps perform some check and then modify the value and write the
modified value back. These kinds of operations are not atomic on any
platform that I know about* not even in Java. The problem being that the
value can change between the read of the value and the write of the
modified value. To solve these issues you'll need to call syncronization
functions that are platform-specific.

* There are some architectures that supports a few selected atomic
operations, like compare and swap or compare and add.

--
Erik Wikström
Jan 3 '07 #7

P: n/a
"Gianni Mariani" <gi*******@mariani.wswrote in message
news:45**********************@per-qv1-newsreader-01.iinet.net.au...
>
Note that I have added comp.programming.threads to this post.

Dave Stallard wrote:
>Pardon if this is the wrong newsgroup for this question, and/or if this
question is naive.

I have a multi-threaded Windows application in which certain
variables/object fields are shared: one thread may write the variable,
and the other thread read it. The variables in question may have int or
int* types. Question: Is it safe to do this? Or is it possible a read
that happens at the same time as a write may retrieve a scrambled value,
in which, say, two of the bytes are from the old value and two of the
bytes from the new value?


comp.programming.threads is probably the right place to ask such
questions.

Sharing variables like this depends on "visibility". Modern CPU's heavily
depend on cache and out of order execution for performance. Normally,
these effects are undetectable in a single threaded program but they
become critical when you're dealing with multi-threaded code.
http://appcore.home.comcast.net/vzdo...c/static-init/
(section 2 deals with some of the issues involved)
Jan 4 '07 #8

P: n/a
http://appcore.home.comcast.net/vzdo...c/static-init/
(section 2 deals with some of the issues involved)
read this as well:

http://groups-beta.google.com/group/...3df394a0370fa6
Jan 4 '07 #9

P: n/a
Gianni Mariani wrote:
An excellent paper on the issues involved in standardizing a solution:
http://www.hpl.hp.com/techreports/20...-2004-209.html

Wikipedia gives an excellent high level perspective.
http://en.wikipedia.org/wiki/Memory_barrier

So, most code uses mutexes and these generally guarentee a memory
barrier, so if you use mutexes, you don't run into sequencing issues,
however they can be a significant performance hit. Having said that,
many and quite probably most applications will never need to worry about
the performance hit of mutexes.
Thanks, Gianni, for your very informative response, and thank you
everyone else who answered. I've taken my lesson, and will lock, lock,
lock in the future.

Dave
Jan 5 '07 #10

This discussion thread is closed

Replies have been disabled for this discussion.