0

I'm writing simple cycle code which needs check simple custom thread lock, and when this lock is passed thread will continue

static bool* lock;
...
while (*lock);
// TODO: process to the next step
...

but when I'm checking compiled assembly I see the next code

static bool* lock;
...
bool lock_value = *lock;
while (lock_value);
// TODO: process to the next step
...

which means the thread will be stuck on the check cycle in the case initially *lock == false;

Question. Lets say this is not thread lock, it's some other thing: color, price etc. So how I can force check this pointer value. Of course, I can handle this by inline assembly

__asm {
    lbl_back:
    mov ecx, lock
    mov eax, [ecx]
    test eax, eax
    jnz lbl_back
}

But how I can do this by C/C++ owns, without std and without external things? Just clear C/C++ language syntax

Thanks to all. volatile is my choice

Verok
  • 13
  • 1
  • 4
  • Are you trying to signal another thread that there is work to do? If you're just interested in signaling I would suggest you use an `std::condition_variable` instead (assuming I've understood you correctly) – WBuck Jun 17 '20 at 01:07
  • Unfortunately, there is no such thing as a "simple custom thread lock". Proper multi-thread synchronization requires the usage of `std::mutex` and `std::condition_variable`s. There's also the `std::atomic` fan club, too, although it's been my experience that their pepetual pursuit of a lock-free synchronization fairy rarely results in proper usage of `std::atomic` resulting in sporadic race conditions that conclude with hard to reproduce bugs, and premature hair loss. You'll do yourself a favor if you simply use `std::mutex` and `std::condition_variable`s, as the gods of C++ want you to. – Sam Varshavchik Jun 17 '20 at 01:07

1 Answers1

1

Short answer: infinite loops without side-effects are Undefined Behaviour. This makes your code formally meaningless, and the compiler is free to assume that Undefined Behaviour never happens. Since while (*lock); is a simply reading a scalar and causing no side-effects, this causes UB, so the compiler goes ahead and does what it wants. It is also Undefined Behaviour to have multiple threads reading and writing the same memory location without extra safety precautions, which I assume is what you are doing in the rest of your code.

Long answer: this "simple custom thread lock" does not work. The idea is nearly correct, but to actually prevent race conditions, you need something more than simple booleans. You should look into synchronization primitives like std::atomic, std::mutex, std::lock_guard, std::condition_variable, semaphores, or higher level asynchronous tools like std::future.

alter_igel
  • 6,899
  • 3
  • 21
  • 40
  • 1
    @Verok I did not mention volatile. You should not use volatile for inter-thread communication because it was not designed for that, will not prevent race conditions, and dropping it into your code will still cause Undefined Behaviour. [docs](https://en.cppreference.com/w/cpp/language/cv). – alter_igel Jun 17 '20 at 01:53
  • but it's working for me for now and generates the same x86 code as I'm expecting – Verok Jun 17 '20 at 02:09
  • @Verok [Why is volatile not considered useful in multithreaded C or C++ programming?](https://stackoverflow.com/questions/2484980/why-is-volatile-not-considered-useful-in-multithreaded-c-or-c-programming). – dxiv Jun 17 '20 at 02:15
  • thanks for the info. But I don't need thread safe, I just need the same assembly code generated as in the main post – Verok Jun 17 '20 at 02:27