How to prove that a concurrent object is linearizable? - concurrency

Is there a method to prove if an object is linearizable?
For example for the code below. How can I prove that the counter is linearizable?
here is the algorithm of the shared counter:
CompareAndSet R = new CompareAndSet(0);
increment() {
Boolean ret; int r;
repeat r = R.read(); ret = R.cas(r, r+1)
until(ret = true)
return
}
read() {
return R.read();
}
CompareAndSet is an object that contains:
an int v
a method read(): returns the value of v
a method cas(expected, update): takes 2 arguments: an expected value and an update value. If the current v value is equal to the expected value, then it is replaced by the update value; otherwise, the value is left unchanged. The method call returns a Boolean indicating whether the value v changed.

Generally speaking, you need to show that for each method that mutates the concurrent object, there is a "linearization point" where the method takes effect.
For your counter, it is trivial. If we assume that R.cas() is performed atomically, then your linearization point in increment() is when R.cas() succeeds in updating the value.

Related

Is there a way to have a version of std::atomic's compare_exchange_strong method that exchanges on inequality?

I have an atomic type where I need to atomically compare it with a value, and if the two values are not equal then exchange the value of the atomic.
Put another way, where compare_exchange_strong essentially does this operation atomically:
if (atomic_value == expected)
atomic_value = desired;
...I'm looking for a way to do this:
if (atomic_value != expected)
atomic_value = desired;
(Yes, I know compare_exchange_strong compares using bitwise equality, not the == operator. And I know the value of expected gets assigned when the comparison fails. This was just for illustration purposes. In my use case I don't need the value of the atomic regardless of the result of the comparison.)
Is there any way to do this without having to fall back on using a lock instead of std::atomic?
auto observed = atomic_value.load();
for (;;)
{
if (observed == expected){
break; // no exchange
}
if (atomic_value.compare_exchange_weak(observed, desired)) {
break; // successfully exchanged observed with desired
}
}
Sure it is suboptimal on architectures where HW has LL/SC, as C++ does not expose it. With LL/SC can have arbitrary condition.
You could use something like this:
#include <atomic>
#include <random>
std::atomic<int> atomVal;
int store_if_not_equal(int desired)
{
while (true) // or maxloop....
{
int expected = desired;
if (atomVal.compare_exchange_strong(expected, desired))
{
// values matched - do nothing
return 0;
}
else
{
//expected now contains the "current value"
// another thread could have sneaked in and changed it,
// so only replace it if it still matches
if (atomVal.compare_exchange_strong(expected, desired))
{
// success
return 1;
}
}
// if we arrive here, retry
}
}
int main()
{
atomVal.store(rand());
return store_if_not_equal(2);
}
Demo: https://godbolt.org/z/qWTP7canf
Just use the loop one ordinarily uses with compare-and-exchange, but instead of looping until the (new) expected value matches, loop either until it matches (and the store happens) or it equals the value in your != expected condition, since that’s the case in which you needn’t do anything. (Obviously don’t make the initial value be that “unless” value so that you can’t “succeed” the first time.)

Calling member function from non memebr function besides main? [duplicate]

In the following call-by-value example, I cannot understand why this code is not changing the value of the 5 to a 6.
Line 11 calls the function changeValue which has the value 6, so I would have thought 6 should be output, however 5 is still output?
#include <iostream>
using namespace std;
void changeValue(int value);
int main()
{
int value = 5;
changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
void changeValue(int value)
{
value = 6;
}
// This doesn't change the value from 5 to 6. 5 is output?
When you pass a function argument by value a copy of the object gets passed to the function and not the original object.Unless you specify explicitly arguments to functions are always passed by value in C/C++.
Your function:
void changeValue(int value)
receives the argument by value, in short a copy of value in main() is created and passed to the function, the function operates on that value and not the value in main().
If you want to modify the original then you need to use pass by reference.
void changeValue(int &value)
Now a reference(alias) to the original value is passed to the function and function operates on it, thus reflecting back the changes in main().
The value of value isn't changing because your int that you pass to the function is being copied into the stack frame of the function, then it's being changed, and when the function exits the copy is destroyed. The original in main's stackframe has not changed, since it was copied to the changeValue.
If you want to change it, you should pass a reference to an int, like so void changeValue(int& value), which says that the value isn't copied into the function, but merely an alias to the original is passed.
The behavior being observed currently is because passing by value means a copy of value (new integer with value of value) is actually passed to the function.
You have to pass by reference. For that the changeValue function will look like this:
void changeValue(int& value)
Rest of the code will remain the same.
Passing a variable by reference means the same int value declared in main is passed to the changeValue function.
Alternatively, you can pass a pointer to value to the changeValue function. That will however, require changes to how you call the function also.
int main()
{
int value = 5;
changeValue(&value);
...
return 0;
}
void changeValue(int* value)
{
*value = 6;
}
I'm including this answer as another way to think about writing functions and passing parameters by value.
You could also have written this code in the following way. That is pass the parameter by value, modify the local copy in the function, which does not alter the original value, and return the altered value.
int changeValue(int val)
{
val = 6;
return val;
}
int main()
{
int value = 5;
value = changeValue(value);
cout << "The value is : " << value << "." << endl;
return 0;
}
I am not in any way indicating my suggestion for your program is better than passing by reference. Instead, it is just the way learning a functional programming language (Clojure) is affecting the way I think.
Also, in languages like Python, you cannot modify a scalar parameter. You can only return a new value. So my answer is more of an exercise in thinking about things differently in C/C++.
AND:
the copy is assigned 6, but the change is not returned.
you need some reference or pointer if you want to change the value:
try using a method signature like:
void changeValue(int& value)
that will probably do what you expected
This is because the change in the changeValue () function is local. When you can changeValue (value) the contents of the variable value in main is copied in the formal argument named value (same name) of the function. Same name does not mean that the both are same. The value you are accessing inside the function is a copy of the value you had in the main.
To change you either need to pass it by reference or a pointer
void changeValue (int *val)
{
*val = 6;
}
call with changeValue (&value) in main
This works because the address of the variable value in main is passed and this address value is copied into val of the function. By doing *val we can get the contents of the address which was copied into val, which in actually the contents of value in main.
OR
void changeValue (int &val)
{
val = 6;
}

C++ Returning a Count

Can someone help me understand what does it mean to return a count?
I know the function involves a for-loop or a while-loop depending on the situation but I'm having trouble understanding the concept. I'll try to be as clear as possible.
Here's an example: I have two functions from a cryptography class: lock() and unlock(). They are polymorphic and they take no parameter and return no value. Does that mean the functions itself are blank?
And then I have another function encryptionLvl(). This one takes no parameter but they should return a count of the current number of encryption level, and that number should be incremented each time lock() is called and decremented each time unlock() is call.
How do I make this work?
Sorry if I'm confusing you. I'm a beginner at this programming, but I appreciate the effort.
A function can take no parameter and return void. You can think of such a function as a procedure. Although there is not return value, a procedure can affect your program through side effects. Like this:
class Counter {
int i;
public:
void increment() { i = i + 1; }
void reset() {
i = 0;
return; // The empty return statement is optional
}
int get() { return i; }
}
In your case, lock() does not return a value, but it increments the counter. unlock() does the opposite. encryptionLvl() is equivalent to get().

unable to change member value with method

I have an int member named size within my blob class whose value I am attempting to change within a method. Initially, I tried...
void blob::make_union(blob parent_blob){
parent=&parent_blob;
parent_blob.size = parent_size
}
Then I tried making a function whose sole purpose was to change the size value. Its worth noting that it changes the values within the function as verified by some cout statements.
int blob::change_size(int dat_size){
size=size+dat_size;
return this.size;
}
after making the new method change my other method
'void blob::make_union(blob parent_blob){
parent=&parent_blob;
int temp = size;
parent_blob.size = parent_blob.change_size(temp);
}'
still no dice. The following within main function does work.
if (charmatrix[m-1][n-1]==charmatrix[m][n]){
blobmatrix[m][n].make_union(blobmatrix[m-1][n-1]);
blobmatrix[m-1][n-1].size=blobmatrix[m-1][n-1].size + blobmatrix[m][n].size;
What am I doing wrong?
You are passing your blob class by value: you are making a copy of your blob object, and that is what the function change_size is working with.
void increment_number(int i) { ++i; }
void increment_number_ref(int& i) { ++i; }
int main()
{
int n = 6;
// This takes a copy of the number, and increments that number, not the one passed in!
increment_number(n);
// n == 6
// This passed our object by reference. No copy is made, so the function works with the correct object.
increment_number_ref(n);
// n == 7
return 0;
}
You need to pass your blob by reference (or as a pointer) if you wish to modify that object's value: see above.
In languages that have pass by reference and pass by value - if you have a situation where you make a change, and then suddenly the change is 'gone', you're almost certainly passing a copy vs a reference.
Try changing the prototype to pass in the blob by reference.

What is the use of this class?

What is this class for ?
class EqualTo {
private:
int target;
public:
EqualTo(int i) : target(i) {}
bool operator()(const int& i) const {
return i == target;
}
};
I have this class in a homework and they have used it with the find function just like :
it = list.find(EqualTo(3));
thanks
It's a functor; that is, an object that can be called like a function. It's more flexible than a function, since it can also contain state and use that when it's called. Here's an example of how to use it directly:
EqualTo is5(5); // Object to test whether numbers are 5
assert(is5(5)); // Returns true: value is 5
assert(!is5(42)); // Returns false: value is not 5
In this case, it takes a single value and returns a boolean to tell you whether that value satisfies some condition; a functor that does that is known as a predicate.
it = list.find(EqualTo(3));
This example uses a predicate to find an element in a container which matches the condition. In this case, it gives you an iterator pointing to the first element that equals 3.