It seems that this question gets asked frequently, but I am not coming to any definitive conclusion. I need a little help on determining whether or not I should (or must!) implement locking code when accessing/modifying global variables when I have:
- global variables defined at file scope
- a single "worker" thread reading/writing to global variables
- calls from the main process thread calling accessor functions which return these globals
So the question is, should I be locking access to my global variables with mutexes?
More specifically, I am writing a C++ library which uses a webcam to track objects on a page of paper -- computer vision is CPU intensive, so performance is critical. I have a single worker thread which is spun off in an Open()
function. This thread handles all of the object tracking. It is terminated (indirectly w/global flag) when a Close()
function is called.
It feels like I'm just asking for memory corruption, but I have observed no deadlock issues nor have I experienced any bad values returned from these accessor functions. And after several hours of research, the general impression I get is, "Meh, probably. Whatever. Have fun with that." If I indeed should be using mutexes, why I have not experienced any problems yet?
Here is an over-simplification on my current program:
// *********** lib.h ***********
// Structure definitions
struct Pointer
{
int x, y;
};
// more...
// API functions
Pointer GetPointer();
void Start();
void Stop();
// more...
The implementation looks like this...
// *********** lib.cpp ***********
// Globals
Pointer p1;
bool isRunning = false;
HANDLE hWorkerThread;
// more...
// API functions
Pointer GetPointer()
{
// NOTE: my current implementation is actually returning a pointer to the
// global object in memory, not a copy of it, like below...
// Return copy of pointer data
return p1;
}
// more "getters"...
void Open()
{
// Create worker thread -- continues until Close() is called by API user
hWorkerThread = CreateThread(NULL, 0, DoWork, NULL, 0, NULL);
}
void Close()
{
isRunning = false;
// Wait for the thread to close nicely or else you WILL get nasty
// deadlock issues on close
WaitForSingleObject(hWorkerThread, INFINITE);
}
DWORD WINAPI DoWork(LPVOID lpParam)
{
while (isRunning)
{
// do work, including updating 'p1' about 10 times per sec
}
return 0;
}
Finally, this code is being called from an external executable. Something like this (pseudocode):
// *********** main.cpp ***********
int main()
{
Open();
while ( <esc not pressed> )
{
Pointer p = GetPointer();
<wait 50ms or so>
}
Close();
}
Is there perhaps a different approach I should be taking? This non-issue issue is driving me nuts today :-/ I need to ensure this library is stable and returning accurate values. Any insight would be greatly appreciated.
Thanks