Trouble with pointer to templated class method [duplicate] - c++

This question already has answers here:
Using c++ 11 multithreading on non-static member function
(1 answer)
How to pass member function of class to thread?
(2 answers)
Closed 7 months ago.
I was writing code for the following parallel processing task:
A std::vector<T> contains data items that need to be processed
A function process_data<T&> does that processing on such a single data item
In my software I want to do this for different types T, so I wrote a template class:
#include <mutex>
#include <thread>
#include <vector>
// Parallel processing class.
template <class T>
class parallel_processing {
public:
// Do parallel processing for all items in the vector.
void do_parallel_processing(std::vector<T>& items,
void (*item_processor)(T&),
size_t thread_count = 1)
{
// Check if we should do sequential processing after all.
if (thread_count <= 1) {
for (size_t i = 0; i < items.size(); i++)
item_processor(items[i]);
return;
}
// Proceed with parallel processing.
item_processor_ptr = item_processor;
items_ptr = &items;
next_item_index = 0;
// Spawn all threads.
std::vector<std::thread> threads;
for (size_t i = 0; i < thread_count; i++)
threads.push_back(std::thread(item_thread_worker));
// The current thread should also work hard. This has an advantage: calling join()
// (see below) blocks the thread, costing time. Method 'item_thread_worker' however
// only returns if all items are processed and thus all threads must also have
// finished (or are busy with their last item...).
item_thread_worker();
// Wait for all threads to finish and call join on them.
for (auto& this_thread : threads)
this_thread.join();
}
private:
// Get the next index to process.
int get_next_item_index()
{
const std::lock_guard<std::mutex> lock(next_item_index_mutex);
// Check if we're already done.
if (next_item_index >= (int)items_ptr->size())
return -1;
// Next index (first return, then increment).
return next_item_index++;
}
// Thread-worker method for items.
void item_thread_worker()
{
int item_index;
// Keep on processing while not all items are processed.
while ((item_index = get_next_item_index()) >= 0)
item_processor_ptr((*items_ptr)[item_index]);
}
// Properties.
std::mutex next_item_index_mutex; // For thread-safe access to 'next_item_index'.
int next_item_index; // Identifies the next item index to process.
void (*item_processor_ptr)(T& items); // The item processing function.
std::vector<T>* items_ptr; // Pointer to the vector with items to be processed.
};
The idea is simple and worked when it was not yet in a template class but separate functions but then of course could only be coded for a single type T:
A number of threads is started and they all run the same worker method
The workers pick a data item to be processed from the std::vector<T>, and call the function to process the selected item until all items are processed
The compiler (VS2019) complains about the line:
threads.push_back(std::thread(item_thread_worker));
'use & to create a pointer to a member'
So I tried threads.push_back(std::thread(&item_thread_worker)); which gives me the error:
''&': illegal operation on bound member function expression'
So I tried all kind of things: with (), with the class in front &parallel_processing<T>:: or &parallel_processing:: but all I get are different errors...
My knowledge about C++ is clearly not enough to solve this, help is appreciated.

As item_thread_worker is a non-static member function, it needs a object to be called with.
When you create your threads, you don't specify any objects. Those objects (which becomes the this pointer inside the functions) are passed as a hidden "first" argument.
Another point is that to get a pointer to a member function, you must use the pointer-to operator &. Unlike non-member functions, member functions do not decay to pointers to themselves. And you need to use the full scope, with the class-name.
So to create a thread using a non-static member function, that should be called on this object, you need to do std::thread(&parallel_processing::item_thread_worker, this).

Related

c++ class method thread [duplicate]

This question already has answers here:
Start thread with member function
(5 answers)
Closed 6 years ago.
i have a class that has a method that needs to be running continuously but also be able to receive input from user. So i thought i would make the method run separately using a thread.
the code looks something like this(just the backbone):
class SystemManager
{
private:
int command;
bool commandAcK;
bool running;
//other vars
public:
SystemManager()
{
//initialisation
}
void runningAlgorithm()
{
while (running)
{
if (commandAcK)
{
//solve command
}
//run algorithm
//print results
}
}
void readCmd()
{
cin >> command;
commandAcK = true;
}
};
int main()
{
SystemManager *SM = new SystemManager;
thread tRunning = SM->runningAlgorithm();
}
now the errors look like this:
no suitable constructor exists to convert from "void" to "std::thread"
Error C2440 'initializing': cannot convert from 'void' to 'std::thread'
i have found a new method and it doesn't give me any errors
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
the first thing i don't understand is that this method doesn't use an instance of the class just the generic function. How can i link it to a specific instance? I need it so it can read the values of the variables.
Secondly what does "&" in front of SystemManager do?
(&SystemManager::runningAlgorithm)
Thirdly is there a better way of doing it? Do you have any ideas?
Thank you in advance.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager()); does use an instance of your class. The instance it uses is SystemManager() which is a temporary and only available to the thread. If you need to share the instance then you need to create one yourself and pass it by reference to the thread like
SystemManager sys_manager;
std::thread tRunning([&](){sys_manager.runningAlgorithm();});
And now your call site and your thread have the same instance.
Also note that command and commandAck need to be protected by some sort of synchronization since you can write to them while reading causing a data race and subsequently undefined behavior. Using std::atmoic should work for you.
The constructor for std::thread accepts a functor, and optionally it's arguments. A functor is anything that can be "called" using operator().
Then it starts a thread and inside that thread calls your functor.
std::thread tRunning(&SystemManager::runningAlgorithm, SystemManager());
This will call the member function SystemManager::runningAlgorithm, passing in the only argument being this (SystemManager() creates a temporary instance).
Remember that member functions always accept this as the first argument.
&SystemManager::runningAlgorithm returns the address of the member function runningAlgorithm from the class SystemManager.
In modern C++ this code can be simplified (i.e. made more readable) with a lambda:
std::thread tRunning([]{ SystemManager().runningAlgorithm(); });
The line
thread tRunning = SM->runningAlgorithm();
takes the result of running SM->runningAlgorithm() (a void), and tries to construct a thread from it. If you look at the relevant constructor, though, you can see it needs a function-like argument (with possibly arguments).
One way of running it is through a lambda function:
thread tRunning(
[SM](){SM->runningAlgorithm();});
Two other things to note:
You should join the thread before its destructor is called, in this case:
tRunning.join();
You have a (short lived) memory leak. Why not just create it on the stack?
SystemManager SM;
thread tRunning(
[&](){SM.runningAlgorithm();});
tRunning.join();
Uhm... I guesss you need to study some of the basic concepts of c++, before going multithread.
However... In your code,
thread tRunning = SM->runningAlgorithm();
tries to put the result of your function (that is void... ) inside a variable of type thread... Non likely to be right.
Instead, your second code takes 2 arguments:
std::thread tRunning(
&SystemManager::runningAlgorithm, //a pointer to a method (a pointer to the code of your function, and that is why you use the "&", even though you could have left that out)
SystemManager()); // An instance of the value, built on the stack.
I guest that you are confused by the lack of the word "new" (coming from higher level language?), but that's how it works here:
SystemManager sm = SystemManager(); // <- variable created on the stack, will be automatically destroyed when out of scope
SystemManager *psm = new SystemManager(); // Created in the heap, while in the stack remains just a pointer to it.
//You will need to delete it when done with :
delete psm;
To answer the question
How can i link it to a specific instance? I need it so it can read the values of the variables.
You can do:
int main()
{
SystemManager SM; // = SystemManager(); // <- this is not needed
std::thread tRunning(SystemManager::runningAlgorithm, SM);
// Access SM as you need
// REMEMBER TO CLOSE & JOIN THE THREAD!
tRunning.join();
}
I still think you should first get used to the underlying concepts or it will be really difficult to go on.

Multi-Threading C++, Passing a function with a parameter from a class into main

I'm trying to pass a function with a parameter form a class into a thread in the main.cpp
This is the error I'm getting:
"Error 1 error C2064: term does not evaluate to a function taking 1 arguments c:\program files (x86)\microsoft visual studio 12.0\vc\include\functional 1149 1 The Dining Philosophers Problem"
I just can't seem to get it working. This is what i have so far:
Philosophers Philosopher;
thread Philosopher_Thread[NUMBEROFPHILOSOPHERS];
int main()
{
for (int Philosopher_Num = 0; Philosopher_Num < NUMBEROFPHILOSOPHERS; Philosopher_Num++)
{
if (Philosopher.Iterations[Philosopher_Num] > 0)
{
Philosopher_Thread[Philosopher_Num] = thread (std::bind(&Philosophers::Hierarchy_Function, &Philosopher_Num)); // Create threads for each philosopher
Philosopher_Thread[Philosopher_Num].join(); //join threads
}
}
}
class.h
class Philosophers
{
public:
void Initialise();
void Hierarchy_Function(int Current_Philosopher);
}
class.cpp
void Philosophers::Hungry_Hierarchy(int Current_Philosopher)
{
//code//
}
You don't need std::bind when using std::thread. Just do e.g.
std::thread(&Philosophers::Hierarchy_Function, Philosopher, Philosopher_Num);
The above also fixes two other problems: The first that since Hierarchy_Function is not a static member function, it must be called on a specific object instance of the Philosophers class (the second argument to the thread constructor). The second problem is that you attempted to pass a pointer to an integer to the function as argument, but the function wants an integer value.
Also, creating a thread, and then immediately joining that thread is no different than just calling the function and doing the calculations serially. Have two loops, one creating the threads, and then when you're done tell the threads to exit (by having e.g. a single boolean variable that the thread checks) and then have a loop joining the threads.
The thread creation line should read:
Philosopher_Thread[Philosopher_Num] = thread (std::bind(&Philosophers::Hierarchy_Function, &Philosopher, &Philosopher_Num));
The reason is that Philosophers::Hierarchy_Function is a class member function. When you call this funcion using Philosopher.Hierarchy_Function(Philsopher_Num); the compiler supplies an implicit this pointer as the first argument. So when you call it using a pointer to member function, the this pointer must be supplied explicitly as a pointer to your object.
Also a note of caution, you are sharing the same Philosopher amongst all your threads, this has the potential to result in a race condition (you have no internal state so you are ok in the above example) so either have a separate Philosopher for each thread or provide some form of synchronization.
Because you're binding to a non static member function you need to provide the instance pointer to bind as the first variable arg.
Philosophers Philosopher;
thread Philosopher_Thread[NUMBEROFPHILOSOPHERS];
int main()
{
for (int Philosopher_Num = 0; Philosopher_Num < NUMBEROFPHILOSOPHERS; Philosopher_Num++)
{
if (Philosopher.Iterations[Philosopher_Num] > 0)
{
auto func = std::bind(&Philosophers::Hierarchy_Function, &Philosopher, &Philosopher_Num)
Philosopher_Thread[Philosopher_Num] = thread (func);
Philosopher_Thread[Philosopher_Num].join();
}
}
}
Also I noticed you passed a pointer to Philosopher_Num as the function param, if you're intending to pass the iteration index then this isn't necessary.

Trying to start threads of a member function from within a class

Here's a quick outline of my class:
class foo{
public:
vector<string> rawData;
vector<vector<string> > slicedData;
void readData();
void sortData();
private:
static void selectionSort(vector<string>);
};
Basically, readData populates rawData with information from an external file. Once it does this, sortData splits that data into subsets, each of which is stored in slicedData. I need to spawn a thread of selectionSort to sort each subset, and I have to do so inside of sortData.
I've tried it this way within sortData:
thread *threads = new thread[slicedData.size()];
for(int i = 0; i < slicedData.size(); i++){
threads[i] = thread(selectionSort,slicedData[i]);
}
...but when I do so, g++ throws error: attempt to use a deleted function.
For the record, I need to store the threads in an array so I can join them later. I realize this could be done more elegantly with the boost library and thread groups, but I'm trying to keep this project dependency-free.
I couldn't reproduce your error, but the following code compiles for me.
I would recommend using a vector of threads and calling emplace_back() to create the threads inside the vector..
Something like this:
class foo
{
public:
std::vector<std::vector<std::string> > slicedData;
void sortData()
{
std::vector<std::thread> threads;
// for each slice add a new thread passing the function and data
// to its constructor
for(auto& slice: slicedData)
threads.emplace_back(&foo::selectionSort, std::ref(slice));
// NOTE: use of std::ref() to pass by reference
// now join the threads to prevent the threads vector
// going out of scope before they finish
for(auto&& thread: threads)
thread.join();
}
private:
static void selectionSort(std::vector<std::string>&); // pass by reference
};
Also note I pass the data by reference because I suspect you don't really want to sort a copy of the data.
The error isn't in the threading code that you have shown here. Probably, your sortData method doesn't wait for the threads to complete (use thread.join as Galik described), and your foo goes out of scope and gets deleted while the threads are still trying to use it. That's why you see "attempt to use a deleted function"

Store Templated Object in Container

Is it possible to store a templated class like
template <typename rtn, typename arg>
class BufferAccessor {
public:
int ThreadID;
virtual rtn do_work(arg) = 0;
};
BufferAccessor<void,int> access1;
BufferAccessor<int,void> access2;
in the same container like a vector or list
edit:
The purpose for this is I am trying to make a circular buffer where the objects that want to use the buffer need to register with the buffer. The buffer will store a boost::shared_ptr to the accessor objects and generate a callback to there functions that will push or pull data to/from the buffer. The callback will be used in a generic thread worker function that I have created similar to a thread pool with the fact that they need to access a shared memory object. Below is some code I have typed up that might help illustrate what I am trying to do, but it hasn't been compiled it yet and this is also my first time using bind, function, multi-threading
typedef boost::function<BUF_QObj (void)> CallbackT_pro;
typedef boost::function<void (BUF_QObj)> CallbackT_con;
typedef boost::shared_ptr<BufferAccessor> buf_ptr;
// Register the worker object
int register_consumer(BufferAccesser &accessor) {
mRegCons[mNumConsumers] = buf_ptr(accessor);
return ++mNumConsumers;
}
int register_producer(BufferAccesser &accessor) {
mRegPros[mNumProducers] = buf_ptr(accessor);
return ++mNumProducers;
}
// Dispatch consumer threads
for(;x<mNumConsumers; ++x) {
CallBack_Tcon callback_con = boost::bind(&BufferAccessor::do_work, mRegCons[x]);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::consumerWorker, this, callback_con));
consumers.add(tw);
}
// Dispatch producer threads
for(x=0;x<mNumProducers; ++x) {
CallBack_Tpro callback_pro = boost::bind(&BufferAccessor::do_work, mRegPros[x], _1);
tw = new boost:thread(boost::bind(&RT_ActiveCircularBuffer::producerWorker, this, callback_pro));
producers.add(tw);
}
// Thread Template Workers - Consumer
void consumerWorker(CallbackT_con worker) {
struct BUF_QObj *qData;
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
if(buf.empty()) {
cond.wait(mLock)
qData = mBuf.front();
mBuf.pop_front(); // remove the front element
} // End Code Block
worker(qData); // Process data
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}
// Thread Template Workers - Producer
void producerWorker(CallbackT_pro worker) {
struct BUF_QObj *qData;
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
while(!mRun)
cond.wait(mLock);
while(!mTerminate) {
// Set interruption point so that thread can be interrupted
boost::thread::interruption_point();
qData = worker(); // get data to be processed
{ // Code Block
boost::mutex::scoped_lock lock(mLock);
buf.push_back(qData);
cond.notify_one(mLock);
} // End Code Block
// Sleep that thread for 1 uSec
boost::thread::sleep(boost::posix_time::nanoseconds(1000));
} // End of while loop
}
No it's not, because STL containers are homogenous, and access1 and access2 have completely different unrelated types. But you could make the class BufferAccessor non-template one but the do-work member as a template, like this:
class BufferAccessor
{
template<class R, class A>
R doWork(A arg) {...}
};
In this case you could store BufferAccessors in a container, but you can't make a member template function virtual.
Yes, you can use vector<BufferAccessor<void,int> > to store BufferAccessor<void,int> objects and vector<BufferAccessor<int,void> > to store BufferAccessor<int,void> objects.
What you cant do is use same vector to store both BufferAccessor<int,void> and BufferAccessor<void,int> object
The reason it doesnt work is because BufferAccessor<void,int>, and BufferAccessor<int,void> are two different classes
Note: it is possible to use same vector to store both BufferAccessor<int,void> and BufferAccessor<void,int> but you would have to either store them as void * using shared_ptr<void>. Or better yet you can use a boost::variant

multithreading and classes?

Here is the issue that I'm having with multithreading. The proc needs to be static which means the only way I see that 2 threads can communicate and share data is through the global scope. This does not seem very clean nor does it feel very OO. I know I can create a static proc function in a class but that's still static.
What I'd like to for example do is have thread procs in the class somehow so that ex: I could create an MD5 checksum class and have an array of these objects, each on their own thread checking its hash, while the UI thread is not impaired by this and another class could simply keep track of the handles and wait for multiple objects before saying "Complete" or something. How is this limitation usually overcome?
You cannot avoid using a static function if you want to start a thread there. You can however (using Windows) pass the this pointer as a parameter and use it on the other side to enter the class instance.
#include <windows.h>
class Threaded {
static DWORD WINAPI StaticThreadEntry(LPVOID me) {
reinterpret_cast<Threaded*>(me)->ThreadEntry();
return 0;
}
void ThreadEntry() {
// Stuff here.
}
public:
void DoSomething() {
::CreateThread(0, 0, StaticThreadEntry, this, 0, 0);
}
};
In C++, Boost.Thread solves the problem nicely. A thread is represented by a functor, meaning that the (non-static) operator() is the thread's entry point.
For example, a thread can be created like this:
// define the thread functor
struct MyThread {
MyThread(int& i) : i(i) {}
void operator()(){...}
private:
int& i;
};
// create the thread
int j;
boost::thread thr(MyThread(j));
by passing data to the thread functor's constructor, we can pass parameters to the thread without having to rely on globals. (In this case, the thread is given a reference to the integer j declared outside the thread.)
With other libraries or APIs, it's up to you to make the jump from a (typically static) entry point to sharing non-static data.
The thread function typically takes a (sometimes optional) parameter (often of type void*), which you can use to pass instance data to the thread.
If you use this to pass a pointer to some object to the thread, then the thread can simply cast the pointer back to the object type, and access the data, without having to rely on globals.
For example, (in pseudocode), this would have roughly the same effect as the Boost example above:
void MyThreadFunc(void* params) {
int& i = *(int*)params;
...
}
int j;
CreateThread(MyThreadFunc, &j);
Or the parameter can be a pointer to an object whose (non-static) member function you wish to call, allowing you to execute a class member function instead of a nonmember.
I'm not sure I understood well... I give it a try. Are you looking for thread local storage ?
Thread creation routines usually allow you to pass a parameter to the function which will run in a new thread. This is true for both Posix pthread_create(...) and Win32 CreateThread(...). Here is a an example using Pthreads:
void* func (void* arg) {
queue_t* pqueue = (queue_t*)arg;
// pull messages off the queue
val = queue_pull(pqueue);
return 0;
}
int main (int argc, char* argv[]) {
pthread_t thread;
queue_t queue = queue_init();
pthread_create(&thread, 0, func, &queue);
// push messages on the queue for the thread to process
queue_push(&queue, 123);
void* ignored;
pthread_join(&thread, &ignored);
return 0;
}
No statics anywhere. In a C++ program you could pass a pointer to an instance of a class.