Are 'boolean' variables thread-safe for reading and writing from any thread? I've seen some newsgroup references to say that they are. Are any other data types available? (Enumerated types, short ints perhaps?)
It would be nice to have a list of all data types that can be safely read from any thread and another list that can also be safely written to in any thread without having to resort to various synchronization methods.
This is not a question of data types being thread-safe, but it is a question of what you do with them. Without locking no operation is thread-safe that involves loading a value, then changing it, then writing it back: incrementing or decrementing a number, clearing or setting an element in a set - they are all not thread-safe.
There is a number of functions that allow for atomic operations: interlocked increment, interlocked decrement, and interlocked exchange. This is a common concept, nothing specific to Windows, x86 or Delphi. For Delphi you can use the InterlockedFoo() functions of the Windows API, there are several wrappers around those too. Or write your own. The functions operate on integers, so you can have atomic increment, decrement and exchange of integers (32 bit) with them.
You can also use assembler and prefix ops with the lock prefix.
For more information see also this StackOverflow question.
With multi-core RISC processing and separate core cache memory being in the mix of a modern processor, it is no-longer the case that any 'trivial' high-level language read or write construct (or for that matter many once-upon-a-time 8086 'atomic' assembly instructions) can be considered atomic. Indeed, unless an assembler instruction is specifically designed to be atomic, it probably is not atomic - and that includes most mechanisms for memory reads. Even a long integer read at assembler level can be corrupted by a simultaneous write from another processor core that is sharing the same memory and using asynchronous cache update actions at the RISC-processor level. Remember that on a processor comprising multiple RISC cores, even assembly language instructions are effectively just "higher-level" code instructions! You never really know just how they are being implemented at the bit level, and it might not be quite what you expected if you were reading an old 8086 (single-core) assembler manual. Windows does provide native-system compatible atomic operators, and you would be well advised to use these rather than make any base assumptions about atomic operations.
Why use the Windows operators? Because one of the first things that Windows does is establish what the machine is that it is running upon. One of the key aspects it ensures it gets right is what atomic operations there are and how they will work. If you want your code to work well into the future upon any future processor, you can either duplicate (and constantly update) all this effort in your own code, or you can make use of the fact that Windows did it all already at startup. It then incorporated the necessary code into its API at runtime.
Read the MSDN pages on atomic operations. The Windows API surfaces these for you. They may sometimes seem clunky or clumsy - but they are future proof and they will always work exactly as it says on the tin.
How do I know this? Well, because if they didn't - then you wouldn't be able to run Windows. Full-stop. Never mind running your own code.
Whenever you write code, it is always a good idea to understand Parsimony and consider Occam's razor. In other words, if Windows already does it, and your code needs Windows to run, then use what Windows already does, rather than trying out many alternative and increasingly complex hypothetical solutions that may or may not work. Doing anything else is just a waste of your time (unless of course that is what you are in to).
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