C++11 lock free stack - c++11

I'm reading C++ Concurrency in Action by Anthony Williams, and don't understand its push implementation of the lock_free_stack class.
Why on earth the atomic load is not in the while loop ? The reason he gave is:
You therefore don’t have to reload head each time through the loop,
because the compiler does that for you.
But I don't get the picture. Can someone shed some light on this?
template<typename T>
class lock_free_stack
{
private:
struct node
{
T data;
node* next;
node(T const& data_) :
data(data_)
{}
};
std::atomic<node*> head;
public:
void push(T const& data)
{
node* const new_node=new node(data);
new_node->next=head.load();
while(!head.compare_exchange_weak(new_node->next,new_node));
}
};

The key is in the interface to compare_exchange_weak, which in this case takes 2 arguments. The first is a reference to the expected value, and the second is the desired. If the current value of the atomic is not equal to the expected input, it will return false and the expected input is set to the current value.
So in this case, what it's doing is setting new_node->next = head. Then, it's saying if head is still equal to new_node->next, swap it into head. If it's no longer that value, it uses the reference to new_node->next to assign it the current value of head. Since every iteration of the loop that fails also replaces new_node->next with the current value of head, there is no read to duplicate that in the body of the loop.

From the documentation of compare_exchange_weak:
Atomically compares the value stored in *this with the value of
expected, and if those are equal, replaces the former with desired
(performs read-modify-write operation). Otherwise, loads the actual
value stored in *this into expected (performs load operation).
As you see, otherwise the actual value of head is loaded into expected.

Related

memory barrier usage with CAS operations

In the code snippet from CPP reference, the memory barriers std::memory_order_release and std::memory_order_relaxed are used for the success and failure cases respectively. When is it OK to use std::memory_order_release for both or std::memory_order_relaxed for both?
template<class T>
struct node
{
T data;
node* next;
node(const T& data) : data(data), next(nullptr) {}
};
template<class T>
class stack
{
std::atomic<node<T>*> head;
public:
void push(const T& data)
{
node<T>* new_node = new node<T>(data);
// put the current value of head into new_node->next
new_node->next = head.load(std::memory_order_relaxed);
// now make new_node the new head, but if the head
// is no longer what's stored in new_node->next
// (some other thread must have inserted a node just now)
// then put that new head into new_node->next and try again
while(!std::atomic_compare_exchange_weak_explicit(
&head,
&new_node->next,
new_node,
std::memory_order_release,
std::memory_order_relaxed))
; // the body of the loop is empty
// note: the above loop is not thread-safe in at least
// GCC prior to 4.8.3 (bug 60272), clang prior to 2014-05-05 (bug 18899)
// MSVC prior to 2014-03-17 (bug 819819). See member function version for workaround
}
};
Using relaxed for both would not be safe. If the compare_exchange succeeds, then head is updated with the value of new_node, and other threads reading head will get that pointer. However, without release ordering, the value written to new_node->next (now head->next) may not be globally visible yet, so if the other thread tries to read head->next it may see garbage, or misbehave in other ways.
Formally, the write to new_node->next needs to happen before any other thread tries to read it, which can only be ensured by having release ordering on the store that signals other threads that the value is ready. (Likewise, the thread that reads head needs to use acquire ordering.) With relaxed ordering on the success store, the happens-before relationship is not there, so the code has a data race and its behavior is undefined.
Using release for both would not make sense, because release ordering only makes sense for stores, and in the failure case, no store is performed. In fact, for this reason, passing std::memory_order_release for the failure ordering is actually illegal; this is stated on the page where you got the sample code from. Using acquire or seq_cst would be safe (stronger ordering is always safe) but unnecessary, and might cause a needless performance hit.

memory leak delete linked list node

Newbie question. Suppose I have a C++11 linked list implementation with
template <typename X> struct Node {
X value;
Node* next;
Node(X x) {
this->value = x;
this->next = nullptr;
}
};
and later in the code I create a pointer variable
X x = something;
Node<X>* node = new Node(x);
and still later I do
delete node;
Is the x stored within node destructed when this statement is executed?
You may tell me I should use std::list instead of writing my own, but right
now I'm just trying to educate myself on pointers.
Since you did not provide a custom desctructor the compiler will generate the default one for you, which (by default) call destructors on its elements.
Now, the answer to your question really depends on what your x is :) If it is an object that has a destructor (like std::string) - it will be properly destroyed. But if it is a "naked pointer" (like int *) - it will not get destroyed and will cause a memory leak.
N.B. You create your x on a stack so I really-really-really hope that X provides proper copy semantics, otherwise you may end up with an invalid object stored in your node!

Explicit invocation of ctor for allocation of memory

Consider the following class:
class Vector{
int dim; //dimension of array v
Complex* v; //Complex is another class
public:
Vector(int dim = 0):dim(dim){(dim)?(v=new Complex[dim]):(v=nullptr);}
Vector(int dim, const Complex* c):dim(dim),v(new Complex[dim]){
for(int i=0;i<dim;i++) v[i]=c[i];}
Vector(const Vector& a):dim(a.dim),v(new Complex[a.dim]){
for(int i=0;i<dim;i++) v[i]=a.v[i];}
~Vector(){if(dim)delete [] v,v=nullptr;}
friend Vector& operator >> (Vector& is,Complex& z){
Vector copie(is);
is.~Vector();
is.Vector::Vector(is.dim+1);}
};
I try to overload the >> operator in order to add elements to v.
My idea was to create a copy, then call dctor and the ctor for the object to
be modified via >> operator.
I'm stuck after getting this error:
In function ‘Vector& operator>>(Vector&, Complex&)’:
main.cc:56:20: error: cannot call constructor ‘Vector::Vector’ directly
is.Vector::Vector(is.dim+1);
I'm not allowed to use containers!!
Please help me!
That's right, you can't call the constructor directly. Probably you want to use placement new.
friend Vector& operator >> (Vector& is,Complex& z){
Vector copie(is);
is.~Vector();
// is.Vector::Vector(is.dim+1);
new(&is) Vector(is.dim + 1);
return is;
}
Even then the code may not be semantically correct.
Having said that, this is not the recommended way to do it for
the last 20 years. Watch this Jon Kalb "Exception-Safe Code, Part
I" for an explanation (the example is almost the same). The
recommended way is to implement this in terms of other operations like
copy or swap.
Minor syntactic detail, operator>> is confusing, use operator<< at worst.
There is no need for calling the destructor and calling the constructor. Steps you can take to make your function work:
Allocate memory to hold the current objects plus the additional object.
Copy the objects from the old memory location to the new memory location.
Delete the old memory.
Associate the newly allocated memory with the input object.
friend Vector& operator>>(Vector& is, Complex& z){
// Allocate memory
Complex* vnew = new Complex[dim+1];
// Copy objects to new memory.
std::copy(is.v, is.v + is.dim, vnew);
vnew[is.dim] = z;
// Delete the old memory.
delete [] is.v;
// Use the new memory
is.v = vnew;
// Increment dim.
is.dim++;
return is;
}
Having said that, I think you are using the wrong function to insert an element to Vector. operator>> is for extracting data from. operator<< is for inserting data to. You should use operator<< to insert an element to a Vector.
friend Vector& operator<<(Vector& is, Complex const& z){
...
}

Accessing object T in vector<unique_ptr<T>> without taking ownership

I have the following member variable in a class:
std::vector<std::unique_ptr<Object>> objects_;
I explicitly want the vector to maintain ownership at all times. I've seen suggestions that in order for a member function to access a pointer in the vector and make changes to the object T wrapped in the std::unique_ptr, we must move the pointer to calling code, i.e:
void foo(int i) {
auto object = std::move( vector.at( i ) ); // move object to caller (caller owns)
object->dosomething();
vector.at(i) = std::move(object); // move back into vector (vector owns)
}
Another method was to work with raw pointers:
void foo(int i) {
Object* object = vector.at( i ).get();
object->doSomething();
}
However, I've been working with this:
void foo(int i) {
auto& object = vector.at( i );
object->doSomething();
}
Which is the correct and most robust method for my case? Does this function ever take ownership of the data in the std::unique_ptr? Is there a way to access Object without playing with the std::unique_ptr?
(excuse me if my methods are incorrect, I hope I got the point across)
The first approach will not retain ownership of the object if object->dosomething() throws an exception (i.e. it is not exception safe) since the second std::move() statement will not be executed.
Assuming C++11, both of the other approaches are effectively equivalent, subject to the assumption that the owned pointer is not null. Under the same assumption, the code can be simplified to
void foo(int i)
{
vector.at(i)->doSomething();
}
which will work with all C++ standards (not just C++11 or later).
It is possible to access the object without monkeying with the unique_ptr - simply store the pointer elsewhere and use that. However, that does compromise the purpose of using std::unique_ptr in the first place. And is error-prone - for example, the std::unique_ptr can destroy the object, and leave those other pointers dangling.
If you are really that worried about the potential of your vector losing ownership, consider using a shared_ptr instead.

Is there a way to make a moved object "invalid"?

I've some code that moves an object into another object. I won't need the original, moved object anymore in the upper level. Thus move is the right choice I think.
However, thinking about safety I wonder if there is a way to invalidate the moved object and thus preventing undefined behaviour if someone accesses it.
Here is a nice example:
// move example
#include <utility> // std::move
#include <vector> // std::vector
#include <string> // std::string
int main () {
std::string foo = "foo-string";
std::string bar = "bar-string";
std::vector<std::string> myvector;
myvector.push_back (foo); // copies
myvector.push_back (std::move(bar)); // moves
return 0;
}
The description says:
The first call to myvector.push_back copies the value of foo into the
vector (foo keeps the value it had before the call). The second call
moves the value of bar into the vector. This transfers its content
into the vector (while bar loses its value, and now is in a valid but
unspecified state).
Is there a way to invalidate bar, such that access to it will cause a compiler error? Something like:
myvector.push_back (std::move(bar)); // moves
invalidate(bar); //something like bar.end() will then result in a compiler error
Edit: And if there is no such thing, why?
Accessing the moved object is not undefined behavior. The moved object is still a valid object, and the program may very well want to continue using said object. For example,
template< typename T >
void swap_by_move(T &a, T &b)
{
using std::move;
T c = move(b);
b = move(a);
a = move(c);
}
The bigger picture answer is because moving or not moving is a decision made at runtime, and giving a compile-time error is a decision made at compile time.
foo(bar); // foo might move or not
bar.baz(); // compile time error or not?
It's not going to work.. you can approximate in compile time analysis, but then it's going to be really difficult for developers to either not get an error or making anything useful in order to keep a valid program or the developer has to make annoying and fragile annotations on functions called to promise not to move the argument.
To put it a different way, you are asking about having a compile time error if you use an integer variable that contains the value 42. Or if you use a pointer that contains a null pointer value. You might be succcessful in implementing an approximate build-time code convention checker using clang the analysis API, however, working on the CFG of the C++ AST and erroring out if you can't prove that std::move has not been called till a given use of a variable.
Move semantics works like that so you get an object in any it's correct state. Correct state means that all fields have correct value, and all internal invariants are still good. That was done because after move you don't actually care about contents of moved object, but stuff like resource management, assignments and destructors should work OK.
All STL classes (and all classed with default move constructor/assignment) just swap it's content with new one, so both states are correct, and it's very easy to implement, fast, and convinient enough.
You can define your class that has isValid field that's generally true and on move (i. e. in move constructor / move assignment) sets that to false. Then your object will have correct state I am invalid. Just don't forget to check it where needed (destructor, assignment etc).
That isValid field can be either one pointer having null value. The point is: you know, that object is in predictable state after move, not just random bytes in memory.
Edit: example of String:
class String {
public:
string data;
private:
bool m_isValid;
public:
String(string const& b): data(b.data), isValid(true) {}
String(String &&b): data(move(b.data)) {
b.m_isValid = false;
}
String const& operator =(String &&b) {
data = move(b.data);
b.m_isValid = false;
return &this;
}
bool isValid() {
return m_isValid;
}
}

Resources