Mutex lock/unlock order - c++

I am interesting whether mutexes(not depending on particular language) must keep the order of lock/unlock?
Here is example C++ code:
std::mutex testVecMtx;
std::vector<int> testVec;
void testPush(int v){
std::lock_guard<std::mutex> lk(testVecMtx);
if (testVec.empty()){
// wait some time to get more threads waiting on testVecMtx
std::this_thread::sleep_for(std::chrono::milliseconds(3000));
}
testVec.push_back(v);
}
void Main_TEST(){
std::list<std::thread> thList;
for (int i = 0; i < 1000; i++){
thList.push_front(std::thread(testPush, i));
}
for (auto &i : thList){
if (i.joinable()){
i.join();
}
}
bool ok = true;
for (int i = 0; i < (testVec.size() - 1) && ok; i++){
ok = testVec[i + 1] - testVec[i] == 1;
}
if (ok){
int stop = 243; // 1st breaking point here...
}
else{
int stop = 432; // ...and 2nd here
}
}
After running this code in VS2013 serveral times in Debug and Release(with some changes to get code not optimized out) mode I always get hit only on 1st breakpoint.

No, there are no guarantees about the order. It just happens to work this way on your machine(for instance, on my computer ok is not always true).

No, there are no guarantees about the order.
You can try with condition variables:
#include <thread>
#include <vector>
#include <array>
#include <list>
#include <mutex>
#include <condition_variable>
const int MAX = 100; //***
std::mutex testVecMtx;
std::vector<int> testVec;
std::array<std::condition_variable,MAX+1> Notifications; //***
int Current = 0; //***
void testPush(int v){
std::unique_lock<std::mutex> lk(testVecMtx);
while (v != Current){
Notifications[v].wait(lk);
}
testVec.push_back(v);
Current++;
if (v != MAX)
Notifications[v+1].notify_all();
}
int main(){
std::list<std::thread> thList;
for (int i = 0; i < MAX; i++){
thList.push_front(std::thread(testPush,i));
}
for (auto &i : thList){
i.join();
}
bool ok = true;
for (int i = 0; i < (testVec.size() - 1) && ok ;i++){
ok = (testVec[i + 1] - testVec[i]) == 1;
}
if (ok){
int stop = 243; // 1st breaking point here...
// std::cout<<"Ok"<<std::endl;
}
else{
int stop = 432; // ...and 2nd here
}
}

Related

Why does my boost::circular_buffer crash when accessed using an iterator?

In the following program, when I access elements from the front of the circular buffer using *(begin_iterator + index) I get a crash. But if I access the same elements using buffer[index], the crash is eliminated. (See the two commented lines below). Why does this happen?
#include <boost/circular_buffer.hpp>
#include <thread>
auto buffer = boost::circular_buffer<int>(5000);
void f1()
{
const auto N = 500;
while (true) {
// Make sure the buffer is never empty
if (buffer.size() < N+1) {
continue;
}
auto front = buffer.begin();
volatile auto j = int{};
for (auto i = 0; i < N; ++i) {
// j = *(front + i); // un-commenting this causes a crash
// j = buffer[i]; // un-commenting this doesn't
}
buffer.erase_begin(N);
}
}
void f2()
{
while (true) {
// Make sure the buffer is at most half-full.
if (buffer.size() > buffer.capacity() / 2) {
continue;
}
static auto k = 0;
buffer.push_back(k++);
}
}
int main()
{
auto t1 = std::thread{f1};
auto t2 = std::thread{f2};
t1.join();
}
You're experiencing undefined behavior because you're reading and modifying the same object unsynchronized from multiple threads.
Coding it one way or another might eliminate the crash, but the program is still wrong.
If we add a mutex, then there's no crash anymore:
#include <boost/circular_buffer.hpp>
#include <thread>
#include <mutex>
boost::circular_buffer<int> buffer(5000);
std::mutex mtx;
void f1()
{
const auto N = 500;
while (true) {
std::lock_guard<std::mutex> lock(mtx);
// Make sure the buffer is never empty
if (buffer.size() < N + 1) {
continue;
}
auto front = buffer.begin();
volatile auto j = int{};
for (auto i = 0; i < N; ++i) {
j = *(front + i); // is OK now
// j = buffer[i];
}
buffer.erase_begin(N);
}
}
void f2()
{
while (true) {
std::lock_guard<std::mutex> lock(mtx);
// Make sure the buffer is at most half-full.
if (buffer.size() > buffer.capacity() / 2) {
continue;
}
static auto k = 0;
buffer.push_back(k++);
}
}
int main()
{
auto t1 = std::thread{ f1 };
auto t2 = std::thread{ f2 };
t1.join();
}

compiling in GPU using thrust (prime numbers)

I have a code written in thrust in C language, but i am not able to compile it since i dont have a GPU. My code is supposed to calculate the first 1000 prime numbers. That's it. But the problem is
1 - i can not compile it since i do not have a GPU.
2 - Since i can not compile it, i can not know if it really calculates prime numbers.
Here is my code:
`struct prime{
_host_ _device_
void operator()(long& x){
bool result = true;
long stop = ceil(sqrt((float)x));
if(x%2!=0){
for(int i = 3;i<stop;i+=2){
if(x%i==0){
result = false;
break;
};
}
}else{
result = false;
}
if(!result)
x = -1;
}
};
void doTest(long gen){
using namespace thrust;
device_vector<long> tNum(gen);
thrust::sequence(tNum.begin(),tNum.end());
}
int main(){
doTest(1000);
return 0;
}`
Could someone help me compile my code and display the result, and if not working correctly, then help me fix it?
If you don't have a GPU, then use thrust::host_vector instead of thrust::device_vector.
I've cleaned up your code, and it's running on the CPU like this:
#include <thrust/host_vector.h>
#include <thrust/device_vector.h>
#include <thrust/sequence.h>
#include <iostream>
int main()
{
thrust::host_vector<long> tNum(1000);
thrust::sequence(std::begin(tNum), std::end(tNum));
thrust::transform(std::cbegin(tNum), std::cend(tNum), std::begin(tNum), [](long x)
{
bool result = true;
long stop = (long)std::ceil(std::sqrt((float)x));
if (x % 2 != 0) {
for (long i = 3; i < stop; i += 2) {
if (x % i == 0) {
result = false;
break;
};
}
} else {
result = false;
}
if (!result) x = -1;
return x;
});
for (const auto& element : tNum) if (element>0) std::cout << element << ", ";
std::cout << std::endl;
std::cin.ignore();
return 0;
}

Synchronize two functions

I am currently trying to sync two different funtions to fill a vector with numbers. One function fills the vector with even numbers, the other one with odd numbers. The numbers should be inserted in the correct order in the vector (that the result is: numbers [i] = i)
void incOdd(std::vector<uint8_t> *numbers, TestMutex *inEven, TestMutex *inOdd){
for(uint8_t i = 1; i < 100;i++){
if((i + 1) % 2 == 0){
continue;
}
inOdd->lock();
(*numbers).push_back(i);
inOdd->unlock();
}
}
void incEven(std::vector<uint8_t> *numbers, TestMutex *inEven, TestMutex *inOdd){
for(uint8_t i = 0; i < 100;i++){
if(i % 2 != 0){
continue;
}
inEven->lock();
(*numbers).push_back(i);
inEven->unlock();
}
}
Just a Note: Test mutex is just a class that is a child of the mutex where only the lock and unlock function are defined. ( the lock function has a counter for the tests later)
Since it is a practice task, the parameters must not be changed and work only in parentheses. I Already tried to use condition_variables to let them wait for each other but it doesn't worked.
I have no other approaches and hope you have a solution for me
Update:
TEST_CASE("synchronize [thread]") {
TestMutex inEven;
TestMutex inOdd;
inEven.lock();
std::vector<uint8_t> numbers;
std::thread even(incEven,&numbers,&inEven,&inOdd);
std::thread odd(incOdd,&numbers,&inEven,&inOdd);
odd.join();
even.join();
for(size_t i=0; i < numbers.size(); i++) {
REQUIRE(numbers[i] == (i+1));
}
REQUIRE(numbers.size() == 100);
REQUIRE(inEven.c==51);
REQUIRE(inOdd.c==50);
}
So this is the Test Case i have to solve for this question i am not allowd to change this.
See my code which is self explanatory:
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std;
condition_variable cv;
bool odd = false;
typedef mutex TestMutex;
void incOdd(std::vector<uint8_t> *numbers,TestMutex *inEven,TestMutex *inOdd) {
for (uint8_t i = 0; i < 100; i++) {
if (i % 2 == 0) {
unique_lock<mutex> lock(*inEven);
cv.wait(lock, []() { return odd == false; });
numbers->push_back(i);
odd = true;
cv.notify_one();
}
}
}
void incEven(std::vector<uint8_t> *numbers, TestMutex *inEven, TestMutex *inOdd) {
for (uint8_t i = 0; i < 100; i++) {
if (i % 2 != 0) {
unique_lock<mutex> lock(*inEven);
cv.wait(lock, []() { return odd == true; });
numbers->push_back(i);
odd = false;
cv.notify_one();
}
}
}
int main()
{
vector<uint8_t> vec;
TestMutex mu;
TestMutex rmu; // redundant
thread thread1([&]() { incEven(&vec,&mu,&rmu); });
thread thread2([&]() { incOdd(&vec,&mu,&rmu); });
thread1.join();
thread2.join();
for (auto e : vec)
cout << int(e) << endl;
return 0;
}

C++ Bubble sort dynamically allocated array

I wrote a bubble sorting algorithm which sorts a dynamically allocated array using string comparison.
Here is my code:
void AddressBook::bubble_sort_address_book(){
bool swapped = true;
while(swapped){
swapped = false;
for(int i = 0; i < noOfEmployees; i++){
if(employees[i].combined_name() > employees[i+1].combined_name()){
Employee temp_employee = employees[i+1];
employees[i+1] = employees[i];
employees[i] = temp_employee;
}
}
}
}
My problem is pretty obvious, yet I can not seem to figure out how to solve it: The code sometimes fails on the line (in an undefined manner) :
Employee temp_employee = employees[i+1]
Its pretty obvious because if i is equal to the end of the array, accessing memory with i+1 results in undefined behaviour. However, if I stop the for loop with noOfEmployees-1, this does not happen but the first element is never sorted (obviously).
How can I implement bubble sort properly? It seems as such a trivial task. Am I missing something?
The following simplified version in pure C works fine:
int employees[10]= {3,1,7,6,9,7,1,0,2,6};
int noOfEmployees= 10;
void bubble_sort_address_book(void){
bool swapped = true;
int i;
while(swapped){
swapped = false;
for(i = 0; i < noOfEmployees-1; i++){
if(employees[i] > employees[i+1]){
int temp_employee = employees[i+1];
employees[i+1] = employees[i];
employees[i] = temp_employee;
swapped= true;
}
}
}
}
int main()
{
int i;
bubble_sort_address_book();
for (i=0; i<noOfEmployees; i++) {
printf("emp %d= %d\n", i, employees[i]);
}
return 0;
}
As you request, the function of variable swapped is to indicate that following a complete pass through the array no swap occurred and so it indicates the array is now sorted.
You can use an explicit bound on the outer loop.
You should also split things out into smaller functions.
bool operator <(Employee const & lhs, Employee const & rhs) {
return lhs.combined_name() < rhs.combined_name();
}
// a.k.a. std::swap
void swap(Employee & lhs, Employee & rhs) {
Employee temp(static_cast<Employee&&>(lhs)); // a.k.a. std::move
lhs = static_cast<Employee&&>(rhs);
rhs = static_cast<Employee&&>(temp);
}
void bubble_sort_impl(Employee * begin, Employee * end) {
for (; end != begin; --end) {
for (Employee * it = begin; it+1 != end; ++it) {
if (*(it+1) < *it) {
swap(*it, *(it+1));
}
}
}
}
// do we really need "bubble_" or "_address_book" in this name?
void AddressBook::bubble_sort_address_book() {
bubble_sort_impl(employees, employees + noOfEmployees);
}
another solution:
#include <iostream>
#include <vector>
using namespace std;
int employees[10] = { 3,1,7,6,9,7,1,0,2,6 };
void bubble_sort_address_book(void) {
bool swapped = true;
int i;
int noOfEmployees = 10;
while (swapped) {
swapped = false;
for (i = 1; i <= noOfEmployees ; i++) {
if (employees[i] > employees[i - 1]) {
int temp_employee = employees[i - 1];
employees[i - 1] = employees[i];
employees[i] = temp_employee;
swapped = true;
}
}
}
}
int main()
{
int i;
int noOfEmployees = 10;
bubble_sort_address_book();
for (i = 0; i<noOfEmployees; i++) {
printf("emp %d= %d\n", i, employees[i]);
}
return 0;
}

C++ threads for background loading

I have used std::sthread for background image loading. I create background job as this:
if (bgThreads.size() > MAX_THREADS_COUNT){
fclose(file);
return;
}
if (bgThreads.find(id) != bgThreads.end()){
fclose(file);
return;
}
std::shared_ptr<BackgroundPNGLoader> bg = std::make_shared<BackgroundPNGLoader>(file, id);
bgThreads[id] = bg;
bg->thread = std::thread(&BackgroundPNGLoader::Run, bg);
In BackgroundPNGLoader, I have:
struct BackgroundPNGLoader{
std::atomic<bool> finished;
FILE * f;
int id;
BackgroundPNGLoader() : finished(false) {}
void Run(){
///.... load data
finished.store(true);
}
}
In my main app, I have Update - Render loop running in main thread. In Update, I have:
std::list<int> finished;
for (auto & it : bgThreads)
{
if (it.second->finished)
{
if (it.second->thread.joinable())
{
it.second->thread.join();
}
finished.push_back(it.first);
//fill image data to texture or whatever need to be done on main thread
fclose(it.second->f);
}
}
for (auto & it : finished)
{
bgThreads.erase(it);
}
Is this considered safe? I am a little worried about spawning new threads every time I need new file open, there is no max limit.
First, avoid fopen/fclose and use C++' file I/O instead to avoid potential resource leaks when exceptions are thrown. Further, using a raw std::thread isn't necessary in most cases. For asynchronous tasks, std::async combined with futures is is the thing to go with.
std::async returns a potential result within a std::future, which can be retrieved later:
#include <future>
#include <thread>
#include <chrono>
#include <array>
#include <iostream>
#include <random>
size_t doHeavyWork(size_t arg)
{
std::mt19937 rng;
rng.seed(std::random_device()());
std::uniform_int_distribution<unsigned int> rnd(333, 777);
//simulate heavy work...
std::this_thread::sleep_for(std::chrono::milliseconds(rnd(rng)));
return arg * 33;
}
//wrapper function for checking whether a task has finished and
//the result can be retrieved by a std::future
template<typename R>
bool isReady(const std::future<R> &f)
{
return f.wait_for(std::chrono::seconds(0)) == std::future_status::ready;
}
int main()
{
constexpr size_t numTasks = 5;
std::array<std::future<size_t>, numTasks> futures;
size_t index = 1;
for(auto &f : futures)
{
f = std::async(std::launch::async, doHeavyWork, index);
index++;
}
std::array<bool, numTasks> finishedTasks;
for(auto &i : finishedTasks)
i = false;
size_t numFinishedTasks = 0;
do
{
for(size_t i = 0; i < numTasks; ++i)
{
if(!finishedTasks[i] && isReady(futures[i]))
{
finishedTasks[i] = true;
numFinishedTasks++;
std::cout << "task " << i << " ended with result " << futures[i].get() << '\n';
}
}
}
while(numFinishedTasks < numTasks);
std::cin.get();
}
std::async may launch separate threads using a thread pool.
First, you better do not spawn more threads than cores.
Here is a simple example using detach and letting threads informing about their statuses:
#include<thread>
#include<atomic>
struct task_data
{
};
void doHeavyWork(task_data to_do, std::atomic<bool>& done)
{
//... do work
//---
//--
done = true;
}
int main()
{
unsigned int available_cores = std::thread::hardware_concurrency();//for real parallelism you should not spawn more threads than cores
std::vector<std::atomic<bool>> thread_statuses(available_cores);
for (auto& b : thread_statuses)//initialize with all cores/threads are free to use
b = true;
const unsigned int nb_tasks = 100;//how many?
std::vector<task_data> tasks_to_realize(nb_tasks);
for (auto t : tasks_to_realize)//loop on tasks to spawn a thread for each
{
bool found = false;
unsigned int status_id = 0;
while (!found) //loop untill you find a core/thread to use
{
for (unsigned int i = 0; i < thread_statuses.size(); i++)
{
if (thread_statuses[i])
{
found = true;
status_id = i;
thread_statuses[i] = false;
break;
}
}
}
//spawn thread for this task
std::thread task_thread(doHeavyWork, std::move(t), std::ref(thread_statuses[status_id]));
task_thread.detach();//detach it --> you will get information it is done by it set done to true!
}
//wait till all are done
bool any_thread_running = true;
while (any_thread_running)//keep untill all are done
{
for (unsigned int i = 0; i < thread_statuses.size(); i++)
{
if (false == thread_statuses[i])
{
any_thread_running = true;
break;
}
any_thread_running = false;
}
}
return 0;
}