// A can I do this?
myString.load()->size()
Yes you can, but you do have a race condition if something else might be mutating or destructing/deallocating the string
to which the snapshot of myString
you received points. In other words, the situation after atomically retrieving the pointer is the same as for any std::string
object to which multiple threads might have pointers, except that...
There is the question of whether the atomic load
guarantees some particular construction/change to the string
- perhaps performed by whichever thread updated myString
to point to the particular string
instance you've load
ed a pointer to - will be visible to you. The default is to ensure this, but you might want to read over this explanation of the memory_order
parameter to load()
. Note that not explicitly asking for memory synchronisation does not keep you safe from mutating/destruction by other threads.
So, say myString()
is pointed successively at string
's a
, b
then c
, and your code retrieves &b
... as long as the string
b
isn't mutated or destructed/deallocated while you're calling size()
, you're ok. It doesn't matter that myString()
might be updated to point to c
before/during/after your call to b
's .size()
.
Taking a step back, it can be tricky for the program to know how long after you call load()
you might try to dereference the pointer, and if the b
object is to later be mutated or destructed/deallocated, the kind of call you propose doesn't cooperate in any synchronisation around that later mutation/destruction. You can obviously add such coordination in myriad ways (e.g. some other atomic counter/flag, notifying the would-be modifier/destructor/deleter using a condition variable...), or you might decide to accept such a race condition sometimes (e.g. perhaps if b
is known to be one of the newest entries in a generously sized LRU cache).
If you're doing something like cycling myString
around a number of static const string
instances, you don't have to worry about all the mutation/destruction stuff above (well, not unless you're accessing them before/after main()
).
// B can I do this?
char myFifthChar = *(myString.load()->c_str() + 5);
Yes, with all the caveats above.
// C can I do this?
char myCharArray[255];
strcpy(myCharArray, myString.load()->c_str());
Yes, as above (and subject to the buffer provided being large enough).
I'm pretty sure C is illegal because myString might be deleted in the meantime.
As above - that concern's equally valid for all the 3 uses you've mentioned, just somewhat more likely for C because copying takes more CPU cycles to complete, and rather than get garbage values back losing a race could cause a buffer overrun.