Domanda

For example if I have the following code:

SomeType obj;  

void GUIThread()  
{  
    ...  
    while (true)  
        // Read and print the content of obj  
    ...  
}  

void workerThread()  
{  
    ...  
    // Do some calculation and write the result into obj  
    ...  
}  

For performance reasons, I can't afford to use mutex or anything alike on obj, and I don't need exact accuracy of what GUIThread prints (obj stores the running computation results of workerThread, which can be considered as a "running total". What GUIThread needs to do is just to show the approximate progress of the calculation being done in workerThread). What I want to make sure is that the read-write race condition between GUIThread and workerThread doesn't alter the data stored in obj, and won't cause the program to crash. Is that true?

P.S. SomeType contains built-in integer types and a std::bitset<T>, but only the former will be accessed simultaneously. The bitset remains untouched by GUIThread.

P.P.S. Maybe this is a little bit out of the topic...but I think I can store the running results in a cache in workerThread, and only update the actually protected (either by atomicity or mutex locking or whatever) every relatively long time period. To achieve this, I need to make sure that if the following code will work as intended:

struct SomeOtherType  
{  
    int a, b, c, d;  // And other primitive types  
}  

std::atomic<SomeOtherType> data;  // Will this work?  

I wonder if this can protect SomeOtherType, and I think it can since there are only primitive types in SomeOtherType.

È stato utile?

Soluzione 2

As far as I understand, you structure looks like this

struct Data {
    int one;
    int two;
    std::bitset<SomeType> three;
}

If you don't want to use any kind of lock for it, you can try to swap a shared pointer to this structure. Check if your compiler supports it, it's a new feature.

std::shared_ptr<Data> dataPointer;

void GUIThread()  
{  
    ...  
    while (true)  {
       auto ptr = std::atomic_load(&dataPointer);
       // Read and print the content of *ptr
    ...  
}  

void workerThread()  
{  
    ...  
   // Do some calculation
   auto newPtr = std::make_shared<Data>();
   // make the new result visible to the gui thread
   std::atomic_store(&dataPointer, newPtr);
}

Altri suggerimenti

What you are saying is "I am writing code with undefined behavior. Will it do what I want anyway?". The only answer is nobody knows except possible of the compiler writer.

It seems likely your code will do what you want because it seems the simplest way to implement the compiler. But it might well decide that nothing outside of your loop can be writing to that variable because if it did it would be a data race and therefore the standard says nothing about what it will do and then decide to replace the variable by a constant in that part of the program as it can't change and re-use that memory to store the value of another pointer in so your other thread will set a completely unconnected value to null and crash your program an hour later. It's unlikely of course but I can see how it could happen.

Undefined behavior is just that - undefined. It literally could do anything. Some things are clearly more likely than others but do you really want to risk formatting your user's disk because you thought "undefined" didn't apply to your program, no matter how small the risk appeared to be?

Depending heavily on the shared data type. What can happen in a complex data type is that during a write operation, the object becomes invalid briefly (e.g. allocates a new internal buffer).

For simple data types, such as integers, floats, etc. the code will not crash on most cases but w/o guaranties!. These should be declared as volatile to avoid the compiler caching them in a register. Forcing a memory barrier will improve your result accuracy.

If you're just checking a Boolean flag or something similar, you can get away with.

If obj is thread safe, then you're OK too.

My suggestion, when in doubt, use a low overhead lock such as spinlocks.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top