I would like to confirm here if I understood correctly how TCriticalSection
and Synchronize
operate.
As far as I know right now Synchronize
uses SendMessage
(update: or at least used it in older VCL versions as mentioned in couple of comments below) which suspends currently executing thread (as well as any other thread) unlike PostMessage
which doesn't and then executes required function (from main thread). In a way SendMessage
"stops" multithreading when executing.
But I am not sure about TCriticalSection
. Let's say for example I create something like this:
// Global variables somewhere in my code any thread can access
boost::scoped_ptr<TCriticalSection> ProtectMyVarAndCallFnction(new TCriticalSection);
int MyVariable1;
void CallMyFunctionThatAlsoModifiesMoreStuff() { /* do even more here */ };
// Thread code within one of the threads
try {
ProtectMyVarAndCallFnction->Acquire();
MyVariable1++;
CallMyFunctionThatAlsoModifiesMoreStuff();
}
__finally {
ProtectMyVarAndCallFnction->Release();
}
Now, my question is - how the critical section "knows" that I am protecting MyVariable1 in this case as well as whatever the called function may modify?
If I understood it correctly - it doesn't - and it is my responsibility to correctly call Acquire() in any thread wants to change MyVariable1 or call this function (or do any of the two). In other words I think of TCriticalSection
as user-defined block which defines whatever logically I assigned to it. It may be a set of variables or any particular function as long as I call Acquire() within all of the threads that might write to this block or use this function. For example "DiskOp" may be my name of TCriticalSection
that writes on disk, "Internet" may be the name of TCriticalSection
that calls functions that retrieve some data from the Internet. Did I get it correctly?
Also, within this context, does TCriticalSection therefore always needs to be a global kind of variable?
SendMessage suspends currently executing thread (as well as any other thread).
No, that is incorrect. SendMessage
does not suspend anything. SendMessage merely delivers a message synchronously. The function does not return until the message has been delivered. That is, the window proc of the target window has been executed. And because the window proc is always called on the thread that owns the window, this means that the calling thread may need to be blocked to wait until the window's owning thread is ready to execute the window proc. It most definitely doesn't suspend all threads in the process.
How does the critical section know that I am protecting
MyVariable1
?
It doesn't. It's entirely up to you to make sure that all uses of MyVariable1
that need protection, are given protection. A critical section is a form of mutex. A mutex ensures that only one thread of execution can hold the mutex any any instant in time.
As I call
Acquire()
within all of the threads that might write to this block or use this function.
That's not really it either. The "within all of the threads" is a mis-think. You need to be thinking about "at all sections of code that use the variable".
Does a critical section therefore always need to be a global kind of variable?
No, a critical section can be a global variable. But it need not be.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With