Can threads safely read variables set by VCL events?

Is it safe for the thread to READ the variable set by the Delphi VCL event?

When a user clicks on the TCheckbox VCL, the main thread sets a boolean value in the Checked Checked field.

CheckboxState := CheckBox1.Checked; 

At any time, the thread reads this variable.

 if CheckBoxState then ... 

It doesn’t matter if a thread “skips” a logical change, because the thread checks the variable in the loop, like other things. So he will see a change in state eventually ...

It is safe? Or do I need a special code? Is the surrounding read and write variable (in the stream and main stream, respectively) with the necessary and sufficient code calls?

As I said, it doesn’t matter if the thread gets the “wrong” value, but I keep thinking that there might be a low level problem if one thread tries to read the variable while the main thread is in the middle of writing or vice versa .

My question is like this: Cross-reading a variable whose value is not considered important .

(Also relevant to my previous question: Using EnterCriticalSection in a stream to update VCL label )

+5
source share
3 answers

This is safe for three reasons:

  • Only one stream is written to the variable.

  • A variable is only one byte, so there is no way to read an inconsistent value. It will be read as True or False . There can be no alignment problems with Delphi boolean values.

  • The Delphi compiler does not conduct detailed checks to see if a variable is written and does not "optimize" any code if not. Non-local variables will always be read; there is no need for a volatile specifier.

Having said that, if you are really not sure about this, you can use the integer value instead of the boolean and use InterlockedExchange() to write to the variable. This is an abundance here, but it is a good technique to be aware of, because for the meanings of a single machine word, this can eliminate the need for locks.

You can also replace boolean with the correct synchronization primitive, for example, an event, and have a thread block on this - this will help you eliminate busy cycles in the thread.

+6
source

In your case (a verified property), the read operation is atomic, so it is safe. This is the same as the TThread.Terminated property; simple read and write operations for correctly aligned bytes, words, and double words are atomic. You can check Intel documentation for more information:

CHAPTER 8 - MANAGEMENT OF MULTIPLE PROCESSOR

8.1.1 Guaranteed atomic operations

The Intel486 processor (and newer processors since) guarantees that the following main memory operations will always be performed atomically:

  • Read or write byte
  • Reading or writing a word aligned on a 16-bit boundary
  • Reading or writing a double word aligned on a 32-bit boundary

The Pentium processor (and newer processors since) ensures that the following additional memory operations are always performed atomically:

  • Reading or writing a quad word aligned on a 64-bit boundary
  • 16-bit access to undisclosed memory locations that fit on a 32-bit data bus
+3
source

For the example you give, it will be safe. Technically, the main problem is in cases where your variable is processed by a machine word in size, and thus you can get an incompatible word of high and long words. However, for small values ​​this is not a problem.

If you think this is a potential problem, for example, using a pointer, then use the TCriticalSection to use the read and write function of the element. It is fast enough for all practical situations and ensures that you are 100% safe.

+1
source

All Articles