Shared global immutable objects in D - thread-safety

Is it safe to make a global (module scope) immutable object shared? Should I use shared or __gshared (as it seems for me safe too)?

https://dlang.org/articles/migrate-to-shared.html says:
Immutable data doesn't have synchronization problems, so the compiler doesn't place it in TLS.
("TLS" is thread local storage.)
So, it does not matter whether the immutable object is declared as shared.
For brevity, we can omit shared in this case.

Related

Container Thread Safety

I'm aware of Container Thread Safety topic listed there:
https://en.cppreference.com/w/cpp/container
But I want to know: can I use non-const member functions and const member functions concurrently without blocking (a mutex)?
More specific:
Can I use std::vector::push_back and std::vector::size concurrently?
Can I use std::set::insert and std::set::size concurrently?
This doesn't make a practical sense commonly, but I don't need an exact result of size which I'll use, I just need a valid result at the time when I call it.
P.S. My doubts are come from there: https://www.cplusplus.com/reference/set/set/insert/ where they say for std::set::insert that
Concurrently accessing existing elements is safe
So maybe getting the size of containter is also safe.
The main thread-safety rule of stl containers is that if more than one working thread is accessing a shared container, and at least one of them is non-const, then the threads should be synchronized. If you do not put any synchronizations, it will be undefined behavior.
if you take a look at the C++ reference here for std::vector::size(), it says:
Data Races
The container is accessed. No contained elements are accessed:
concurrently accessing or modifying them is safe.
As mentioned, the vector container will be accessed during the call to .size() and this access does not allow you to call non-const methods at the same time on the vector. If you push_back an element into the vector when you get the size of the vector by calling .size(), then the behavior of your program will be undefined.

Is there a robust implementation of condition_variable and mutex that can be stored in shared memory on Windows?

As described in this question, use of boost's interprocess_mutex and interproces condition_variable may result in a deadlock if the process holding the mutex crashes.
This is because boost's mutex is not a kernel object and therefore is not automatically released when the process holding it exits.
Is there a way in boost to use interprocess conditional variables with the mutex returned by a call to CreateMutex?
Just use CreateSemaphore() directly to implement condvars across multiple processes. You don't need to use Boost condvars. Windows provides a very rich set of well defined, fairly correct, named machine-wide synchronisation objects. Use those instead.

What's the purpose of copy relocation?

BACKGROUND:
If an executable file has a external data reference, which is defined in a shared object, the compiler will use copy relocation and place a copy in its .bss section.
Copy relocation is detailed in this site:
http://www.shrubbery.net/solaris9ab/SUNWdev/LLM/p22.html#CHAPTER4-84604
However, my question is:
Is it possible to implement it through GOT, just like the external data reference in shared object? The executable can indirectly accesses this external code through its GOT entry, and this GOT entry can be stuffed with the real address of this symbol in run-time.
I don't know why GCC doesn't implement it like this. What's the upside of copy relocation?
In languages like C and C++ addresses of objects with static storage duration qualify as address constants. It means that conceptually, at language level they are treated as if their values are "known" at compile time.
Of course, this is not the case in reality, when it comes to the matter in question. To counter that the compiler-linker-loader combination has to implement a dynamic mechanism that would provide full support the language-level concept of address constant. Intuitively a GOT-based mechanism, being based on full run-time indirection, would be much farther away from that concept than a load-time relocation-based mechanism.
For one thing, C language was designed as a language that requires no dynamic initialization of objects with static storage duration, i.e. conceptually there's no initializing startup code and no issues related to the order of initialization. But in a GOT-based implementation an initialization of a global variable with such address constant would require startup code to extract the actual value from GOT and place it into the variable. Meanwhile, a relocation-based approach produces a full illusion of such global variable beginning its life with the proper value without any startup code.
If you look at the features provided by the relocation mechanism, you will notice that they are in sync with the C specification of address constant. E.g. the final value might involve adding a fixed offset, which is intended to act as a loader-side implementation of C [] and -> operators, permissible in C address constant expressions.
Is it possible to implement it through GOT, just like the external data reference in shared object?
Yes. For this to work, you'll need to build code that is linked into the main executable with -fPIC. Since that is often less efficient (extra indirection), and usually not done, the linker has to do copy relocations instead.
More info here.

Releasing memory in smart pointer

When we are using dynamically allocated memory, the usefulness of the delete command is obvious - we need to let our program know that the memory at the pointer is no longer needed and can be repurposed.
Smart pointers in C++11 (e.g. unique_ptr) have a member function seemingly used for a similar purpose: release(). I thought the point of using smart pointers was to avoid having to manually handle the release of memory. Why is the release() function provided when, in this context, it seems pointless?
(pun intended)
unique_ptr::release is not equivalent to calling delete on the managed pointer. unique_ptrs are used when you want a sole entity owning a heap-allocated object. unique_ptr::release relinquishes ownership and returns the raw pointer. There might be instances when you no longer want the unique_ptr to own the managed data and yet not destroy the object - maybe you want to call a legacy API which takes a plain pointer and assumes ownership of it. Or perhaps you want your interface receive a unique_ptr but have many shared_ptrs having access to it in the implementation. So, the implementation would release from the unique_ptr and transfer ownership to one or more shared_ptrs.
unique_ptr only automatically releases memory when it goes out of scope or is assigned a new pointer, but you might want to release the memory before that (the most obvious reason would be optimizing memory usage).

Why do we need boost::thread_specific_ptr?

Why do we need boost::thread_specific_ptr, or in other words what can we not easily do without it?
I can see why pthread provides pthread_getspecific() etc. These functions are useful for cleaning up after dead threads, and handy to call from C-style functions (the obvious alternative being to pass a pointer everywhere that points to some memory allocated before the thread was created).
In contrast, the constructor of boost:thread takes a callable class by value, and everything non-static in that class becomes thread local once it is copied. I cannot see why I would want to use boost::thread_specific_ptr in preference to a class member any more than I would want to use a global variable in OOP code.
Do I horribly misunderstand anything? A very brief example would help, please. Many thanks.
thread_specific_ptr simply provides portable thread local data access. You don't have to be managing your threads with Boost.Thread to get value from this. The canonical example is the one cited in the Boost docs for this class:
One example is the C errno variable,
used for storing the error code
related to functions from the Standard
C library. It is common practice (and
required by POSIX) for compilers that
support multi-threaded applications to
provide a separate instance of errno
for each thread, in order to avoid
different threads competing to read or
update the value.

Resources