bind return value and variadic templates - c++

I am trying to create a Thread Pool in C++. The concept is that main will create a new Task and the ThreadPool class will get the Task objects and implement the other work. This is the Task class:
template<typename ... Arguments>
class Task{
//
public:
Task(std::function<void (Arguments...)> _func, Arguments... _args){
auto f1 = std::bind(_func, _args...);
f1();
};
void run(){
};
};
and this how i am trying to use it:
#include <iostream>
#include <algorithm>
#include "Task.hpp"
void prtinhi(int a)
{
std::cout << a << std::endl;
return;
}
int main(){
Task<int> task(prtinhi, 5);
task.run();
return 0;
}
Obviously the Task object will be passed in the ThreadPool and the ThreadPool will call run() according to some logic.
This codes run successfully printing 5. But what i want is to call f1() from the run() function. If i change Task class to have the auto f1 defintion as a class member i get an error:
non-static data member declared ‘auto’
if i declare it static i can't assign a value to it.
So how do i solve this one? Is there a better way to do it?

Why does the task need to know about the function arguments? The task should be a void() type-erased callable object.
using Task = std::function<void()>;
Task task([]{ prtinhi(5); });
ThreadPool pool;
pool.schedule(task);
// ...
// `prtinhi(5)` will be eventually called.
If you need to get the return value, you want std::future.
ThreadPool could be implemented as follows:
struct ThreadPool
{
some_lockfree_queue<Task> _queue;
std::vector<std::thread> _workers;
void initialize()
{
for(int i = 0; i < num_threads; ++i)
{
_workers.emplace_back([this]
{
Task t = _queue.try_dequeue();
t();
});
}
}
};
std::bind is bad (watch this talk by STL for more info). You should use lambdas to bind the arguments you require and get a nullary function back.

Related

Can I capture lambda variables without std::function?

Is it possible to get the captured values of a lambda without using std::function? I'm asking because I want to place the captured copies into my own memory, which std::function cannot do as they don't support custom allocators.
(I assume allocator support missing for std::function is due to a very good reason, perhaps the logic behind capturing values in a lambda is extremely difficult to implement? But if it's possible, I'd like to try it myself.)
Background: I'm asking to learn more about lambda in C++. I'd like to place the captured values and reference pointers in over-aligned memory for a thread pool system I'm writing as an academic exercise. I also really like the brevity writing lambdas with automatic captures, it'd make for a very easy "job" writing interface I think.
class MyFunction {
public:
// I want more than just the function pointer,
// I also want the captured value copies or references too
// I'm unsure how to really accomplish this though.
MyFunction & operator=( ??? ) {
???
}
};
int main(){
int captureThis = 1;
MyFunction func = [=]()->void {
printf("%i", captureThis);
};
}
Checking values of captured variables outside of lambda would not look good but at least you can use a factory function to produce it with its unique "lambda" template type (also with help of auto on the final type) so that you can do extra work between what thread calls and what you initialize:
#include <iostream>
#include <thread>
#include <vector>
template <typename F>
struct Callable
{
Callable(const F && lambda):func(std::move(lambda))
{
}
// this is what the std::thread calls
void operator()()
{
// you can check the captured variable
int out;
func(out,false);
std::cout<< "Callable successfully found out the value of captured variable: "<<out <<std::endl;
func(out,true);
}
const F func;
};
template<typename F>
Callable<F> CallableFactory(F&& lambda)
{
return Callable<F>(std::forward<F>(lambda)); // or std::move(lambda)
}
int main()
{
// variable to capture
int a=1;
auto callable = CallableFactory([&](int & outputCapturedValue, bool runNow){
// not looking good as its not possible from outside (because they are private variables & depends on implementation of C++)
// if checking the captured variables
if(!runNow)
{
outputCapturedValue = a;
std::cout << "inside the lambda: a=" << a <<std::endl;
}
else
{
std::cout<<"algorithm runs"<<std::endl;
}
});
std::vector<std::thread> threads;
threads.emplace_back(std::move(callable));
threads[0].join();
return 0;
}
output:
inside the lambda: a=1
Callable successfully found out the value of captured variable: 1
algorithm runs
If its only for having an array of lambdas processed by array of threads, you can use smart-pointers and an extra container struct to box/unbox them during work-distribution:
#include <iostream>
#include <thread>
#include <vector>
#include <memory>
struct ICallable
{
virtual void operator()()=0;
};
template <typename F>
struct Callable:public ICallable
{
Callable(const F && lambda):func(std::move(lambda))
{
}
// this is what the std::thread calls
void operator()() override
{
func();
}
const F func;
};
template<typename F>
std::shared_ptr<ICallable> CallablePtrFactory(F&& lambda)
{
return std::shared_ptr<ICallable>(new Callable<F>(std::forward<F>(lambda)));
}
struct CallableContainer
{
std::shared_ptr<ICallable> callable;
void operator()()
{
callable.get()->operator()();
}
};
int main()
{
// variable to capture
int a=1;
// simulating work pool
std::vector<std::shared_ptr<ICallable>> callables;
callables.push_back(CallablePtrFactory([&](){
std::cout<< "a="<<a<<std::endl;
}));
// simulating worker pool load-balancing
std::vector<std::thread> threads;
threads.emplace_back(CallableContainer{ callables[0] });
threads[0].join();
return 0;
}
output:
a=1
If you're after a custom-allocation for the container, you can just use a second parameter for the factory function. Following example uses placement-new on a stack buffer. But still the lambda itself has something else outside of it making container's size not changed by its lambda (just like a function-pointer):
#include <iostream>
#include <thread>
#include <vector>
#include <memory>
struct ICallable
{
virtual void operator()()=0;
};
template <typename F>
struct Callable:public ICallable
{
Callable(const F && lambda):func(std::move(lambda))
{
currentSize = sizeof(*this); std::cout<<"current size = "<<currentSize <<" (useful for alignement of next element?)" <<std::endl;
}
// this is what the std::thread calls
void operator()() override
{
func();
}
int currentSize;
const F func;
};
template<typename F>
std::shared_ptr<ICallable> CallablePtrFactory(F&& lambda, char * buffer)
{
return std::shared_ptr<ICallable>(
new (buffer) Callable<F>(std::forward<F>(lambda)),
[](ICallable *){ /* placement-new does not require a delete! */}
);
}
struct CallableContainer
{
std::shared_ptr<ICallable> callable;
void operator()()
{
callable.get()->operator()();
}
};
int main()
{
// variable to capture
int a=1;
char buffer[10000];
// simulating work pool
std::vector<std::shared_ptr<ICallable>> callables;
callables.push_back(
// observe the buffer for placement-new
CallablePtrFactory([&](){
std::cout<< "a="<<a<<std::endl;
},buffer /* you should compute offset for next element */)
);
// simulating worker pool load-balancing
std::vector<std::thread> threads;
threads.emplace_back(CallableContainer{ callables[0] });
threads[0].join();
return 0;
}
output:
current size = 24 (useful for alignement of next element?)
a=1
Considering the thread pool system you mention in comments then you could try a polymorphic approach:
class ThreadRoutine
{
protected:
virtual ~ThreadRoutine() { }
public:
virtual void run() = 0;
};
template <typename Runner>
class ThreadRoutineT
{
// variant 1:
Runner m_runner; // store by value;
// variant 2:
std::reference_wrapper<Runner> m_runner;
public:
void run() override { m_runner(); } // call operator()
};
Now you might store your thread routines in a std::vector (note: pointers to, by value would lead to object slicing; likely std::unique_ptr, possibly, depending on use case, a classic raw pointer might fit, too).
You could even implement both variants, your thread pool manager could provide an additional parameter in the thread creation function or maybe even more elegant distinguish by overloading that function (l-value reference: create the reference wrapper variant; r-value reference: create the value variant, move-construct it), e.g. like:
class ThreadManager
{
template <typename Runner>
void createThread(Runner& runner)
{
// assuming std::vector<std::unique_ptr<ThreadRoutine>>
m_runners.emplace_back
(
// assuming appropriate constructor
std::make_unique<ThreadRoutineRef>(runner)
);
// return some kind of thread handle or start thread directly?
// thread handle: could be an iterator into a std::list
// (instead of std::vector) as these iterators do not invalidate
// if elements preceding in the list are removed
// alternatively an id as key into a std::[unordered_]map
}
template <typename Runner>
void createThread(Runner&& runner)
{
m_runners.emplace_back
(
// assuming appropriate constructor
std::make_unique<ThreadRoutineVal>(std::move(runner))
);
}
}
About the alignment issue: The specific template instantiations would select the alignment appropriate for the template argument type, so you wouldn't have to consider anything particular.

Make thread in class and use it in class C++

i need make new thread in class and use it.
Somethink like:
class Somethink
{
public:
func_to_be_thread();
init_func();
}
Somethink::init_func()
{
std::thread newThread(func_to_be_thread);
}
int main()
{
Somethink ss;
ss.init_func();
}
EDIT:
How to make it correctly? Everythink i wrote returns error becouse idk how to make new thread in class with parameter (function to run) class method. My question is how to do it correctly?
If you need to create a thread with member function you can do the following:
class Something
{
public:
void func_to_be_thread();
void func_to_be_thread_advanced(const char* arg1);
std::thread init_func();
std::thread init_func_with_param(const char *arg1);
}
std::thread Something::init_func()
{
return std::thread(&Something::func_to_be_thread, this);
}
Also you can do it with lambda and parameters:
std::thread init_func_with_param(const char *arg1)
{
return std::thread([=] { func_to_be_thread_advanced(arg1); });
}
which C++ version are you using ? you can use std::thread only starting C++11 .. if you need more help with the syntax, you can check std::thread calling method of class
Start thread with member function

How to submit thread pool with templatised member function (need to modify the members inside function)

I am trying to re-use a simple thread pool mentioned in SO -
class thread_pool
{
thread_safe_queue<std::function<void()> work_queue; // need to submit fun(v) of class A where v is vector<string> here.
void worker_thread() {
while(!done)
{
std::function<void()> task;
if(work_queue.try_pop(task))
{
task(); // how should my function MyClass::Func(a,b) be called here?
}
else
{
std::this_thread::yield();
}
}
}
// -- Submit a task to the thread pool
template <typename FunctionType>
void submit(FunctionType f) {
work_queue.push(std::function<void()>(f)); //how do i submit something like A.fun(v) ?
}
}
Now i need to submit a task which is a member function of a templatized class in the queue
template<class T>
class A
{
private:
int x ;
public:
void fun(std::vector<std::string> & items)
{
//do somehting with items.
x = 5; // modify the members.
}// please note that i need to modify members in this function in submitted thread.
};
so finally i need something like-
thread_pool tp;
// a member function of class obj A (a) submitted with vector<string> v.
tp.submit(&A<int>::fun, std::ref(a), v);
the queries i have is how will the task queue signature look like to execute above mentioned task?
How would I need to change the thread_pool class in order to run this templatized member function?How can I call the submit Function in my code?
I saw a similar question here but still wondering about it.
An example of the same would really be helpful.
Thank you very much for your help.
You may use lambda:
thread_pool tp;
A<int> a;
td::vector<std::string> v;
tp.submit([&]() { a.fun(v); });
Note: you have to make sure that a, v live long enough.

Is there a possibility to make a function wrapper that runs the injected code and returns the same data as the injected function?

I am toying with this idea for a while but cant seem to wrap my head around it.
Basically what I want to do is create a general Timer class that times all the functions that are passed to it. Averaging it when the same function is called multiple times so it has to store it somehow. It should therefore use the function name to store the task and average it when it occurs more than once.
Pseudoish code of what it should look like.
Class FunctionTaks
{
std::string d_name;
double d_execution_time;
}
Class Timer
{
private:
std::vector<FunctionTask> d_tasks;
public:
template <typename Function, typename ReturnType>
ReturnType time(Function f)
{
// check if function f is timed for first time
// start timer
// run function f
auto r = f.invoke();
// stop timer
// store function name and time, average if more than once
// return whatever f should return
return r;
}
void report() const;
}
I dont really know how to do this, especially when Function f has a different amount of arguments.
Timer t;
t.time(foo());
t.time(bar());
t.time(foo());
t.report();
I basically have a few core issues.
How to let a function wrapper return the same type that the injected code is suppose to return.
How to obtain the function name that is being injected.
The wrapper should not be limited by arguments passed on to the injected function. How to give the injected function the freedom of arguments.
On the other hand I dont really care about the arguments and return type, the wrapper should simply run the injected function as is and perform some timings and then return whatever the injected function is suppose to return.
C++11 but why templates? You need lambda expressions:
typedef void(*TimerFunction)();
void time(TimerFunction fun) {
// start timer
fun();
// stop timer
}
int fun1() { return 1; }
int fun2() { return 2; }
string fun3() { return string("Test"); }
main() {
int ret1, ret2;
string ret3;
t.time([&ret1]() { ret1 = fun1(); });
t.time([&ret2]() { ret2 = fun2(); });
t.time([&ret3]() { ret3 = fun3(); });
}
That's the concept. For details: C++ lambda with captures as a function pointer
With C++11 you can use variable template parameters:
class TimerFoo {
public:
template <class Foo, class... Args> TimerFoo(Foo foo, Args... args) {
// ... start timer
foo(args...);
// ... stop timer
}
};
And use e.g.:
TimerFoo tf = TimerFoo(foo, 1, 2, 3);
Ofcourse you need some field in TimerFoo that will store the measured time...
Edit:
To be able to return a value of your function using this approach you could change the above code to:
#include <iostream>
using namespace std;
class TimerFoo {
public:
template <class Foo, class... Args> auto run(Foo foo, Args... args) -> decltype(foo(args...)) {
// ... start timer
auto result = foo(args...);
// ... stop timer
return result;
}
};
int foo(int a, int b) {
return 2;
}
int main() {
TimerFoo tf;
cout << tf.run(foo, 1, 2) << endl; // output: 2
}

tasks from member functions using std.parallelism in D

I would like to create a task that executes a member function of a struct or class:
import std.parallelism, std.stdio;
struct S {
void foo() {
writeln("S.foo()");
}
}
void main() {
S s;
auto pool = new TaskPool();
auto t = task!(s.foo)(); // error
pool.put(t);
pool.finish();
}
How can I achieve this? I also tried using delegates to no avail.
edit: I found a potentially related question here.
import std.parallelism, std.stdio;
struct S {
void foo() {
writeln("S.foo()");
}
}
void main() {
S s;
auto pool = new TaskPool();
auto t = task(&s.foo); // Constructor taking a runtime function pointer, delegate or callable (opCall).
pool.put(t);
pool.finish();
}
Output:
S.foo()
You can use scopedTask as well, but then you have to wait until the task has finished before returning. TaskPool.finish does not wait.