How to use std::atomic<bool> without compiler error?

Hi -- I'm setting up a wifi event callback and in the callback function I'd like to set a state boolean to represent the connection having been lost.

My understanding is that this callback will come from a different thread and that therefore it will be wise to use a threadsafe boolean to communicate this to my main thread.

I'm using VSCode / PlatformIO on an ESP32 with the Arduino framework.

Rather than deal with mutex regions and so forth, I found std::atomic which sounded like just the ticket, but I can't seem to get the compiler to accept it:

std::atomic<bool> my_boolean;

always gets:

error: variable 'std::atomic<bool> my_boolean' has initializer but incomplete type

I've tried a variety of different syntaxes to declare or define the variable with no luck. Tried #include <atomic>, no luck.

Am I just having bad luck finding the right syntactic example somewhere, or is this an issue of the compiler using an old version of c++? (I thought it was using gnu++11 which I thought meant it would know std::atomic...) If so, what's the simplest way to make a threadsafe boolean switch?

Thanks!

Argh, disregard: buggy IDE was flagging it as wrong when it was right. I know better than to trust the red squiggly lines, but it got me again. :slight_smile:

if you're using your atomic bool inside of an ISR - ensure it's lock free

Thanks -- I was trying to research what you were referring to but I got a little lost... I see that in C++20 they have std::atomic_unsigned_lock_free but that doesn't appear to be available to me (C++11 standard I think is in play for me I believe.) Is your recommendation because I want to be maximally efficient in an ISR, or is there another motivation?

Oh, or do you mean I should use std::atomic_flag ?

I meant that it is designed to be thread-safe without relying on traditional locks or mutexes (lock-free design).

See also std::atomic<T>::is_lock_free - cppreference.com

Thanks! And the reason I want lock-free is: efficiency in the ISR? Or is there some risk of a subtle issue if I use a boolean that is not lock free? I would think that if I am just assigning or using the bool (.store/.load) then there wouldn't be any risk?

Oh I think I get it... deadlock because the program thread gets the mutex, but then it's interrupted by the ISR which tries to get the mutex and hangs... right?

If my atomic_bool is not lock-free, what's the better way to sync between ISR and main thread?

You got it

See ESP-IDF FreeRTOS SMP Changes - ESP32 - β€” ESP-IDF Programming Guide v4.3.2 documentation.

Mmmkay having read up on this a bit, here's what I've learned regarding atomic modification of regular variables, in case anyone else finds this thread:

  • if I'm modifying volatile variables that are <= the bit size of the processor, they are likely safe atomic updates, but might be smart not to rely on that
  • cli(); my_bool=true; sei(); is one good approach
    • keep the section enclosed to an absolute minimum
    • single ISRs that happen while cli() are deferred, not skipped, but if >1 trigger happens during the enclosed section, only the last one will fire an ISR (i.e. others are indeed skipped)
  • variable must be marked volatile whether using cli/sei or not
  • ATOMIC_BLOCK macro (and related) exists for convenience

I found this useful.

Thanks for the assistance!