Interoperabilty between C and C++ atomics












10















Suppose, I have a task that might be cancelled from another thread. The task is performed in a C function, another thread runs C++ code. How do I do that?



Rough example.



C:



void do_task(atomic_bool const *cancelled);


C++:



std::atomic_bool cancelled;

do_task(&cancelled);


For now, I created a file atomics.h with the following content:



#ifdef __cplusplus
#include <atomic>
using std::atomic_bool;
#else
#include <stdatomic.h>
#endif


It appears to work, but I don't see any guarantees for that. I wonder, if there is a better (correct) way.










share|improve this question























  • for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

    – RbMm
    Dec 22 '18 at 21:47













  • really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

    – RbMm
    Dec 22 '18 at 21:56













  • @RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

    – R..
    Dec 23 '18 at 8:14













  • @R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

    – RbMm
    Dec 23 '18 at 8:37











  • @RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

    – phön
    Dec 23 '18 at 9:32
















10















Suppose, I have a task that might be cancelled from another thread. The task is performed in a C function, another thread runs C++ code. How do I do that?



Rough example.



C:



void do_task(atomic_bool const *cancelled);


C++:



std::atomic_bool cancelled;

do_task(&cancelled);


For now, I created a file atomics.h with the following content:



#ifdef __cplusplus
#include <atomic>
using std::atomic_bool;
#else
#include <stdatomic.h>
#endif


It appears to work, but I don't see any guarantees for that. I wonder, if there is a better (correct) way.










share|improve this question























  • for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

    – RbMm
    Dec 22 '18 at 21:47













  • really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

    – RbMm
    Dec 22 '18 at 21:56













  • @RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

    – R..
    Dec 23 '18 at 8:14













  • @R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

    – RbMm
    Dec 23 '18 at 8:37











  • @RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

    – phön
    Dec 23 '18 at 9:32














10












10








10


1






Suppose, I have a task that might be cancelled from another thread. The task is performed in a C function, another thread runs C++ code. How do I do that?



Rough example.



C:



void do_task(atomic_bool const *cancelled);


C++:



std::atomic_bool cancelled;

do_task(&cancelled);


For now, I created a file atomics.h with the following content:



#ifdef __cplusplus
#include <atomic>
using std::atomic_bool;
#else
#include <stdatomic.h>
#endif


It appears to work, but I don't see any guarantees for that. I wonder, if there is a better (correct) way.










share|improve this question














Suppose, I have a task that might be cancelled from another thread. The task is performed in a C function, another thread runs C++ code. How do I do that?



Rough example.



C:



void do_task(atomic_bool const *cancelled);


C++:



std::atomic_bool cancelled;

do_task(&cancelled);


For now, I created a file atomics.h with the following content:



#ifdef __cplusplus
#include <atomic>
using std::atomic_bool;
#else
#include <stdatomic.h>
#endif


It appears to work, but I don't see any guarantees for that. I wonder, if there is a better (correct) way.







c++ c atomic






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked Dec 22 '18 at 18:50









grepcakegrepcake

6681520




6681520













  • for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

    – RbMm
    Dec 22 '18 at 21:47













  • really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

    – RbMm
    Dec 22 '18 at 21:56













  • @RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

    – R..
    Dec 23 '18 at 8:14













  • @R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

    – RbMm
    Dec 23 '18 at 8:37











  • @RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

    – phön
    Dec 23 '18 at 9:32



















  • for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

    – RbMm
    Dec 22 '18 at 21:47













  • really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

    – RbMm
    Dec 22 '18 at 21:56













  • @RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

    – R..
    Dec 23 '18 at 8:14













  • @R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

    – RbMm
    Dec 23 '18 at 8:37











  • @RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

    – phön
    Dec 23 '18 at 9:32

















for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

– RbMm
Dec 22 '18 at 21:47







for what you here need atomic ? which operation need to be atomic ? nothing. you here need volatile by sense, but not atomic - void do_task(volatile bool *cancelled);

– RbMm
Dec 22 '18 at 21:47















really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

– RbMm
Dec 22 '18 at 21:56







really in most case you even not need volatile if inside loop do { * } while (!*cancelled); you call some external function, for which compiler can not know - are it modify *cancelled

– RbMm
Dec 22 '18 at 21:56















@RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

– R..
Dec 23 '18 at 8:14







@RbMm: Advice to do things that might happen to work on current tooling but that is explicitly wrong and has no advantages over doing it right is not helpful.

– R..
Dec 23 '18 at 8:14















@R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

– RbMm
Dec 23 '18 at 8:37





@R.. - why this is explicitly wrong ? of course without view complete code can not exactly say are need atomic here, but how usual cancelled use - not require any atomic or memory order other than relaxed. need only volatile.

– RbMm
Dec 23 '18 at 8:37













@RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

– phön
Dec 23 '18 at 9:32





@RbMn one threads reads a variable. one thread writes it. all without further synchronization-> you need atomic. end of story.

– phön
Dec 23 '18 at 9:32












5 Answers
5






active

oldest

votes


















8














The atomic_bool type in C and the std::atomic<bool> type in C++ (typedefed as std::atomic_bool) are two different types that are unrelated. Passing a std::atomic_bool to a C function expecting C's atomic_bool is Undefined Behavior. That it works at all is a combination of luck and the simple definitions of these types being compatible.



If the C++ code needs to call a C function that expects C's atomic_bool, then that is what it must use. However, the <stdatomic.h> header does not exist in C++. You'll have to provide a way for the C++ code to call C code to get a pointer to the atomic variable you need in a way that hides the type. (Possibly declare a struct that holds the atomic bool, that C++ would only know that the type exists and only know about pointers to it.)






share|improve this answer
























  • It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

    – ALX23z
    Dec 22 '18 at 20:36






  • 1





    from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

    – Manny_Mar
    Dec 22 '18 at 23:29








  • 1





    @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

    – Lightness Races in Orbit
    Dec 23 '18 at 1:25











  • @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

    – ALX23z
    Dec 23 '18 at 2:19








  • 3





    @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

    – user2357112
    Dec 23 '18 at 2:22



















9














To side-step all ABI issues you may like to implement a C function that is called from C++ and operates on that atomic_bool. This way your C++ code doesn't need to know anything about that global variable and its type:



In an .hfile:



#ifdef __cplusplus
extern "C" {
#endif

void cancel_my_thread(void);
int is_my_thread_cancelled(void);

#ifdef __cplusplus
}
#endif


And then in a .c file:



#include <stdatomic.h>

static atomic_bool cancelled = 0;

void cancel_my_thread(void) {
atomic_store_explicit(&cancelled, 1, memory_order_relaxed);
}
int is_my_thread_cancelled(void) {
return atomic_load_explicit(&cancelled, memory_order_relaxed);
}


The C++ code would include that headed and call cancel_my_thread.






share|improve this answer


























  • Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

    – grepcake
    Dec 23 '18 at 9:13



















1














I found this on a net search https://developers.redhat.com/blog/2016/01/14/toward-a-better-use-of-c11-atomics-part-1/




Following the lead of C++, along with a memory model describing the
requirements and semantics of multithreaded programs, the C11 standard
adopted a proposal for a set of atomic types and operations into the
language. This change has made it possible to write portable
multi-threaded software that efficiently manipulates objects
indivisibly and without data races. The atomic types are fully
interoperable between the two languages so that programs can be
developed that share objects of atomic types across the language
boundary. This paper examines some of the trade-offs of the design,
points out some of its shortcomings, and outlines solutions that
simplify the use of atomic objects in both languages.




I am just learning about atomics now, but it looks like its compatible between C and CPP.






share|improve this answer





















  • 1





    Do you have a more authoritative source than "some guy's blog said it was okay"?

    – user2357112
    Dec 23 '18 at 2:16











  • If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

    – Manny_Mar
    Dec 23 '18 at 2:21





















-1














how i understand your code in general is (must be) next



// c code

void _do_task();

void do_task(volatile bool *cancelled)
{
do {
_do_task();
} while (!*cancelled);
}

// c++ code

volatile bool g_cancelled;// can be modify by another thread
do_task(&cancelled);

void some_proc()
{
//...
g_cancelled = true;
}


i be ask question - are here we need declare cancelled as atomic ? are we need atomic here ?



atomic need in 3 case:





  • we do Read-Modify-Write operation. say if we need set
    cancelled to true and check are it was already true. this for example can be need if several threads set cancelled to true and who do this first need free some resources.



    if (!cancelled.exchange(true)) { free_resources(); }



  • the read or write operation for type need to be atomic. of course on
    all current and all possible future implementations this is true for
    bool type (despite formal not defined). but even this is not
    important. we here check cancelled only for 2 values - 0 (false) and
    all another. so even if both write and read operation on
    cancelled assume not atomic, after one thread write non-zero to
    canceled, another thread sooner or later will read modified non-zero value
    from canceled . even if it will be another value, not the same
    first thread write: for example if cancelled = true translated to
    mov cancelled, -1; mov cancelled, 1 - two hardware, not atomic
    operation - second thread can read -1 instead final 1 (true)
    from canceled, but this not play role if we check only for non-zero - all
    another values break loop - while (!*cancelled); if we use here atomic operation for write/read cancelled - nothing change here - after one thread atomic write to it another thread sooner or later will read modified non-zero value from canceled - atomic operation or not - memory is common - if one thread write to memory (atomic or no) another threads sooner or later will view this memory modification.


  • we need synchronize another read/writes with cancelled. so we need
    synchronization point between 2 threads around canceled with memory
    order other than memory_order_relaxed say for example next code:


//



void _do_task();

int result;

void do_task(atomic_bool *cancelled)
{
do {
_do_task();
} while (!g_cancelled.load(memory_order_acquire));

switch(result)
{
case 1:
//...
break;
}
}

void some_proc()
{
result = 1;
g_cancelled.store(true, memory_order_release);
}


so we not simply set g_cancelled to true here, but before this

write some shared data (result) and want that another thread after
view modification of g_cancelled, will be also view modification of

shared data (result). but i doubt that you actually use/need this

scenario



if none of this 3 things is need- you not need atomic here. what you really need - that one thread just write true to cancelled and another thread all time read value of cancelled (instead do this once and cache result). usual in most case of code this will be done auto, but for be exactly you need declare canceled as volatile



if however you by some reason need exactly atomic (atomic_bool), because you here cross the border of languages, you need understand concrete implementation of atomic_bool in both languages and are it the same (type declaration, operations (load, store, etc)). by fact atomic_bool is the same for c and c++.



or (better) instead of make visible and share type atomic_bool use interface functions like



bool is_canceled(void* cancelled);



so code can be next



// c code
void _do_task();

bool is_canceled(void* cancelled);

void do_task(void *cancelled)
{
do {
_do_task();
} while (!is_canceled(cancelled));
}

// c++ code

atomic_bool g_cancelled;// can be modify by another thread

bool is_canceled(void* cancelled)
{
return *reinterpret_cast<atomic_bool*>(cancelled);
}

void some_proc()
{
//...
g_cancelled = true;
}

do_task(&g_cancelled);


but again i doubt that in your task you need atomic_bool by semantic. you need volatile bool






share|improve this answer

































    -5














    Atomicity of operations is caused by hardware, not software (well, in C++ there are also "atomic" variables that are atomic in name only, those are implemented via mutexes and locks). So, basically, C++ atomics and C atomics do the very same thing. Hence as long as the types are compatible there won't be issues. And C++11 and C11 atomic classes were made to be compatible.





    Apparently, people do not understand how atomics and locks work and require further explanation. Check out current memory models for more information.



    1) We will start with basics. What and why are atomics? How does memory works?



    Memory Model: think of processor as several independent cores and each has its own memory (cashes L1, L2, and L3; and in fact, L3 cash is common but it isn't really important).



    Why do we need atomic operation?



    If you don't use atomics, then each processor might have its own version of the variable 'x' and they are in general not synchronized. There is no telling when they will perform synchronizations with RAM/L3 cash.



    When atomic operations are used, such memory operations are used that ensure synchronization with RAM/L3 cash (or whatever is needed) - ensuring that different cores have access to the same variable and not have variety of different versions of it.



    Nobody cares if it is C, C++, or whatever language you use - as long as one ensures memory synchronization (both read, write, and modify) there will never be no issues.



    2) OK, what about locks and mutexes?



    Mutexes tend to work with OS and have queue over which thread should be allowed next to perform. And they enforce stricter memory synchronization than atomics do. With atomics one can syhchronize just the variable itself or more depending on the request / which function you call.



    3) Say I have atomic_bool, can it work in interchangeably on different languages (C/C++11)?



    Normally a boolean can be sychronized via memory operations (you're just synchronizing a single byte of memory from their perspective).
    If the compilers are aware that the hardware can perform such operations then they surely will use them as long as you use the standard.



    Logical atomics (any std::atomic< T > with T having wrong size/alignment) are synchronized via locks. In this case it is unlikely that different languages can use them interchangeably - if they have different methods of usage of these locks, or for some reason one decided to use a lock and the other one came to conclusion that it can work with atomic hardware memory synchronizations... then there will be issues.



    If you use atomic_bool on any modern machine with C/C++, it will surely be able to synchronize without locks.






    share|improve this answer





















    • 8





      "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

      – idmean
      Dec 22 '18 at 19:12











    • @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

      – ALX23z
      Dec 22 '18 at 19:22













    • It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

      – R..
      Dec 23 '18 at 8:18











    Your Answer






    StackExchange.ifUsing("editor", function () {
    StackExchange.using("externalEditor", function () {
    StackExchange.using("snippets", function () {
    StackExchange.snippets.init();
    });
    });
    }, "code-snippets");

    StackExchange.ready(function() {
    var channelOptions = {
    tags: "".split(" "),
    id: "1"
    };
    initTagRenderer("".split(" "), "".split(" "), channelOptions);

    StackExchange.using("externalEditor", function() {
    // Have to fire editor after snippets, if snippets enabled
    if (StackExchange.settings.snippets.snippetsEnabled) {
    StackExchange.using("snippets", function() {
    createEditor();
    });
    }
    else {
    createEditor();
    }
    });

    function createEditor() {
    StackExchange.prepareEditor({
    heartbeatType: 'answer',
    autoActivateHeartbeat: false,
    convertImagesToLinks: true,
    noModals: true,
    showLowRepImageUploadWarning: true,
    reputationToPostImages: 10,
    bindNavPrevention: true,
    postfix: "",
    imageUploader: {
    brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
    contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
    allowUrls: true
    },
    onDemand: true,
    discardSelector: ".discard-answer"
    ,immediatelyShowMarkdownHelp:true
    });


    }
    });














    draft saved

    draft discarded


















    StackExchange.ready(
    function () {
    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53898429%2finteroperabilty-between-c-and-c-atomics%23new-answer', 'question_page');
    }
    );

    Post as a guest















    Required, but never shown

























    5 Answers
    5






    active

    oldest

    votes








    5 Answers
    5






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes









    8














    The atomic_bool type in C and the std::atomic<bool> type in C++ (typedefed as std::atomic_bool) are two different types that are unrelated. Passing a std::atomic_bool to a C function expecting C's atomic_bool is Undefined Behavior. That it works at all is a combination of luck and the simple definitions of these types being compatible.



    If the C++ code needs to call a C function that expects C's atomic_bool, then that is what it must use. However, the <stdatomic.h> header does not exist in C++. You'll have to provide a way for the C++ code to call C code to get a pointer to the atomic variable you need in a way that hides the type. (Possibly declare a struct that holds the atomic bool, that C++ would only know that the type exists and only know about pointers to it.)






    share|improve this answer
























    • It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

      – ALX23z
      Dec 22 '18 at 20:36






    • 1





      from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

      – Manny_Mar
      Dec 22 '18 at 23:29








    • 1





      @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

      – Lightness Races in Orbit
      Dec 23 '18 at 1:25











    • @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

      – ALX23z
      Dec 23 '18 at 2:19








    • 3





      @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

      – user2357112
      Dec 23 '18 at 2:22
















    8














    The atomic_bool type in C and the std::atomic<bool> type in C++ (typedefed as std::atomic_bool) are two different types that are unrelated. Passing a std::atomic_bool to a C function expecting C's atomic_bool is Undefined Behavior. That it works at all is a combination of luck and the simple definitions of these types being compatible.



    If the C++ code needs to call a C function that expects C's atomic_bool, then that is what it must use. However, the <stdatomic.h> header does not exist in C++. You'll have to provide a way for the C++ code to call C code to get a pointer to the atomic variable you need in a way that hides the type. (Possibly declare a struct that holds the atomic bool, that C++ would only know that the type exists and only know about pointers to it.)






    share|improve this answer
























    • It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

      – ALX23z
      Dec 22 '18 at 20:36






    • 1





      from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

      – Manny_Mar
      Dec 22 '18 at 23:29








    • 1





      @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

      – Lightness Races in Orbit
      Dec 23 '18 at 1:25











    • @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

      – ALX23z
      Dec 23 '18 at 2:19








    • 3





      @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

      – user2357112
      Dec 23 '18 at 2:22














    8












    8








    8







    The atomic_bool type in C and the std::atomic<bool> type in C++ (typedefed as std::atomic_bool) are two different types that are unrelated. Passing a std::atomic_bool to a C function expecting C's atomic_bool is Undefined Behavior. That it works at all is a combination of luck and the simple definitions of these types being compatible.



    If the C++ code needs to call a C function that expects C's atomic_bool, then that is what it must use. However, the <stdatomic.h> header does not exist in C++. You'll have to provide a way for the C++ code to call C code to get a pointer to the atomic variable you need in a way that hides the type. (Possibly declare a struct that holds the atomic bool, that C++ would only know that the type exists and only know about pointers to it.)






    share|improve this answer













    The atomic_bool type in C and the std::atomic<bool> type in C++ (typedefed as std::atomic_bool) are two different types that are unrelated. Passing a std::atomic_bool to a C function expecting C's atomic_bool is Undefined Behavior. That it works at all is a combination of luck and the simple definitions of these types being compatible.



    If the C++ code needs to call a C function that expects C's atomic_bool, then that is what it must use. However, the <stdatomic.h> header does not exist in C++. You'll have to provide a way for the C++ code to call C code to get a pointer to the atomic variable you need in a way that hides the type. (Possibly declare a struct that holds the atomic bool, that C++ would only know that the type exists and only know about pointers to it.)







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered Dec 22 '18 at 20:02









    1201ProgramAlarm1201ProgramAlarm

    16.5k42439




    16.5k42439













    • It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

      – ALX23z
      Dec 22 '18 at 20:36






    • 1





      from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

      – Manny_Mar
      Dec 22 '18 at 23:29








    • 1





      @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

      – Lightness Races in Orbit
      Dec 23 '18 at 1:25











    • @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

      – ALX23z
      Dec 23 '18 at 2:19








    • 3





      @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

      – user2357112
      Dec 23 '18 at 2:22



















    • It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

      – ALX23z
      Dec 22 '18 at 20:36






    • 1





      from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

      – Manny_Mar
      Dec 22 '18 at 23:29








    • 1





      @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

      – Lightness Races in Orbit
      Dec 23 '18 at 1:25











    • @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

      – ALX23z
      Dec 23 '18 at 2:19








    • 3





      @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

      – user2357112
      Dec 23 '18 at 2:22

















    It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

    – ALX23z
    Dec 22 '18 at 20:36





    It doesn't matter that they are different types. They basically synchronize the same byte of memory via same memory operations. struct A{int x; int y; int z}; and struct B{int a[3];}; are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior. Same with atomic_bool and std::atomic<bool>.

    – ALX23z
    Dec 22 '18 at 20:36




    1




    1





    from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

    – Manny_Mar
    Dec 22 '18 at 23:29







    from developers.redhat.com/blog/2016/01/14/… "The atomic types are fully interoperable between the two languages so that programs can be developed that share objects of atomic types across the language boundary."

    – Manny_Mar
    Dec 22 '18 at 23:29






    1




    1





    @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

    – Lightness Races in Orbit
    Dec 23 '18 at 1:25





    @ALX23z "are different but there is no problem when converting one from the other via brute-force conversions. There is no undefined behavior" Really?

    – Lightness Races in Orbit
    Dec 23 '18 at 1:25













    @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

    – ALX23z
    Dec 23 '18 at 2:19







    @LightnessRacesinOrbit "Really?" Of course, from POV of CPU it is just 3 consecutive integers - 12 bytes of data. Who cares what you called these variables in your source code? Definitely not the program after you compiled it. Perhaps, 100 years into the future they will decide that compiler can rearrange internal variables in any order but it is not the case now or in any foreseeable future. Try and find system where A a; B *b = (B*)(void*)&a; won't work correctly.

    – ALX23z
    Dec 23 '18 at 2:19






    3




    3





    @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

    – user2357112
    Dec 23 '18 at 2:22





    @ALX23z: "from POV of CPU" doesn't matter. That's not how undefined behavior works.

    – user2357112
    Dec 23 '18 at 2:22













    9














    To side-step all ABI issues you may like to implement a C function that is called from C++ and operates on that atomic_bool. This way your C++ code doesn't need to know anything about that global variable and its type:



    In an .hfile:



    #ifdef __cplusplus
    extern "C" {
    #endif

    void cancel_my_thread(void);
    int is_my_thread_cancelled(void);

    #ifdef __cplusplus
    }
    #endif


    And then in a .c file:



    #include <stdatomic.h>

    static atomic_bool cancelled = 0;

    void cancel_my_thread(void) {
    atomic_store_explicit(&cancelled, 1, memory_order_relaxed);
    }
    int is_my_thread_cancelled(void) {
    return atomic_load_explicit(&cancelled, memory_order_relaxed);
    }


    The C++ code would include that headed and call cancel_my_thread.






    share|improve this answer


























    • Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

      – grepcake
      Dec 23 '18 at 9:13
















    9














    To side-step all ABI issues you may like to implement a C function that is called from C++ and operates on that atomic_bool. This way your C++ code doesn't need to know anything about that global variable and its type:



    In an .hfile:



    #ifdef __cplusplus
    extern "C" {
    #endif

    void cancel_my_thread(void);
    int is_my_thread_cancelled(void);

    #ifdef __cplusplus
    }
    #endif


    And then in a .c file:



    #include <stdatomic.h>

    static atomic_bool cancelled = 0;

    void cancel_my_thread(void) {
    atomic_store_explicit(&cancelled, 1, memory_order_relaxed);
    }
    int is_my_thread_cancelled(void) {
    return atomic_load_explicit(&cancelled, memory_order_relaxed);
    }


    The C++ code would include that headed and call cancel_my_thread.






    share|improve this answer


























    • Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

      – grepcake
      Dec 23 '18 at 9:13














    9












    9








    9







    To side-step all ABI issues you may like to implement a C function that is called from C++ and operates on that atomic_bool. This way your C++ code doesn't need to know anything about that global variable and its type:



    In an .hfile:



    #ifdef __cplusplus
    extern "C" {
    #endif

    void cancel_my_thread(void);
    int is_my_thread_cancelled(void);

    #ifdef __cplusplus
    }
    #endif


    And then in a .c file:



    #include <stdatomic.h>

    static atomic_bool cancelled = 0;

    void cancel_my_thread(void) {
    atomic_store_explicit(&cancelled, 1, memory_order_relaxed);
    }
    int is_my_thread_cancelled(void) {
    return atomic_load_explicit(&cancelled, memory_order_relaxed);
    }


    The C++ code would include that headed and call cancel_my_thread.






    share|improve this answer















    To side-step all ABI issues you may like to implement a C function that is called from C++ and operates on that atomic_bool. This way your C++ code doesn't need to know anything about that global variable and its type:



    In an .hfile:



    #ifdef __cplusplus
    extern "C" {
    #endif

    void cancel_my_thread(void);
    int is_my_thread_cancelled(void);

    #ifdef __cplusplus
    }
    #endif


    And then in a .c file:



    #include <stdatomic.h>

    static atomic_bool cancelled = 0;

    void cancel_my_thread(void) {
    atomic_store_explicit(&cancelled, 1, memory_order_relaxed);
    }
    int is_my_thread_cancelled(void) {
    return atomic_load_explicit(&cancelled, memory_order_relaxed);
    }


    The C++ code would include that headed and call cancel_my_thread.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 22 '18 at 23:52

























    answered Dec 22 '18 at 23:37









    Maxim EgorushkinMaxim Egorushkin

    86.1k11100183




    86.1k11100183













    • Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

      – grepcake
      Dec 23 '18 at 9:13



















    • Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

      – grepcake
      Dec 23 '18 at 9:13

















    Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

    – grepcake
    Dec 23 '18 at 9:13





    Thank you, it is a sane solution, however in my particular case, do_task might be called from several threads, so using using global variable wouldn't work. I guess, I'll just wrap it in a struct as @1201ProgramAlarm suggests.

    – grepcake
    Dec 23 '18 at 9:13











    1














    I found this on a net search https://developers.redhat.com/blog/2016/01/14/toward-a-better-use-of-c11-atomics-part-1/




    Following the lead of C++, along with a memory model describing the
    requirements and semantics of multithreaded programs, the C11 standard
    adopted a proposal for a set of atomic types and operations into the
    language. This change has made it possible to write portable
    multi-threaded software that efficiently manipulates objects
    indivisibly and without data races. The atomic types are fully
    interoperable between the two languages so that programs can be
    developed that share objects of atomic types across the language
    boundary. This paper examines some of the trade-offs of the design,
    points out some of its shortcomings, and outlines solutions that
    simplify the use of atomic objects in both languages.




    I am just learning about atomics now, but it looks like its compatible between C and CPP.






    share|improve this answer





















    • 1





      Do you have a more authoritative source than "some guy's blog said it was okay"?

      – user2357112
      Dec 23 '18 at 2:16











    • If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

      – Manny_Mar
      Dec 23 '18 at 2:21


















    1














    I found this on a net search https://developers.redhat.com/blog/2016/01/14/toward-a-better-use-of-c11-atomics-part-1/




    Following the lead of C++, along with a memory model describing the
    requirements and semantics of multithreaded programs, the C11 standard
    adopted a proposal for a set of atomic types and operations into the
    language. This change has made it possible to write portable
    multi-threaded software that efficiently manipulates objects
    indivisibly and without data races. The atomic types are fully
    interoperable between the two languages so that programs can be
    developed that share objects of atomic types across the language
    boundary. This paper examines some of the trade-offs of the design,
    points out some of its shortcomings, and outlines solutions that
    simplify the use of atomic objects in both languages.




    I am just learning about atomics now, but it looks like its compatible between C and CPP.






    share|improve this answer





















    • 1





      Do you have a more authoritative source than "some guy's blog said it was okay"?

      – user2357112
      Dec 23 '18 at 2:16











    • If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

      – Manny_Mar
      Dec 23 '18 at 2:21
















    1












    1








    1







    I found this on a net search https://developers.redhat.com/blog/2016/01/14/toward-a-better-use-of-c11-atomics-part-1/




    Following the lead of C++, along with a memory model describing the
    requirements and semantics of multithreaded programs, the C11 standard
    adopted a proposal for a set of atomic types and operations into the
    language. This change has made it possible to write portable
    multi-threaded software that efficiently manipulates objects
    indivisibly and without data races. The atomic types are fully
    interoperable between the two languages so that programs can be
    developed that share objects of atomic types across the language
    boundary. This paper examines some of the trade-offs of the design,
    points out some of its shortcomings, and outlines solutions that
    simplify the use of atomic objects in both languages.




    I am just learning about atomics now, but it looks like its compatible between C and CPP.






    share|improve this answer















    I found this on a net search https://developers.redhat.com/blog/2016/01/14/toward-a-better-use-of-c11-atomics-part-1/




    Following the lead of C++, along with a memory model describing the
    requirements and semantics of multithreaded programs, the C11 standard
    adopted a proposal for a set of atomic types and operations into the
    language. This change has made it possible to write portable
    multi-threaded software that efficiently manipulates objects
    indivisibly and without data races. The atomic types are fully
    interoperable between the two languages so that programs can be
    developed that share objects of atomic types across the language
    boundary. This paper examines some of the trade-offs of the design,
    points out some of its shortcomings, and outlines solutions that
    simplify the use of atomic objects in both languages.




    I am just learning about atomics now, but it looks like its compatible between C and CPP.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited Dec 22 '18 at 23:46

























    answered Dec 22 '18 at 23:32









    Manny_MarManny_Mar

    1318




    1318








    • 1





      Do you have a more authoritative source than "some guy's blog said it was okay"?

      – user2357112
      Dec 23 '18 at 2:16











    • If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

      – Manny_Mar
      Dec 23 '18 at 2:21
















    • 1





      Do you have a more authoritative source than "some guy's blog said it was okay"?

      – user2357112
      Dec 23 '18 at 2:16











    • If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

      – Manny_Mar
      Dec 23 '18 at 2:21










    1




    1





    Do you have a more authoritative source than "some guy's blog said it was okay"?

    – user2357112
    Dec 23 '18 at 2:16





    Do you have a more authoritative source than "some guy's blog said it was okay"?

    – user2357112
    Dec 23 '18 at 2:16













    If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

    – Manny_Mar
    Dec 23 '18 at 2:21







    If you read it the paper is about trade-offs of the design, points out some of its shortcomings, and outlines solutions that simplify the use of atomic objects in both languages. He goes into a lot of detail, which I think require some knowledge. I do not claim to be an expert on this. I did read in the past, that C11 got it's atomics from cpp.

    – Manny_Mar
    Dec 23 '18 at 2:21













    -1














    how i understand your code in general is (must be) next



    // c code

    void _do_task();

    void do_task(volatile bool *cancelled)
    {
    do {
    _do_task();
    } while (!*cancelled);
    }

    // c++ code

    volatile bool g_cancelled;// can be modify by another thread
    do_task(&cancelled);

    void some_proc()
    {
    //...
    g_cancelled = true;
    }


    i be ask question - are here we need declare cancelled as atomic ? are we need atomic here ?



    atomic need in 3 case:





    • we do Read-Modify-Write operation. say if we need set
      cancelled to true and check are it was already true. this for example can be need if several threads set cancelled to true and who do this first need free some resources.



      if (!cancelled.exchange(true)) { free_resources(); }



    • the read or write operation for type need to be atomic. of course on
      all current and all possible future implementations this is true for
      bool type (despite formal not defined). but even this is not
      important. we here check cancelled only for 2 values - 0 (false) and
      all another. so even if both write and read operation on
      cancelled assume not atomic, after one thread write non-zero to
      canceled, another thread sooner or later will read modified non-zero value
      from canceled . even if it will be another value, not the same
      first thread write: for example if cancelled = true translated to
      mov cancelled, -1; mov cancelled, 1 - two hardware, not atomic
      operation - second thread can read -1 instead final 1 (true)
      from canceled, but this not play role if we check only for non-zero - all
      another values break loop - while (!*cancelled); if we use here atomic operation for write/read cancelled - nothing change here - after one thread atomic write to it another thread sooner or later will read modified non-zero value from canceled - atomic operation or not - memory is common - if one thread write to memory (atomic or no) another threads sooner or later will view this memory modification.


    • we need synchronize another read/writes with cancelled. so we need
      synchronization point between 2 threads around canceled with memory
      order other than memory_order_relaxed say for example next code:


    //



    void _do_task();

    int result;

    void do_task(atomic_bool *cancelled)
    {
    do {
    _do_task();
    } while (!g_cancelled.load(memory_order_acquire));

    switch(result)
    {
    case 1:
    //...
    break;
    }
    }

    void some_proc()
    {
    result = 1;
    g_cancelled.store(true, memory_order_release);
    }


    so we not simply set g_cancelled to true here, but before this

    write some shared data (result) and want that another thread after
    view modification of g_cancelled, will be also view modification of

    shared data (result). but i doubt that you actually use/need this

    scenario



    if none of this 3 things is need- you not need atomic here. what you really need - that one thread just write true to cancelled and another thread all time read value of cancelled (instead do this once and cache result). usual in most case of code this will be done auto, but for be exactly you need declare canceled as volatile



    if however you by some reason need exactly atomic (atomic_bool), because you here cross the border of languages, you need understand concrete implementation of atomic_bool in both languages and are it the same (type declaration, operations (load, store, etc)). by fact atomic_bool is the same for c and c++.



    or (better) instead of make visible and share type atomic_bool use interface functions like



    bool is_canceled(void* cancelled);



    so code can be next



    // c code
    void _do_task();

    bool is_canceled(void* cancelled);

    void do_task(void *cancelled)
    {
    do {
    _do_task();
    } while (!is_canceled(cancelled));
    }

    // c++ code

    atomic_bool g_cancelled;// can be modify by another thread

    bool is_canceled(void* cancelled)
    {
    return *reinterpret_cast<atomic_bool*>(cancelled);
    }

    void some_proc()
    {
    //...
    g_cancelled = true;
    }

    do_task(&g_cancelled);


    but again i doubt that in your task you need atomic_bool by semantic. you need volatile bool






    share|improve this answer






























      -1














      how i understand your code in general is (must be) next



      // c code

      void _do_task();

      void do_task(volatile bool *cancelled)
      {
      do {
      _do_task();
      } while (!*cancelled);
      }

      // c++ code

      volatile bool g_cancelled;// can be modify by another thread
      do_task(&cancelled);

      void some_proc()
      {
      //...
      g_cancelled = true;
      }


      i be ask question - are here we need declare cancelled as atomic ? are we need atomic here ?



      atomic need in 3 case:





      • we do Read-Modify-Write operation. say if we need set
        cancelled to true and check are it was already true. this for example can be need if several threads set cancelled to true and who do this first need free some resources.



        if (!cancelled.exchange(true)) { free_resources(); }



      • the read or write operation for type need to be atomic. of course on
        all current and all possible future implementations this is true for
        bool type (despite formal not defined). but even this is not
        important. we here check cancelled only for 2 values - 0 (false) and
        all another. so even if both write and read operation on
        cancelled assume not atomic, after one thread write non-zero to
        canceled, another thread sooner or later will read modified non-zero value
        from canceled . even if it will be another value, not the same
        first thread write: for example if cancelled = true translated to
        mov cancelled, -1; mov cancelled, 1 - two hardware, not atomic
        operation - second thread can read -1 instead final 1 (true)
        from canceled, but this not play role if we check only for non-zero - all
        another values break loop - while (!*cancelled); if we use here atomic operation for write/read cancelled - nothing change here - after one thread atomic write to it another thread sooner or later will read modified non-zero value from canceled - atomic operation or not - memory is common - if one thread write to memory (atomic or no) another threads sooner or later will view this memory modification.


      • we need synchronize another read/writes with cancelled. so we need
        synchronization point between 2 threads around canceled with memory
        order other than memory_order_relaxed say for example next code:


      //



      void _do_task();

      int result;

      void do_task(atomic_bool *cancelled)
      {
      do {
      _do_task();
      } while (!g_cancelled.load(memory_order_acquire));

      switch(result)
      {
      case 1:
      //...
      break;
      }
      }

      void some_proc()
      {
      result = 1;
      g_cancelled.store(true, memory_order_release);
      }


      so we not simply set g_cancelled to true here, but before this

      write some shared data (result) and want that another thread after
      view modification of g_cancelled, will be also view modification of

      shared data (result). but i doubt that you actually use/need this

      scenario



      if none of this 3 things is need- you not need atomic here. what you really need - that one thread just write true to cancelled and another thread all time read value of cancelled (instead do this once and cache result). usual in most case of code this will be done auto, but for be exactly you need declare canceled as volatile



      if however you by some reason need exactly atomic (atomic_bool), because you here cross the border of languages, you need understand concrete implementation of atomic_bool in both languages and are it the same (type declaration, operations (load, store, etc)). by fact atomic_bool is the same for c and c++.



      or (better) instead of make visible and share type atomic_bool use interface functions like



      bool is_canceled(void* cancelled);



      so code can be next



      // c code
      void _do_task();

      bool is_canceled(void* cancelled);

      void do_task(void *cancelled)
      {
      do {
      _do_task();
      } while (!is_canceled(cancelled));
      }

      // c++ code

      atomic_bool g_cancelled;// can be modify by another thread

      bool is_canceled(void* cancelled)
      {
      return *reinterpret_cast<atomic_bool*>(cancelled);
      }

      void some_proc()
      {
      //...
      g_cancelled = true;
      }

      do_task(&g_cancelled);


      but again i doubt that in your task you need atomic_bool by semantic. you need volatile bool






      share|improve this answer




























        -1












        -1








        -1







        how i understand your code in general is (must be) next



        // c code

        void _do_task();

        void do_task(volatile bool *cancelled)
        {
        do {
        _do_task();
        } while (!*cancelled);
        }

        // c++ code

        volatile bool g_cancelled;// can be modify by another thread
        do_task(&cancelled);

        void some_proc()
        {
        //...
        g_cancelled = true;
        }


        i be ask question - are here we need declare cancelled as atomic ? are we need atomic here ?



        atomic need in 3 case:





        • we do Read-Modify-Write operation. say if we need set
          cancelled to true and check are it was already true. this for example can be need if several threads set cancelled to true and who do this first need free some resources.



          if (!cancelled.exchange(true)) { free_resources(); }



        • the read or write operation for type need to be atomic. of course on
          all current and all possible future implementations this is true for
          bool type (despite formal not defined). but even this is not
          important. we here check cancelled only for 2 values - 0 (false) and
          all another. so even if both write and read operation on
          cancelled assume not atomic, after one thread write non-zero to
          canceled, another thread sooner or later will read modified non-zero value
          from canceled . even if it will be another value, not the same
          first thread write: for example if cancelled = true translated to
          mov cancelled, -1; mov cancelled, 1 - two hardware, not atomic
          operation - second thread can read -1 instead final 1 (true)
          from canceled, but this not play role if we check only for non-zero - all
          another values break loop - while (!*cancelled); if we use here atomic operation for write/read cancelled - nothing change here - after one thread atomic write to it another thread sooner or later will read modified non-zero value from canceled - atomic operation or not - memory is common - if one thread write to memory (atomic or no) another threads sooner or later will view this memory modification.


        • we need synchronize another read/writes with cancelled. so we need
          synchronization point between 2 threads around canceled with memory
          order other than memory_order_relaxed say for example next code:


        //



        void _do_task();

        int result;

        void do_task(atomic_bool *cancelled)
        {
        do {
        _do_task();
        } while (!g_cancelled.load(memory_order_acquire));

        switch(result)
        {
        case 1:
        //...
        break;
        }
        }

        void some_proc()
        {
        result = 1;
        g_cancelled.store(true, memory_order_release);
        }


        so we not simply set g_cancelled to true here, but before this

        write some shared data (result) and want that another thread after
        view modification of g_cancelled, will be also view modification of

        shared data (result). but i doubt that you actually use/need this

        scenario



        if none of this 3 things is need- you not need atomic here. what you really need - that one thread just write true to cancelled and another thread all time read value of cancelled (instead do this once and cache result). usual in most case of code this will be done auto, but for be exactly you need declare canceled as volatile



        if however you by some reason need exactly atomic (atomic_bool), because you here cross the border of languages, you need understand concrete implementation of atomic_bool in both languages and are it the same (type declaration, operations (load, store, etc)). by fact atomic_bool is the same for c and c++.



        or (better) instead of make visible and share type atomic_bool use interface functions like



        bool is_canceled(void* cancelled);



        so code can be next



        // c code
        void _do_task();

        bool is_canceled(void* cancelled);

        void do_task(void *cancelled)
        {
        do {
        _do_task();
        } while (!is_canceled(cancelled));
        }

        // c++ code

        atomic_bool g_cancelled;// can be modify by another thread

        bool is_canceled(void* cancelled)
        {
        return *reinterpret_cast<atomic_bool*>(cancelled);
        }

        void some_proc()
        {
        //...
        g_cancelled = true;
        }

        do_task(&g_cancelled);


        but again i doubt that in your task you need atomic_bool by semantic. you need volatile bool






        share|improve this answer















        how i understand your code in general is (must be) next



        // c code

        void _do_task();

        void do_task(volatile bool *cancelled)
        {
        do {
        _do_task();
        } while (!*cancelled);
        }

        // c++ code

        volatile bool g_cancelled;// can be modify by another thread
        do_task(&cancelled);

        void some_proc()
        {
        //...
        g_cancelled = true;
        }


        i be ask question - are here we need declare cancelled as atomic ? are we need atomic here ?



        atomic need in 3 case:





        • we do Read-Modify-Write operation. say if we need set
          cancelled to true and check are it was already true. this for example can be need if several threads set cancelled to true and who do this first need free some resources.



          if (!cancelled.exchange(true)) { free_resources(); }



        • the read or write operation for type need to be atomic. of course on
          all current and all possible future implementations this is true for
          bool type (despite formal not defined). but even this is not
          important. we here check cancelled only for 2 values - 0 (false) and
          all another. so even if both write and read operation on
          cancelled assume not atomic, after one thread write non-zero to
          canceled, another thread sooner or later will read modified non-zero value
          from canceled . even if it will be another value, not the same
          first thread write: for example if cancelled = true translated to
          mov cancelled, -1; mov cancelled, 1 - two hardware, not atomic
          operation - second thread can read -1 instead final 1 (true)
          from canceled, but this not play role if we check only for non-zero - all
          another values break loop - while (!*cancelled); if we use here atomic operation for write/read cancelled - nothing change here - after one thread atomic write to it another thread sooner or later will read modified non-zero value from canceled - atomic operation or not - memory is common - if one thread write to memory (atomic or no) another threads sooner or later will view this memory modification.


        • we need synchronize another read/writes with cancelled. so we need
          synchronization point between 2 threads around canceled with memory
          order other than memory_order_relaxed say for example next code:


        //



        void _do_task();

        int result;

        void do_task(atomic_bool *cancelled)
        {
        do {
        _do_task();
        } while (!g_cancelled.load(memory_order_acquire));

        switch(result)
        {
        case 1:
        //...
        break;
        }
        }

        void some_proc()
        {
        result = 1;
        g_cancelled.store(true, memory_order_release);
        }


        so we not simply set g_cancelled to true here, but before this

        write some shared data (result) and want that another thread after
        view modification of g_cancelled, will be also view modification of

        shared data (result). but i doubt that you actually use/need this

        scenario



        if none of this 3 things is need- you not need atomic here. what you really need - that one thread just write true to cancelled and another thread all time read value of cancelled (instead do this once and cache result). usual in most case of code this will be done auto, but for be exactly you need declare canceled as volatile



        if however you by some reason need exactly atomic (atomic_bool), because you here cross the border of languages, you need understand concrete implementation of atomic_bool in both languages and are it the same (type declaration, operations (load, store, etc)). by fact atomic_bool is the same for c and c++.



        or (better) instead of make visible and share type atomic_bool use interface functions like



        bool is_canceled(void* cancelled);



        so code can be next



        // c code
        void _do_task();

        bool is_canceled(void* cancelled);

        void do_task(void *cancelled)
        {
        do {
        _do_task();
        } while (!is_canceled(cancelled));
        }

        // c++ code

        atomic_bool g_cancelled;// can be modify by another thread

        bool is_canceled(void* cancelled)
        {
        return *reinterpret_cast<atomic_bool*>(cancelled);
        }

        void some_proc()
        {
        //...
        g_cancelled = true;
        }

        do_task(&g_cancelled);


        but again i doubt that in your task you need atomic_bool by semantic. you need volatile bool







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Dec 23 '18 at 9:07

























        answered Dec 23 '18 at 0:18









        RbMmRbMm

        17.4k11224




        17.4k11224























            -5














            Atomicity of operations is caused by hardware, not software (well, in C++ there are also "atomic" variables that are atomic in name only, those are implemented via mutexes and locks). So, basically, C++ atomics and C atomics do the very same thing. Hence as long as the types are compatible there won't be issues. And C++11 and C11 atomic classes were made to be compatible.





            Apparently, people do not understand how atomics and locks work and require further explanation. Check out current memory models for more information.



            1) We will start with basics. What and why are atomics? How does memory works?



            Memory Model: think of processor as several independent cores and each has its own memory (cashes L1, L2, and L3; and in fact, L3 cash is common but it isn't really important).



            Why do we need atomic operation?



            If you don't use atomics, then each processor might have its own version of the variable 'x' and they are in general not synchronized. There is no telling when they will perform synchronizations with RAM/L3 cash.



            When atomic operations are used, such memory operations are used that ensure synchronization with RAM/L3 cash (or whatever is needed) - ensuring that different cores have access to the same variable and not have variety of different versions of it.



            Nobody cares if it is C, C++, or whatever language you use - as long as one ensures memory synchronization (both read, write, and modify) there will never be no issues.



            2) OK, what about locks and mutexes?



            Mutexes tend to work with OS and have queue over which thread should be allowed next to perform. And they enforce stricter memory synchronization than atomics do. With atomics one can syhchronize just the variable itself or more depending on the request / which function you call.



            3) Say I have atomic_bool, can it work in interchangeably on different languages (C/C++11)?



            Normally a boolean can be sychronized via memory operations (you're just synchronizing a single byte of memory from their perspective).
            If the compilers are aware that the hardware can perform such operations then they surely will use them as long as you use the standard.



            Logical atomics (any std::atomic< T > with T having wrong size/alignment) are synchronized via locks. In this case it is unlikely that different languages can use them interchangeably - if they have different methods of usage of these locks, or for some reason one decided to use a lock and the other one came to conclusion that it can work with atomic hardware memory synchronizations... then there will be issues.



            If you use atomic_bool on any modern machine with C/C++, it will surely be able to synchronize without locks.






            share|improve this answer





















            • 8





              "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

              – idmean
              Dec 22 '18 at 19:12











            • @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

              – ALX23z
              Dec 22 '18 at 19:22













            • It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

              – R..
              Dec 23 '18 at 8:18
















            -5














            Atomicity of operations is caused by hardware, not software (well, in C++ there are also "atomic" variables that are atomic in name only, those are implemented via mutexes and locks). So, basically, C++ atomics and C atomics do the very same thing. Hence as long as the types are compatible there won't be issues. And C++11 and C11 atomic classes were made to be compatible.





            Apparently, people do not understand how atomics and locks work and require further explanation. Check out current memory models for more information.



            1) We will start with basics. What and why are atomics? How does memory works?



            Memory Model: think of processor as several independent cores and each has its own memory (cashes L1, L2, and L3; and in fact, L3 cash is common but it isn't really important).



            Why do we need atomic operation?



            If you don't use atomics, then each processor might have its own version of the variable 'x' and they are in general not synchronized. There is no telling when they will perform synchronizations with RAM/L3 cash.



            When atomic operations are used, such memory operations are used that ensure synchronization with RAM/L3 cash (or whatever is needed) - ensuring that different cores have access to the same variable and not have variety of different versions of it.



            Nobody cares if it is C, C++, or whatever language you use - as long as one ensures memory synchronization (both read, write, and modify) there will never be no issues.



            2) OK, what about locks and mutexes?



            Mutexes tend to work with OS and have queue over which thread should be allowed next to perform. And they enforce stricter memory synchronization than atomics do. With atomics one can syhchronize just the variable itself or more depending on the request / which function you call.



            3) Say I have atomic_bool, can it work in interchangeably on different languages (C/C++11)?



            Normally a boolean can be sychronized via memory operations (you're just synchronizing a single byte of memory from their perspective).
            If the compilers are aware that the hardware can perform such operations then they surely will use them as long as you use the standard.



            Logical atomics (any std::atomic< T > with T having wrong size/alignment) are synchronized via locks. In this case it is unlikely that different languages can use them interchangeably - if they have different methods of usage of these locks, or for some reason one decided to use a lock and the other one came to conclusion that it can work with atomic hardware memory synchronizations... then there will be issues.



            If you use atomic_bool on any modern machine with C/C++, it will surely be able to synchronize without locks.






            share|improve this answer





















            • 8





              "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

              – idmean
              Dec 22 '18 at 19:12











            • @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

              – ALX23z
              Dec 22 '18 at 19:22













            • It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

              – R..
              Dec 23 '18 at 8:18














            -5












            -5








            -5







            Atomicity of operations is caused by hardware, not software (well, in C++ there are also "atomic" variables that are atomic in name only, those are implemented via mutexes and locks). So, basically, C++ atomics and C atomics do the very same thing. Hence as long as the types are compatible there won't be issues. And C++11 and C11 atomic classes were made to be compatible.





            Apparently, people do not understand how atomics and locks work and require further explanation. Check out current memory models for more information.



            1) We will start with basics. What and why are atomics? How does memory works?



            Memory Model: think of processor as several independent cores and each has its own memory (cashes L1, L2, and L3; and in fact, L3 cash is common but it isn't really important).



            Why do we need atomic operation?



            If you don't use atomics, then each processor might have its own version of the variable 'x' and they are in general not synchronized. There is no telling when they will perform synchronizations with RAM/L3 cash.



            When atomic operations are used, such memory operations are used that ensure synchronization with RAM/L3 cash (or whatever is needed) - ensuring that different cores have access to the same variable and not have variety of different versions of it.



            Nobody cares if it is C, C++, or whatever language you use - as long as one ensures memory synchronization (both read, write, and modify) there will never be no issues.



            2) OK, what about locks and mutexes?



            Mutexes tend to work with OS and have queue over which thread should be allowed next to perform. And they enforce stricter memory synchronization than atomics do. With atomics one can syhchronize just the variable itself or more depending on the request / which function you call.



            3) Say I have atomic_bool, can it work in interchangeably on different languages (C/C++11)?



            Normally a boolean can be sychronized via memory operations (you're just synchronizing a single byte of memory from their perspective).
            If the compilers are aware that the hardware can perform such operations then they surely will use them as long as you use the standard.



            Logical atomics (any std::atomic< T > with T having wrong size/alignment) are synchronized via locks. In this case it is unlikely that different languages can use them interchangeably - if they have different methods of usage of these locks, or for some reason one decided to use a lock and the other one came to conclusion that it can work with atomic hardware memory synchronizations... then there will be issues.



            If you use atomic_bool on any modern machine with C/C++, it will surely be able to synchronize without locks.






            share|improve this answer















            Atomicity of operations is caused by hardware, not software (well, in C++ there are also "atomic" variables that are atomic in name only, those are implemented via mutexes and locks). So, basically, C++ atomics and C atomics do the very same thing. Hence as long as the types are compatible there won't be issues. And C++11 and C11 atomic classes were made to be compatible.





            Apparently, people do not understand how atomics and locks work and require further explanation. Check out current memory models for more information.



            1) We will start with basics. What and why are atomics? How does memory works?



            Memory Model: think of processor as several independent cores and each has its own memory (cashes L1, L2, and L3; and in fact, L3 cash is common but it isn't really important).



            Why do we need atomic operation?



            If you don't use atomics, then each processor might have its own version of the variable 'x' and they are in general not synchronized. There is no telling when they will perform synchronizations with RAM/L3 cash.



            When atomic operations are used, such memory operations are used that ensure synchronization with RAM/L3 cash (or whatever is needed) - ensuring that different cores have access to the same variable and not have variety of different versions of it.



            Nobody cares if it is C, C++, or whatever language you use - as long as one ensures memory synchronization (both read, write, and modify) there will never be no issues.



            2) OK, what about locks and mutexes?



            Mutexes tend to work with OS and have queue over which thread should be allowed next to perform. And they enforce stricter memory synchronization than atomics do. With atomics one can syhchronize just the variable itself or more depending on the request / which function you call.



            3) Say I have atomic_bool, can it work in interchangeably on different languages (C/C++11)?



            Normally a boolean can be sychronized via memory operations (you're just synchronizing a single byte of memory from their perspective).
            If the compilers are aware that the hardware can perform such operations then they surely will use them as long as you use the standard.



            Logical atomics (any std::atomic< T > with T having wrong size/alignment) are synchronized via locks. In this case it is unlikely that different languages can use them interchangeably - if they have different methods of usage of these locks, or for some reason one decided to use a lock and the other one came to conclusion that it can work with atomic hardware memory synchronizations... then there will be issues.



            If you use atomic_bool on any modern machine with C/C++, it will surely be able to synchronize without locks.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Dec 22 '18 at 21:44

























            answered Dec 22 '18 at 19:05









            ALX23zALX23z

            1275




            1275








            • 8





              "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

              – idmean
              Dec 22 '18 at 19:12











            • @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

              – ALX23z
              Dec 22 '18 at 19:22













            • It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

              – R..
              Dec 23 '18 at 8:18














            • 8





              "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

              – idmean
              Dec 22 '18 at 19:12











            • @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

              – ALX23z
              Dec 22 '18 at 19:22













            • It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

              – R..
              Dec 23 '18 at 8:18








            8




            8





            "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

            – idmean
            Dec 22 '18 at 19:12





            "And C++11 and C11 atomic classes were made to be compatible" Can you cite any source for this claim? Moreover, std::atomic_bool is not guaranteed to be lock free as opposed to std::atomic_flag.

            – idmean
            Dec 22 '18 at 19:12













            @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

            – ALX23z
            Dec 22 '18 at 19:22







            @idmean atomic_bool is not guaranteed to be lock free by the standart, as it doesn't require it to be. Whether it is lock free or not is something you ought to ask hardware whether it supports atomic operations. Locks are also in sense atomics, as they force more strict memory syncronization, while atomics allow way more relaxed memory sync.

            – ALX23z
            Dec 22 '18 at 19:22















            It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

            – R..
            Dec 23 '18 at 8:18





            It reads like a rant by a newcomer who's mad that experts are telling them they're wrong.

            – R..
            Dec 23 '18 at 8:18


















            draft saved

            draft discarded




















































            Thanks for contributing an answer to Stack Overflow!


            • Please be sure to answer the question. Provide details and share your research!

            But avoid



            • Asking for help, clarification, or responding to other answers.

            • Making statements based on opinion; back them up with references or personal experience.


            To learn more, see our tips on writing great answers.




            draft saved


            draft discarded














            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53898429%2finteroperabilty-between-c-and-c-atomics%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown





















































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown

































            Required, but never shown














            Required, but never shown












            Required, but never shown







            Required, but never shown







            Popular posts from this blog

            If I really need a card on my start hand, how many mulligans make sense? [duplicate]

            Alcedinidae

            Can an atomic nucleus contain both particles and antiparticles? [duplicate]