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.
Related
I have a class with a function that takes a std::function and stores it. This part seems to compile ok (but please point out any issue if there are any)
#include <functional>
#include <iostream>
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = std::bind(callback, std::placeholders::_1);
callback("hello world\n");
}
};
// pretty boring class - a cut down of my actual class
struct helper
{
worker the_worker;
bool work_callback(std::string str)
{
std::cout << str << std::endl;
return true;
}
};
int main()
{
helper the_helper;
//the_helper.the_worker.do_work(std::bind(&helper::work_callback, the_helper, std::placeholders::_1)); // <---- SEGFAULT (but works in minimal example)
the_helper.the_worker.do_work(std::bind(&helper::work_callback, &the_helper, std::placeholders::_1)); // <---- SEEMS TO WORK
}
I get a segfault, but I am not sure why. I have used this before, in fact, I copied this example from another place I used it. The only real difference that the member function was part of the class I called it from (i.e. this instead of the_helper).
So this is why I am also asking if there is anything else I am doing wrong in general? Like should I be passing the std::function as:
void do_work(std::function<bool(std::string)>&& callback)
or
void do_work(std::function<bool(std::string)>& callback)
As also noted by #Rakete1111 in comments, the problem probably was in this code:
bool work_callback(std::string str)
{
std::cout << str << std::endl;
}
In C++ if a non-void function does not return a value the result is undefined behavior.
This example will crash with clang but pass with gcc.
If helper::work_callback returns (e.g, true) the code works just fine.
I don't know why your code seg faults because I was spoiled and skipped std::bind straight to lambdas. Since you use C++11 you should really convert your code from std::bind to lambdas:
struct worker
{
std::function<bool(std::string)> m_callback;
void do_work(std::function<bool(std::string)> callback)
{
m_callback = callback;
callback("hello world\n");
}
};
Now with work_callback and calling do_work things need some analysis.
First version:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([&](std::string s) { return the_helper.work_callback(s); });
}
Now this version works with your toy example. However out in the wild you need to be careful. The lambda passed to do_work and then stored in the_worker captures the_helper by reference. This means that this code is valid only if the helper object passed as reference to the lambda outlives the worker object that stores the m_callback. In your example the worker object is a sub-object of the the helper class so this is true. However if in your real example this is not the case or you cannot prove this, then you need to capture by value.
First attempt to capture by value (does not compile):
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
This does not compile because the copy of the_helper stored in the lambda object is const by default and as such you cannot call work_callback on it.
A questionable solution if you can't make work_callback const is to make the lambda mutable:
struct helper
{
worker the_worker;
bool work_callback(std::string)
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) mutable { return the_helper.work_callback(s); });
}
But you need to think if this is what you intended.
What would make more sense is to make work_callback const:
struct helper
{
worker the_worker;
bool work_callback(std::string) const
{
return false;
}
};
int main()
{
helper the_helper;
the_helper.the_worker.do_work([=](std::string s) { return the_helper.work_callback(s); });
}
The reason for getting SEGFAULT has been already mentioned in the comments.
However, I would like to point out that, you need to use neither std::bind nor std::function, here in your given case. Instead, simply having a lambda and a function pointer you can handle what you intend to do.
struct worker
{
typedef bool(*fPtr)(const std::string&); // define fun ptr type
fPtr m_callback;
void do_work(const std::string& str)
{
// define a lambda
m_callback = [](const std::string& str)
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
};
bool flag = m_callback(str);// just call the lambda here
/* do some other stuff*/
}
};
struct helper
{
worker the_worker;
bool work_callback(const std::string& str)
{
std::cout << "Call from helper: ";
this->the_worker.do_work(str);
return true; ------------------------>// remmeber to keep the promise
}
};
And use case would be:
int main()
{
helper the_helper;
the_helper.work_callback(std::string("hello world"));
// or if you intend to use
the_helper.the_worker.do_work(std::string("hello world"));
return 0;
}
see Output here:
PS: In the above case, if worker does not required m_callback for later cases(i.e, only for do_work()), then you can remove this member, as lambdas can be created and called at same place where it has been declared.
struct worker
{
void do_work(const std::string& str)
{
bool flag = [](const std::string& str)->bool
{
/* do something with string*/
std::cout << "Call from worker: " << str << "\n";
return true;
}(str); -------------------------------------> // function call
/* do other stuff */
}
};
So I have this function which is behaving like the setInterval function in JS. I found it here.
I am currently trying to change it so it can be stopped. I do not fully understand the behavior of this code.
void setInterval(function<void(void)> func, unsigned int interval) {
thread([func, interval]() {
while (1) {
auto x = chrono::steady_clock::now() + chrono::milliseconds(interval);
func();
this_thread::sleep_until(x);
}
}).detach();
}
I tried it like this:
void setInterval(function<void(void)> func, unsigned int interval, bool &b) {
thread([func, interval, *b]() {
while (*b) {
auto x = chrono::steady_clock::now() + chrono::milliseconds(interval);
func();
this_thread::sleep_until(x);
}
}).detach();
}
(this won't compile), and in main calling it like this:
bool B;
setInterval(myFunction,1000,B);
I was expecting that if I change the B variable to false, then the thread in setInterval function stops, but I haven't managed to reach my goal like this. Any idead/suggestions? Thank you in advance.
Sorry, but I didn't find a design simpler than that.
You could, make a class that owns both a thread, and a weak_ptr to itself,
to be a "holder" that the callable can see it safely, because the callable
will still exists even if the object is destructed. You don't want a dangling pointer.
template<typename T>
struct IntervalRepeater {
using CallableCopyable = T;
private:
weak_ptr<IntervalRepeater<CallableCopyable>> holder;
std::thread theThread;
IntervalRepeater(unsigned int interval,
CallableCopyable callable): callable(callable), interval(interval) {}
void thread() {
weak_ptr<IntervalRepeater<CallableCopyable>> holder = this->holder;
theThread = std::thread([holder](){
// Try to strongify the pointer, to make it survive this loop iteration,
// and ensure that this pointer is valid, if not valid, end the loop.
while (shared_ptr<IntervalRepeater<CallableCopyable>> ptr = holder.lock()) {
auto x = chrono::steady_clock::now() + chrono::milliseconds(ptr->interval);
ptr->callable();
this_thread::sleep_until(x);
}
});
}
public:
const CallableCopyable callable;
const unsigned int interval;
static shared_ptr<IntervalRepeater<T>> createIntervalRepeater(unsigned int interval,
CallableCopyable callable) {
std::shared_ptr<IntervalRepeater<CallableCopyable>> ret =
shared_ptr<IntervalRepeater<CallableCopyable>>(
new IntervalRepeater<CallableCopyable>(interval, callable));
ret->holder = ret;
ret->thread();
return ret;
}
~IntervalRepeater() {
// Detach the thread before it is released.
theThread.detach();
}
};
void beginItWaitThenDestruct() {
auto repeater = IntervalRepeater<function<void()>>::createIntervalRepeater(
1000, [](){ cout << "A second\n"; });
std::this_thread::sleep_for(std::chrono::milliseconds(3700));
}
int main() {
beginItWaitThenDestruct();
// Wait for another 2.5 seconds, to test whether there is still an effect of the object
// or no.
std::this_thread::sleep_for(std::chrono::milliseconds(2500));
return 0;
}
C++ is not JavaScript, but C++ can apply most programming paradigms in different languages.
I have designed a simple callback-keyListener-"Interface" with the help of a pure virtual function. Also I used a shared_ptr, to express the ownership and to be sure, that the listener is always available in the handler. That works like a charme, but now I want to implement the same functionality with the help of std::function, because with std::function I am able to use lambdas/functors and I do not need to derive from some "interface"-classes.
I tried to implement the std::function-variant in the second example and it seems to work, but I have two questions related to example 2:
Why does this example still work, although the listener is out of scope? (It seems, that we are working with a copy of the listener instead of the origin listener?)
How can I modify the second example, to achieve the same functionality like in the first example (working on the origin listener)? (member-ptr to std::function seems not to work! How can we handle here the case, when the listener is going out of scope before the handler? )
Example 1: With a virtual function
#include <memory>
struct KeyListenerInterface
{
virtual ~KeyListenerInterface(){}
virtual void keyPressed(int k) = 0;
};
struct KeyListenerA : public KeyListenerInterface
{
void virtual keyPressed(int k) override {}
};
struct KeyHandler
{
std::shared_ptr<KeyListenerInterface> m_sptrkeyListener;
void registerKeyListener(std::shared_ptr<KeyListenerInterface> sptrkeyListener)
{
m_sptrkeyListener = sptrkeyListener;
}
void pressKey() { m_sptrkeyListener->keyPressed(42); }
};
int main()
{
KeyHandler oKeyHandler;
{
auto sptrKeyListener = std::make_shared<KeyListenerA>();
oKeyHandler.registerKeyListener(sptrKeyListener);
}
oKeyHandler.pressKey();
}
Example 2: With std::function
#include <functional>
#include <memory>
struct KeyListenerA
{
void operator()(int k) {}
};
struct KeyHandler
{
std::function<void(int)> m_funcKeyListener;
void registerKeyListener(const std::function<void(int)> &funcKeyListener)
{
m_funcKeyListener = funcKeyListener;
}
void pressKey() { m_funcKeyListener(42); }
};
int main()
{
KeyHandler oKeyHandler;
{
KeyListenerA keyListener;
oKeyHandler.registerKeyListener(keyListener);
}
oKeyHandler.pressKey();
}
std::function<Sig> implements value semantic callbacks.
This means it copies what you put into it.
In C++, things that can be copied or moved should, well, behave a lot like the original. The thing you are copying or moving can carry with it references or pointers to an extrenal resource, and everything should work fine.
How exactly to adapt to value semantics depends on what state you want in your KeyListener; in your case, there is no state, and copies of no state are all the same.
I'll assume we want to care about the state it stores:
struct KeyListenerA {
int* last_pressed = 0;
void operator()(int k) {if (last_pressed) *last_pressed = k;}
};
struct KeyHandler {
std::function<void(int)> m_funcKeyListener;
void registerKeyListener(std::function<void(int)> funcKeyListener) {
m_funcKeyListener = std::move(funcKeyListener);
}
void pressKey() { m_funcKeyListener(42); }
};
int main() {
KeyHandler oKeyHandler;
int last_pressed = -1;
{
KeyListenerA keyListener{&last_pressed};
oKeyHandler.registerKeyListener(keyListener);
}
oKeyHandler.pressKey();
std::cout << last_pressed << "\n"; // prints 42
}
or
{
oKeyHandler.registerKeyListener([&last_pressed](int k){last_pressed=k;});
}
here we store a reference or pointer to the state in the callable. This gets copied around, and when invoked the right action occurs.
The problem I have with listeners is the doulbe lifetime issue; a listener link is only valid as long as both the broadcaster and reciever exist.
To this end, I use something like this:
using token = std::shared_ptr<void>;
template<class...Message>
struct broadcaster {
using reciever = std::function< void(Message...) >;
token attach( reciever r ) {
return attach(std::make_shared<reciever>(std::move(r)));
}
token attach( std::shared_ptr<reciever> r ) {
auto l = lock();
targets.push_back(r);
return r;
}
void operator()( Message... msg ) {
decltype(targets) tmp;
{
// do a pass that filters out expired targets,
// so we don't leave zombie targets around forever.
auto l = lock();
targets.erase(
std::remove_if( begin(targets), end(targets),
[](auto&& ptr){ return ptr.expired(); }
),
end(targets)
);
tmp = targets; // copy the targets to a local array
}
for (auto&& wpf:tmp) {
auto spf = wpf.lock();
// If in another thread, someone makes the token invalid
// while it still exists, we can do an invalid call here:
if (spf) (*spf)(msg...);
// (There is no safe way around this issue; to fix it, you
// have to either restrict which threads invalidation occurs
// in, or use the shared_ptr `attach` and ensure that final
// destruction doesn't occur until shared ptr is actually
// destroyed. Aliasing constructor may help here.)
}
}
private:
std::mutex m;
auto lock() { return std::unique_lock<std::mutex>(m); }
std::vector< std::weak_ptr<reciever> > targets;
};
which converts your code to:
struct KeyHandler {
broadcaster<int> KeyPressed;
};
int main() {
KeyHandler oKeyHandler;
int last_pressed = -1;
token listen;
{
listen = oKeyHandler.KeyPressed.attach([&last_pressed](int k){last_pressed=k;});
}
oKeyHandler.KeyPressed(42);
std::cout << last_pressed << "\n"; // prints 42
listen = {}; // detach
oKeyHandler.KeyPressed(13);
std::cout << last_pressed << "\n"; // still prints 42
}
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.
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
}