Click here to Skip to main content
15,882,329 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm new to building apps in MFC/VS/VC++.

I've spent a great deal of time reading SO and it's disconcerting as they assert the MSDN documentation is flat-out wrong as to the (lack of) thread-safety of Microsoft constructs including volatile variables and tools such as InterlockedIncrement. I have an application I am developing where one thread generates a list of tasks to be performed, storing these in a structure, while other threads poll to perform these tasks as they become prompt and appropriate. The logic of the code would appear naively to preclude race conditions, as functions are called which change the global variables/structure before other functions are called which use them. Of course, the compiler (VS2003 for me) can compile in a way where the calling thread may not re-check the value of the global variable each time, so it may not see the updated values. The function "InterlockedIncrement" was built for applications as mine, and I use it to increment and decrement the count of the number of tasks in the list, so each worker thread knows how many tasks are in the list to be scanned. But the tasks are relatively complex structures being modified by the task-building thread, and are subject to "invalidation" (and disaster for me) if a worker thread were to read one only partly completed.

Which simple strategies are best for the relatively simple application where only one thread is making changes to shared structures while many other threads read these?
Updated 29-Oct-14 4:08am

Share this answer
NoBizness 28-Oct-14 7:34am    
Thank you very much. I will leave my question open for a bit hoping for a snippet or two of C++ code illustrating the technique.
Just from a short read through your description the first thing I'd suggest is NOT to use global variables when multi-threading. When you start a new thread one of the things you can pass to it is a pointer to a structure. This structure should contain all of the thread instance variables that the thread needs to do its job.

If you absolutely need to have global variables, use a critical section or a mutex to block simultaneous access to shared variables. Critical sections are faster but mutexes are more widely supported across platforms.

Boost has mutexes that are easier and safer to use but then you have a boost dependency. Boost offers mutexes that can lock/unlock upon construction/destruction. They are safer because they will always unlock when a part of the code that locks a mutex goes out of scope (i.e. you don't have to hit that line of code that specifically unlocks, important for exception handling).
Share this answer
nv3 28-Oct-14 14:23pm    
My 5.
Albert Holguin 28-Oct-14 15:12pm    
NoBizness 29-Oct-14 4:12am    

How is it different to pass a pointer to a structure as opposed to making reference to the structure by name within? I'm very confused. I apologize. You wrote your answer so well perhaps you can give me a few more words to go by in pursuing this.
Albert Holguin 29-Oct-14 9:25am    
Not sure what you're asking... the important thing to realize when you're creating a data structure to pass on to the thread is that while that thread is running, NO OTHER THREAD touches those variables until that thread is done with them.
NoBizness 29-Oct-14 10:04am    
Yes, agreed. Thanks.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900