This question already has an answer here:
Multithreading with templated class member function
(1 answer)
Closed 7 years ago.
I have an object like this:
class Blocking_queue
{
private:
queue<T> my_queue;
unsigned int dim;
mutex m;
condition_variable cv;
}
In my main I want to create some threads which call the object methods:
Blocking_queue<int> q(6);
thread t(close, q);
How can I do my copy constructor with the mutex? I think that I cannot simply do like this because it's not copiable
Blocking_queue(const Blocking_queue& source){
this->queue = source.queue;
this->dim = source.dim;
this->m = source.m;
this->cv = source.cv;
}
If you really want to copy the contents of the queue and have two separate, independent queues, you should copy the contents and initialize new mutexes, like this:
Blocking_queue(const Blocking_queue& source){
this->queue = source.queue;
this->dim = source.dim;
}
Or better yet, like this:
Blocking_queue(const Blocking_queue& source):
queue(source.queue),
dim(source.dim) {
}
But it's probably not what you want. If you want this object to be shared between threads, pass it by reference:
Blocking_queue<int> q(6);
thread t(close, ref(q));
Or, if the thread may last longer than the scope of the function where you defined the queue, use shared pointers to make sure the object remains valid.
auto q = make_shared<Blocking_queue<int>>(6);
thread t(close, q));
Related
This question already has answers here:
How to insert a conditional_variable object into a Vector?
(4 answers)
Closed 1 year ago.
I try to insert into vector with a class including condition variable,my code as follow:
class LockRequest {
public:
LockRequest( ) : granted_(false) {}
bool granted_;
};
class LockRequestQueue {
public:
std::list<LockRequest> request_queue_;
std::condition_variable cv_; // for notifying blocked transactions on this rid
bool upgrading_ = false;
};
int main(){
LockRequestQueue request;
std::vector<LockRequestQueue> vecs;
vecs.push_back(request);
return 0;
}
but I get error.When I remove the condition variable cv_,the result is correct.How can I fix this problem??
std::condition_variable is not
copy constructible,
move constructible,
copy assignable or
move assignable.
So adding it directly to any class as a member would also add those qualifications to that class too.
In order to avoid that, we use an extra level of indirection, for example, a std::unique_ptr to hold a pointer to it.
class LockRequestQueue {
public:
LockRequestQueue() // make a condition variable and assign it to the unique_ptr
:cv_(std::make_unique<std::condition_variable>())
{}
std::list<LockRequest> request_queue_;
std::unique_ptr<std::condition_variable> cv_; //notice the unique_ptr
bool upgrading_ = false;
};
And now, in our main() function, we use std::move to push to the vector since std::unique_ptr itself is not copy constructible:
int main()
{
LockRequestQueue request;
std::vector<LockRequestQueue> vecs;
vecs.push_back(std::move(request)); //notice the std::move
return 0;
}
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 1 year ago.
Improve this question
I have a method in class like this:
int Class1::addObject(Struct1 object)
{
object.objectID = objCounter;
objCounter++;
vector1.push_back(object); // this line throws exception
// unrelated line
return object.objectID;
}
Vector is defined and initialized as following:
std::vector<Struct1> vector1 = {};
The biggest problem is that this exception occurs sometimes and I am afraid that there is memory leakage.
I am using C++14 and I don't think there is problem with that (because I read somewhere that before C++11 vector was not allowed). Also the Struct1 object is initialized before calling this method, so it isn't about that neither.
Could it be because Visual Studio doesn't have Administrator privileges or it may be due to vector changing location in memory when adding more elements and process couldn't allocate more memory (I think this can be it)? The third possible suspect is multithreading: since I am accessing Class1 with 4 threads at the time, but every thread has it's own group of objects that it adds/removes, and that group is never the same for 2 or more threads?
Update 1:
Definition of Struct1 (copy and default constructors are added when someone suggested in answers)
struct Struct1
{
int objectID;
Struct1ObjectType objectType;
GLfloat array1[2];
GLfloat array2[3];
GLfloat objectSize;
Struct1() {}
Struct1(const Struct1& cs1)
{
objectID = cs1.objectID;
objectType = cs1.objectType;
for (int i = 0; i < 2; i++)
array1[i] = cs1.array1[i];
for (int i = 0; i < 3; i++)
array2[i] = cs1.array2[i];
objectSize = cs1.objectSize;
}
};
Re:
The third possible suspect is multithreading: since I am accessing Class1 with 4 threads at the time, but every thread has it's own group of objects that it adds/removes, and that group is never the same for 2 or more threads?
Regardless of objects being different, you can't access the same vector from multiple threads without synchronization.
One way of doing this is with mutex:
std::mutex m_lock;
then when you need to access that vector:
{
const std::lock_guard<std::mutex> l(m_lock);
vector1.push_back(object); // this line throws exception
}
The C++ standard library uses "copy semantics" for elements in its collections. The code line vector1.push_back(object); cause the copy-construction of a Struct1 object (the object that is stored inside the std::vector<>, which is a copy of the object that is in the parameter).
You haven't shown the definition of class Struct1 so I don't know how it's being copy-constructed, but I would check there to see if you have a programming bug in that code.
Here's my problem.
I have a structure like this.
struct threadInfo
{
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
When building my code I get this error
Error C2280 threadInfo::threadInfo(const threadInfo &): attempting
to reference a deleted function PriorityListMutex
From my understanding it means that the constructor for threadInfo is called and it tries to copy the mutex which is not possible.
I don't have much experience with c++ and even though I somewhat understand what is happening, I'm not sure how to attempt to fix this. Any help would be great!
Here is the code that uses ThreadInfo
threadInfo info;
info.priorityLevel = priority;
priorityListMutex.lock();
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info.priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info.cv.wait(lock);
I guess the structure is being copied somewhere in there, but I'm completely missing where.
You can solve your problem by avoiding copies and emplacing the structs directly in the list. This does require a custom constructor though. I've shortened your code sample to only show the emplacing portion:
#include <mutex>
#include <condition_variable>
#include <list>
struct threadInfo
{
explicit threadInfo(int prio) : priorityLevel(prio) {}
std::condition_variable cv;
std::mutex m;
int priorityLevel;
};
int main()
{
std::list<threadInfo> threadList;
int priorityLevel = 0;
for (std::list<threadInfo>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < priorityLevel)
{
threadList.emplace(it, priorityLevel);
break;
}
else if (it == threadList.end())
{
threadList.emplace_back(priorityLevel);
break;
}
}
return 0;
}
In the Standard C++ Library, classes related to threading, like mutex, do not have a copy constructor.
When an assignment involves two objects, like
Class b(10);
Class a = b;
At the second line, we try to create an object initializing from another object. This makes the compiler look for a copy constructor, a constructor developed specifically for this purpose.
Since having two identical copy of a mutex is not good, the library doesn't use such method for thread related classes.
Usually compilers create default copy-constructors in case they are needed, but when a class a property of this type it cannot do so, so it gives you and error.
To solve, you will have to explicitly define a copy constructor and handle manually. Beware, you should keep in mind that things related to threads like mutex and cv should not exists in more than one copy.
The copy constructor of mutex is deleted explicitly. You can't copy a mutex, however, if what you are doing is moving rather than copying (e.g. you won't need the old value of you threadInfo object) than you can move the mutex using std::move and writing a move constructor for your threadInfo object.
However, a move constructor can cause hard to spot bug so I wouldn't recommend that. A more straight forward way would be to wrap your "info" object in a pointer and use that. You can achieve that as such:
auto info = std::make_shared<threadInfo>{};
info->priorityLevel = priority;
priorityListMutex.lock();
for (std::list<std::shared_ptr<threadInfo>>::iterator it = threadList.begin(); it != threadList.end(); it++)
{
if ((*it).priorityLevel < info->priorityLevel)
{
threadList.insert(it, info);
break;
}
else if (it == threadList.end())
{
threadList.push_back(info);
break;
}
}
priorityListMutex.unlock();
std::unique_lock<std::mutex> lock(info.m);
info->cv.wait(lock);
Do note however, that in this case I'm using a shared_ptr, which is the "easiest" way to do this since it won't break anything but probably not want you want to do, what you most likely want to do, is give the 'threadList' object ownership of your info object. in which case you would declare it as a unique_ptr:
auto info = std::make_uniq<threadInfo>{};
and move it into the threadList:
threadList.insert(it, std::move(info));
This question already has answers here:
Is local static variable initialization thread-safe in C++11? [duplicate]
(2 answers)
Closed 6 years ago.
Suppose I have a class with three static functions like this :
#include <vector>
#include <iostream>
using namespace std;
#include <thread>
class Employee
{
};
class client
{
public:
void Doprocessing()
{
//is this thread safe in c++11/14
static int i = CreateEmployee();
//does it look good to use static variable like this to make it thread safe?
static int k = ProcessEmploye();
}
private:
static int CreateEmployee()
{
static Employee * e = new Employee();
InsertEmployee(e);
return 1;
}
static int InsertEmployee(Employee *e)
{
vec.push_back(e);
return 1;
}
static int ProcessEmploye()
{
Employee* e = vec[0];
//do something with e
//...
//.
//Suppose 10 -20 lines
return 1;
}
static std::vector<Employee*> vec;
};
std::vector<Employee*> client::vec;
void func()
{
client cobj;
cobj.Doprocessing();
}
const int No_Of_Threads = 10;
int main() {
std::thread * threadpointer = new std::thread[No_Of_Threads];
std::srand(11);
for (int i = 0; i < No_Of_Threads; i++)
{
threadpointer[i] = std::thread(func);
}
for (int i = 0; i < No_Of_Threads; i++)
{
threadpointer[i].join();
}
delete[] threadpointer;
std::cout << " Good" << std::endl;
return 0;
}
My questions are :
1)If I use static int i = Somefunc() and no matter how bulky somefunc is, will be called once and will it be thread safe ?
2) if answer of 1) is yes, Does it look good to programers eyes to use static int i = SomeFunc() for above purpose.
Yes, it will be thread safe, but only since C++11. Static variables are initialized in thread safe way, they are often also called magic statics.
For more see here: http://en.cppreference.com/w/cpp/language/storage_duration#Static_local_variables
If multiple threads attempt to initialize the same static local variable concurrently, the initialization occurs exactly once (similar behavior can be obtained for arbitrary functions with std::call_once).
Note: usual implementations of this feature use variants of the double-checked locking pattern, which reduces runtime overhead for already-initialized local statics to a single non-atomic boolean comparison.
Also - in your code you call CreateEmployee(); during initialization of static i, and CreateEmployee( also initializes a static variable. This should also be OK, you can find in standard following footnote:
The implementation must not introduce any deadlock around execution of the
initializer.
As to your second question, from the code you have shown I dont see that it is OK to use static variable as a way to gain thread safety.
Are you aware that specifying a variable as static inside function body allows you to assign it only once? This means your CreateEmployee() will always return the same Employee instance.
I have a situation in which i need to instantiate a vector of boost::threads to solve the following:
I have a class called Instrument to hold Symbol information, which looks something like below:
class Instrument
{
public:
Instrument(StringVector symbols, int i);
virtual ~Instrument();
const Instrument& operator= (const Instrument& inst)
{
return *this;
}
String GetSymbol() { return Symbol_; }
LongToSymbolInfoPairVector GetTS() { return TS_; }
bool OrganiseData(TimeToSymbolsInfoPairVector& input, int i);
static int getRandomNumber(const int low, const int high);
static double getProbability();
bool ConstructNewTimeSeries(const int low, const int high);
bool ReconstructTimeSeries(TimeToSymbolsInfoPairVector& reconstructeddata, int i);
private:
LongToSymbolInfoPairVector TS_;
String Symbol_;
const int checkWindow_;
String start_, end_;
long numberofsecsinaday_;
static std::default_random_engine generator_;
};
This class will have as many objects as the number of symbols. These symbols shall be accessed in another class Analysis for further work, whose constructor accepts the vector of the above Instrument class, as shown below.
class Analysis
{
public:
Analysis(std::vector<Instrument>::iterator start, std::vector<Instrument>::iterator end);
virtual ~Analysis();
bool buildNewTimeSeries(TimeToSymbolsInfoPairVector& reconstructeddata);
bool printData(TimeToSymbolsInfoPairVector& reconstructeddata);
private:
std::vector<Instrument> Instruments_;
};
Now i want to multithread this process so that i can separate out say 7 symbols per thread and spawn out, say, 4 threads.
Following is the updated main.
std::vector<Instrument>::iterator block_start = Instruments.begin();
int first = 0, last = 0;
for (unsigned long i=0; i<MAX_THREADS; i++)
{
std::vector<Instrument>::iterator block_end = block_start;
std::advance(block_end, block_size);
last = (i+1)*block_size;
Analysis* analyzed = new Analysis(block_start, block_end /*first, last*/);
analyzed->setData(output, first, last);
threads.push_back(std::thread(std::bind(&Analysis::buildNewTimeSeries, std::ref(*analyzed))));
block_start = block_end;
first = last;
}
for (int i=0; i<MAX_THREADS; i++)
{
(threads[i]).join();
}
This is evidently incorrect, although i know how to instantiate a thread's constructor to pass a class constructor an argument or a member function an argument, but i seem to be facing an issue when my purpose is:
a) Pass the constructor of class Analysis a subset of vector and
b) Call the buildNewTimeSeries(TimeToSymbolsInfoPairVector& reconstructeddata)
for each of the 4 threads and then later on join them.
Can anyone suggest a neat way of doing this please ?
The best way to go about partitioning a vector of resources (like std::vector in ur case) on to limited number of threads is by using a multi-threaded design paradigm called threadpools. There is no standard thread-pool in c++ and hence you might have to build one yourself(or use open source libraries). You can have a look at one of the many good opensource implementations here:- https://github.com/progschj/ThreadPool
Now, I am not going to be using threadpools, but will just give you a couple of suggestions to help u fix ur problem without modifying ur core functionality/idea.
In main you are dynamically creating vectors using new and are passing on the reference of the vector by dereferencing the pointer. Analysis* analyzed = new. I understand that your idea here, is to use the same vector analysis* in both main and the thread function. In my opinion this is not a good design. There is a better way to do it.
Instead of using std::thread use std::async. std::async creates tasks as opposed to threads. There are numerous advantages using tasks by using async. I do not want to make this a long answer by describing thread/tasks. But, one main advantage of tasks which directly helps you in your case is that it lets you return values(called future) from tasks back to the main function.
No to rewrite your main function async, tweak your code as follows,
Do not dynamically create a vector using new, instead just create a
local vector and just move the vector using std::move to the task
while calling async.
Modify Analysis::buildNewTimeSeries to accept rvalue reference.
Write a constructor for analysis with rvalue vector
The task will then modify this vector locally and then
return this vector to main function.
while calling async store the return value of the async
calls in a vector < future < objectType > >
After launching all the tasks using async, you can call the .get() on each of the element of this future vector.
This .get() method will return the vector modified and returned from
thread.
Merge these returned vectors into the final result vector.
By moving the vector from main to thread and then returning it back, you are allowing only one owner to have exclusive access on the vector. So you can not access a vector from main after it gets moved to thread. This is in contrast to your implementation, where both the main function and the thread function can access the newly created vector that gets passed by reference to the thread.