Say I have code like this...

typedef struct {
    unsigned A:1;
    unsigned B:1;
} FlagStruct;
extern FlagStruct *Flags;

Imagine that the Flags instance is a shared resource in a multi-threaded application. Say thread #1 decides to read the value of Flags->A but thread #2 decides to set or clear Flag->B at the exact same time. How isolated is Flag->A from Flag->B such that any changes to Flag->B does not affect the value of Flag->A? In other words, are set or clear operations in this structure atomic and therefore thread safe?

Recommended Answers

All 4 Replies

I wouldn't assume so, no. There's nothing in the standard specifying atomicity, for that or (AFAIK) anything else in C. Even if it is an atomic operation on a specific processor and with a specific compiler, it is not certain to be on others. To the best of my knowledge, there is no portable way to write any form of mutual exclusion entirely in C, or any other language for that matter (while some languages have built-in support or library support for mutex primitives, that sort of thing relies on low-level access to the processor by the language translator and/or the library writer).

In any case, the likelihood of it being implemented in an atomic fashion is very low. In the scenario you describe, it would (on any processors I know of) in the general case take at least three steps to perform: a pointer dereference, a bit set operation (probably AND), and a store back to the dereferenced memory location.

While the x86 architecture has some instructions that are guaranteed to be atomic (with the LOCK modifier), there is no (portable and reliable) way to ensure that the compiler will use them.

The practical upshot of this is, no, that isn't going to be atomic without blocking, and on a modern multicore/multiprocessor system, without memory bus locking as well.

Thats what I thought too which is why I've been naturally avoiding using them in that way, but it would have been so convinient and elegant if it did. Thus is life in the world of the compiled.

Why make assumptions that may or may not be valid? Just do it the safe way and use a semaphore to synchronize access to the byte that contains those bits.

I didn't make any assumptions. I was always avoiding using flags in the way I described but decided today to ask what you guys thought about it purely out of curiousity.

In my applications I tend to use mutex locking as a multi-threaded resource protection mechanism.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.