Combine QtConcurrent call - c++

I have three methods and all of them returns a string, I want to run all of them using QtConcurrent and get their return into a single list or something like that. QtConcurrent::mapped is ideal as it returns an iterator but I can only run one method at time.
In JavaScript there's promise.all([method_a, method_b, method_c]), it will automatically merge their return into a single result (iterator).
How to do that in Qt?

Since you have several methods to call, you can pass them as a sequence of functors as the first argument to QtConcurrent::mapped. The mapping functor would be an apply functor that takes a functor representing the method call and returns the result of invoking it.
First, let's have our class:
// https://github.com/KubaO/stackoverflown/tree/master/questions/concurrent-combine-49802153
#include <QtConcurrent>
#include <functional>
#include <initializer_list>
#include <type_traits>
class Cls {
public:
QString method1() const { return QStringLiteral("10"); }
QString method2() const { return QStringLiteral("20"); }
QString method3() const { return QStringLiteral("30"); }
};
The apply_t functor invokes the method passed to it as an argument:
template <class Method> struct apply_t {
using result_type = typename std::result_of_t<Method()>;
auto operator()(Method method) {
return method();
}
};
Let's make it convenient to make such applicators from the type of a sequence of functors to be called:
template <class Sequence, class A = apply_t<typename std::decay_t<Sequence>::value_type>>
A make_apply(Sequence &&) { return {}; }
For convenience, we'll also have a vector generator in the spirit of e.g. make_unique, etc.:
template <class T> QVector<T> make_vector(std::initializer_list<T> init) {
return {init};
}
Then, the problem becomes fairly simple. First, we make a vector of bound methods that will be called. Then we pass the methods to call, as well as the applicator to operate on them, to QtConcurrent::mapped. The results() gives a list of all results of the method calls, in sequence.
int main() {
Cls obj;
auto const methods = make_vector({
std::bind(&Cls::method1, &obj),
std::bind(&Cls::method2, &obj),
std::bind(&Cls::method3, &obj)
});
QFuture<QString> result =
QtConcurrent::mapped(methods, make_apply(methods));
Q_ASSERT((result.results() == QStringList{"10", "20", "30"}));
}
Instead of making a custom apply_t class, we could use a lambda, wrapped to provide the result_type member type that QtConcurrent::mapped expects. See this answer for details of wrapping the lambda. The rest of this answer provides examples of such wrapping.

Since there's no built in way to do that, you can work out a class on your own to keep futures together and return a collection of results when all tasks completed. The only limitation, here, is due to the strongly typed nature of c++: each future returned by QtConcurrent::run holds the called function result, the type of which is given at compile time, as the QFuture template parameter. What if the return types of the called functions differ from each other? In the example I provide, they all return the same type, but I think one could use QVariant for that mean and get away with it.
In a promise.h:
#ifndef PROMISE_H
#define PROMISE_H
#include <QtConcurrent/QtConcurrentRun>
#include <QFutureWatcher>
class PromiseInterface
{
public:
virtual ~PromiseInterface() = default;
virtual void finished(int id) = 0;
};
class Watcher : public QObject
{
Q_OBJECT
int _id;
PromiseInterface * _promise;
public slots:
void finished()
{
_promise->finished(_id);
deleteLater();
}
public:
Watcher(int id, PromiseInterface * promise)
: _id(id),
_promise(promise)
{}
};
template <typename T>
class Promise : public PromiseInterface
{
friend class Watcher;
void finished(int id) override
{
_resolved++;
_results[id] = _watchers[id]->result();
delete _watchers[id];
if(_resolved == _results.size())
{
if(_callback != nullptr)
{
_callback(_results);
}
}
}
QList<QFutureWatcher<T> *> _watchers;
QVector<T> _results;
void (*_callback)(QVector<T>);
int _resolved;
public:
Promise(QList<QFuture<T>> futures)
{
_resolved = 0;
_callback = nullptr;
_results.resize(futures.size());
int i=0;
for(auto f : futures)
{
QFutureWatcher<T> * watcher = new QFutureWatcher<T>();
watcher->setFuture(f);
QObject::connect(watcher, &QFutureWatcher<T>::finished, new Watcher(i++, this), &Watcher::finished);
_watchers.append(watcher);
}
}
void then(void (*callback)(QVector<T>)) { _callback = callback; }
};
#endif // PROMISE_H
The Promise class is a class template with a single template parameter that matches the one of QFuture. The observed futures are passed in the constructor, while the then method accepts a the completion callback as its only argument.
The Watcher class provides a slot to catch QFutureWatcher::finished' signals. Each instance knows the promise object through a pointer to itsPromiseInterfaceand will callfinished` from the slot, passing in the id of the future that completed.
When all futures finished, the callback function is called with the vector of results passed in.
In a very simple usage example, we can execute this function concurrently:
#include <unistd.h>
int f(int r) { sleep(1); return r;}
and pass this callback to the promise then:
void callback(QVector<int> results)
{
qDebug() << results;
}
Our main:
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QList<QFuture<int>> futures = {
QtConcurrent::run(&f, 1),
QtConcurrent::run(&f, 2),
QtConcurrent::run(&f, 3)
};
Promise<int> promise(futures);
promise.then(callback);
return a.exec();
}
After about a second, this is the expected output:
QVector(1, 2, 3)
Just in case one wonders why I put in three classes, instead of making Promise extend QObject directly, and implement the finished slot itself: Qt is not letting me do that. When the Q_OBJECT macro is added to a class template, an explicit compiler error will prompt: Template classes not supported by Q_OBJECT.

The method you're looking for is QFuture::results():
QList<T> QFuture::results() const
Returns all results from the future. If the results are not
immediately available, this function will block and wait for them to
become available.
Expanding from Qt's own QtConcurrent::mapped example:
QImage scaled(const QImage &image)
{
return image.scaled(100, 100);
}
QList<QImage> images = ...;
QList<QImage> thumbnails = QtConcurrent::mapped(images, scaled).results();

I know AsyncFuture is a c++ library that converts calls into a QFuture type and uses it like a Promise object in Javascript (Combine multiple futures with different type into a single future object). unfortunately i never used it! but there are details on this reference Qt Blog Multithreaded Programming with Future & Promise

Related

Save template type parameter pack for later use

I'm working on a code where I can bind events and callbacks to react to those events, the interface looks like this:
void on_close();
struct S
{
void the_app_is_closing();
};
S s;
Events::Register(app::CLOSE, on_close);
Events::Register(app::CLOSE, s, &S::the_app_is_closing);
...
...
if (/* something happens */)
Events::Broadcast(app::CLOSE);
Internally it keeps a container which associates an enum value identifying an event with all the functions expected to react to that event. Those functions are kept into an object which can hold free functions or member functions and feeds the functions through a template function (apply) that forwards the parameters:
class callback
{
struct base {};
template <typename ... params_pack>
struct callable : public base
{
callable(void(*a_function)(params_pack ...)) :
m_call{a_function}
{}
template <typename listener_t>
callable(listener_t &a_listener, void(listener_t:: *a_function)(params_pack ...)) :
m_call{[&a_listener, &a_function](params_pack ... a_argument)
{
(a_listener.*a_function)(a_argument ...);
}}
{}
std::function<void(params_pack ...)> m_call;
};
template <typename ... params_pack>
auto build(void(*a_function)(params_pack ...))
{
return std::make_unique<callable<params_pack ...>>(a_function);
}
template <typename listener_t, typename ... params_pack>
auto build(listener_t &a_listener, void(listener_t:: *a_function)(params_pack ...))
{
return std::make_unique<callable<params_pack ...>>(a_listener, a_function);
}
std::unique_ptr<base> m_function{nullptr};
public:
template <typename function_t>
callback(function_t a_function) :
m_function{build(a_function)}
{}
template <typename listener_t, typename function_t>
callback(listener_t &a_listener, function_t a_function) :
m_function{build(a_listener, a_function)}
{}
template <typename ... params_pack>
void apply(params_pack ... a_argument) const
{
if (auto &call = *static_cast<callable<params_pack ...> *>(m_function.get());
std::is_invocable_v<decltype(call.m_call), params_pack ...>)
{
call.m_call(a_argument ...);
}
}
};
I have an important bug on that apply function that can be reproduced with this code:
void string_parameter(const std::string &s) { std::cout << s << '\n'; }
void long_parameter(long l) { std::cout << l << '\n'; }
int main()
{
callback l(long_parameter);
callback s(string_parameter);
l.apply(123);
s.apply("Test");
return 0;
}
Even if you can call string_parameter directly with a literal string and long_parameter directly with a literal integer, doing the call through callback::apply messes everything up. I know why it is happening:
I'm static_casting callback::callable<const std::string &> to callback::callable<const char *>.
Then the callable::m_call which underlying type is std::function<const std::string &> thinks it is std::function<const char *>.
The callable::m_call receives a literal string but is reinterpreted as std::string during the std::function call, creating the mess.
Same story with long and int.
The solution would be to save the parameter pack used on construction in order to use it inside apply:
template <typename function_t>
callback(function_t a_function) :
m_function{build(a_function)}
{ PARAMETERS = function_t.parameters } // ???
template <typename listener_t, typename function_t>
callback(listener_t &a_listener, function_t a_function) :
m_function{build(a_listener, a_function)}
{ PARAMETERS = function_t.parameters } // ???
...
...
template <typename ... params_pack>
void apply(params_pack ... a_argument) const
{
// Saved parameters --> vvvvvvvvvvvvvv
if (auto &call = *static_cast<callable<PARAMETERS ...> *>(m_function.get());
std::is_invocable_v<decltype(call.m_call), params_pack ...>)
{
call.m_call(a_argument ...);
}
}
But I don't know if this is even possible. Any advise?
Thanks!
tl;dr:
Completely abstracting away the signature of the function AND still calling it in a type-safe way is impossible in C++
A type-based event system could be a good alternative
1. Why it's impossible to do what you're asking for
1.1 How Type-Erasure works
Type-erasure is fundamentally based on polymorphism. By defining a set of methods that all objects we want to store have in common (the interface) we don't need to know the actual type we're dealing with.
There is no way to do type-erasure without involving polymorphism.
For example, a very crude implementation of std::function could look like this:
template<class RetVal, class... Args>
class function {
public:
template<class U>
function(U u) : ptr(new impl<U>(u)) {}
~function() { delete ptr; }
RetVal operator()(Args... args) {
return ptr->call(args...);
}
private:
struct base {
virtual ~base() = default;
virtual RetVal call(Args... args) = 0;
};
template<class T>
struct impl : base {
impl(T t): t(t) {}
RetVal call(Args... args) override {
return t(args...);
}
private:
T t;
};
base* ptr;
};
template<class RetVal, class... Args>
class function<RetVal(Args...)> : public function<RetVal, Args...> {};
godbolt example
This is how std::function accomplishes to store any function object that is compatible with it's signature - it declares an interface (base) that will be used by all function objects (impl).
The interface only consists of 2 functions in this case:
The destructor (we need to know how to properly cleanup the function object)
The call() function (for invoking the actual function)
Sidenote 1: A real std::function implementation would need a couple more interface functions, e.g. for copying / moving the callable
Sidenote 2: Your existing implementation has a small bug: struct base MUST have a virtual destructor, otherwise the destructor of struct callable would never be called, resulting in undefined behaviour.
1.2 How your callable would need to work
What you want is an object that completely erases both the function object AND the parameters that you pass.
But what should your interface then look like?
struct base {
virtual ~base() = default;
virtual ??? call(???); // how should this work?
};
This is the underlying problem you're facing - it's impossible to define an interface for your callable - because you don't know what the arguments are gonna be.
This is what #Yakk - Adam Nevraumont implied with "non-uniform" objects - there is no definition of call() that can handle all potential function types.
1.3 Options
So at that point you basically have two options:
Don't erase the function type (like #Yakk - Adam Nevraumont suggested)
Sacrifice compile-time type safety and maintainability by creating an interface that can deal with arbitrary function types
The latter option is what your code currently uses - either the function parameters match or your code has undefined behaviour.
A few other ways to implement it that don't rely on undefined behaviour could be:
Add an interface function for each possible argument combination
struct base {
/* ... */
// All possible ways a `callable` could potentially be invoked
virtual void call(int val0) { throw std::exception("invalid call"); };
virtual void call(std::string val0) { throw std::exception("invalid call"); };
virtual void call(const char* val0) { throw std::exception("invalid call"); };
virtual void call(int val0, std::string val1) { throw std::exception("invalid call"); };
virtual void call(int val0, const char* val1) { throw std::exception("invalid call"); };
// etc...
}
// then implement the ones that are sensible
struct callable<std::string> : public base {
/* ... */
void call(std::string val0) override { /* ... */ }
void call(const char* val0) override { /* ... */ }
}
This obviously gets out of hand rather quickly.
"Accept anything" interface
struct base {
/* ... */
virtual void call(std::any* arr, int length);
};
// then implement the ones that are sensible
struct callable<std::string> : public base {
/* ... */
void call(std::any* arr, int length) override {
if(length != 1) throw new std::exception("invalid arg count");
// will throw if first argument is not a std::string
std::string& value = std::any_cast<std::string&>(arr[0]);
/* ... */
}
};
A bit better, but still looses compile-time type safety.
1.4 Conclusion
Compile-time type-safety with type-erasure is only possible if there is an uniform interface for all possible objects.
It is technically possible to type-erase non-uniform objects, but if you do that you'll loose compile-time type-safety (and need to do those checks at runtime instead)
2. Another Approach: Type-Based Event System
I'd like to propose a different way to handle the events that allows you to have arbitrary events without having to hard-code them into your Events class.
2.1 Basic Functionality
The main idea of this implementation is to have a class for each event you'd want to have that contains the parameters for the given event, e.g.:
struct AppClosingEvent {
const std::string message;
const int exitCode;
};
struct BananaPeeledEvent {
const std::shared_ptr<Banana> banana;
const std::shared_ptr<Person> peeler;
};
// etc...
This would then allow you to use the type of the event struct as a key for your event listeners.
A very simple implementation of this event system could look like this: (ignoring unregistration for now)
class EventBus {
private:
using EventMap = std::multimap<std::type_index, std::function<void(void*)>>;
// Adds an event listener for a specific event
template<class EvtCls, class Callable>
requires std::is_invocable_v<Callable, EvtCls&>
inline void Register(Callable&& callable) {
callbacks.emplace(
typeid(EvtCls),
[cb = std::forward<Callable>(callable)](void* evt) {
cb(*static_cast<EvtCls*>(evt));
}
);
}
// Broadcasts the given event to all registered event listeners
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last; ++it)
(it->second)(&evt);
}
private:
EventMap callbacks;
};
Register() takes a callable object that needs to be invocable with the given event type. Then it type-erases the callable so we can store it as a std::function<void(void*>
Broadcast(evt) looks up all event listeners that are registered based on the type of the event object and calls them.
Example Usage would look like this:
EventBus bus;
bus.Register<AppClosingEvent>([](AppClosingEvent& evt) {
std::cout << "App is closing! Message: " << evt.message << std::endl;
});
bus.Register<BananaPeeledEvent>([](BananaPeeledEvent& evt) {
// TODO: Handle banana peeling
});
AppClosingEvent evt{"Shutting down", 0};
bus.Broadcast(evt);
By using the type of the event as the key both Register() and Broadcast() are completely type-safe - it's impossible to register a function with incompatible function arguments.
Additionally the EventBus class doesn't need to know anything about the events it'll handle - adding a new event is as simple as defining a new class with the members you need for your event.
2.2 Adding the ability to unregister an event listener
I chose to use a multimap in this case because they guarantee to not invalidate iterators, unless the element the iterator points to itself gets removed from the multimap - which allows us to use a multimap iterator as the registration token for the event handler.
Full implementation: godbolt example
/*
EventBus - allows you to register listeners for arbitrary events via `.Register()`
and then later invoke all registered listeners for an event type with `.Broadcast()`.
Events are passed as lvalues, to allow event handlers to interact with the event, if required.
*/
class EventBus {
private:
using EventMap = std::multimap<std::type_index, std::function<void(void*)>>;
public:
/*
Represents a registered event handler on the EventBus.
Works a lot like std::unique_ptr (it is movable but not copyable)
Will automatically unregister the associated event handler on destruction.
You can call `.disconnect()` to unregister the event handler manually.
*/
class Connection {
private:
friend class EventBus;
// Internal constructor used by EventBus::Register
inline Connection(EventBus& bus, EventMap::iterator it) : bus(&bus), it(it) { }
public:
inline Connection() : bus(nullptr), it() {}
// not copyable
inline Connection(Connection const&) = delete;
inline Connection& operator=(Connection const&) = delete;
// but movable
inline Connection(Connection&& other)
: bus(other.bus), it(other.it) {
other.detach();
}
inline Connection& operator=(Connection&& other) {
if(this != &other) {
disconnect();
bus = other.bus;
it = other.it;
other.detach();
}
return *this;
}
inline ~Connection() {
disconnect();
}
// Allows to manually unregister the associated event handler
inline void disconnect() {
if(bus) {
bus->callbacks.erase(it);
detach();
}
}
// Releases the associated event handler without unregistering
// Warning: After calling this method it becomes impossible to unregister
// the associated event handler.
inline void detach() {
bus = nullptr;
it = {};
}
private:
EventBus* bus;
EventMap::iterator it;
};
// Adds an event listener for a specific event
template<class EvtCls, class Callable>
requires std::is_invocable_v<Callable, EvtCls&>
inline Connection Register(Callable&& callable) {
auto it = callbacks.emplace(
typeid(EvtCls),
[cb = std::forward<Callable>(callable)](void* evt) {
cb(*static_cast<EvtCls*>(evt));
}
);
return { *this, it };
}
// Broadcasts the given event to all registered event listeners
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last;)
(it++)->second(&evt);
}
private:
EventMap callbacks;
};
With this you can easily register listeners and unregister them later (e.g. if the class they're bound to gets destructed)
Example:
struct DispenseNachosEvent {};
struct DispenseCheeseEvent {};
class NachoMachine {
public:
NachoMachine(EventBus& bus) {
// register using std::bind
nachoEvent = bus.Register<DispenseNachosEvent>(
std::bind(
&NachoMachine::OnDispenseNachos,
this,
std::placeholders::_1
)
);
// register with lambda
cheeseEvent = bus.Register<DispenseCheeseEvent>(
[&](DispenseCheeseEvent& evt) {
OnDispenseCheese(evt);
}
);
}
// Default destructor will automatically
// disconnect both event listeners
private:
void OnDispenseNachos(DispenseNachosEvent&) {
std::cout << "Dispensing Nachos..." << std::endl;
}
void OnDispenseCheese(DispenseCheeseEvent&) {
std::cout << "Dispensing Cheese..." << std::endl;
}
private:
EventBus::Connection nachoEvent;
EventBus::Connection cheeseEvent;
};
2.3 Other benefits
If you want you can also allow the event handlers to modify the event object - e.g. cancel it - which allows you to return state to the piece of code that called Broadcast()
Example:
struct CancelableExampleEvent {
inline void Cancel() { isCancelled = true; }
inline bool IsCancelled() { return isCancelled; }
CancelableExampleEvent(std::string message) : message(message) {}
const std::string message;
private:
bool isCancelled = false;
};
// Usage:
CancelableExampleEvent evt;
bus.Broadcast(evt);
if(!evt.IsCancelled()) {
// TODO: Do something
}
Event Handlers can remove themselves - this is usually tricky to implement due to iterators being invalidated, but with multimaps it's rather easy to implement:
template<class EvtCls>
inline void Broadcast(EvtCls& evt) {
auto [first, last] = callbacks.equal_range(typeid(EvtCls));
for(auto it = first; it != last;)
(it++)->second(&evt);
}
By incrementing it before calling the function we make sure that it remains valid, even if the event handler chooses to unregister itself as part of its callback.
e.g. this would work:
EventBus::Connection con;
con = bus.Register<SomeEvent>([&con](SomeEvent&){
std::cout << "Received event once!" << std::endl;
con.disconnect();
});
2.4 Try it online!
Here's a godbolt that contains the entire code of this post to try it out.
This is your problem:
class callback
it should be
template<class...Args>
class callback
because you have to think about what happens when the types do not match
void string_parameter(const std::string &s) { std::cout << s << '\n'; }
void long_parameter(long l) { std::cout << l << '\n'; }
callback<long> l(long_parameter);
callback<std::string> s(string_parameter);
l.apply(123);
s.apply("Test");
which works flawlessly.
Now you run into the problem of a central enum for all callbacks.
Events::Register(app::CLOSE, on_close);
Events::Register(app::CLOSE, s, &S::the_app_is_closing);
The problem is that all use of app::CLOSE must know what the signature of the callback must be. The code registering it must know, and the code invoking the callback must know.
Your design, however, carefully forgets this fact, and forces type unsafety at both ends. Then you add so,e template code in the middle to ferry types around... which even if it did work, would be work for no good reason.
template<app::event e>
void Events::Register(event_sig<e>* pf);
template<app::event e, class T>
void Events::Register(T* pt, event_mem_sig<T,e>* pf);
template<app::event e, class...Ts>
void Event::Broadcast(Ts&&....ts);
here we have a more sensible API. The event type is compile time value, so we can do type checking, and store the event callbacks in a type safe list.
...
Now, if you have a reasonably bounded number of events (ie, not 1000s of which under 1% are subscribed to), an even simpler solution is to make an event queue an actual object, instead of an enum and traits.
using token=std::shared_ptr<void>;
template<class...Args>
struct broadcaster {
size_t broadcast(Ts...ts)const;
token subscribe(std::function<void(Ts...)>);
void unsafe_subscribe(void(*)(Ts...));
// IMPLEMENTATION
};
now your code becomes
struct Events {
broadcaster<> appClosing;
};
Events g_events;
struct S
{
void the_app_is_closing();
token listening;
};
S s;
s.listening=g_events.appClosing.subscribe(&s, &S::the_app_is_closing);
g_events.appClosing.unsafe_subscribe(on_close);
g_events.appClosing.broadcast();
The types of the arguments are now tied to the appClosing object, so it is checked at both sibscription and at broadcast, conversion is done automatically.
Here each broadcaster maintains its own listener queue (hence bit above about "1000s of event types most unused). Extra work can be done to reduce the queue storage and share it, but that should onlh be done if you need it. And you probably won't.
The enum solution seems like it reduces duplication, but uniform lists of things with non uniform types are often a sign your list shoudln't be uniform.
Members of a struct are a fine way to list non uniform things. Having them be generated from a template means there isn't code writing duplication. And identical signature broadcasters will share binary implementations, somit isn't inefficient.

rebind one parameter of std::function

In my C++ project I decided to give the new++ features a try. One of those features is the binding of a function with std::function via std::bind.
Now I came to a use case, where I have to rebind the std::function.
Consider the following simplified code:
class Test
{
public:
void first()
{
second(bind(&Test::third, this));
}
void second(function<void()> fun)
{
Test *other = new Test();
fun->rebindLastParameter(other); // How can I do this?
fun();
}
void third()
{
// This is called in context of "other"
}
}
How can I do the fun->rebindLastParameter(other); part (replace this pointer with other)?
(EDIT) Context:
In my application there are several classes which inherit from a class called BaseModel. Those classes are automatically transpiled from a self made description language. The following class represents a simple "asteroid" which consists of two other "asteroids":
#pragma once
#include "BaseModel.h"
#include <functional>
using namespace std;
using namespace std::placeholders;
class Test : public BaseModel
{
public:
Test(const OBB& start_obb) : BaseModel(start_obb) {}
void __init() {
scene();
}
void scene() {
combine(bind(&Test::asteroid, this),bind(&Test::asteroid, this));
}
void asteroid() {
translate(random_float(),random_float(),random_float());
sphere(7);
repeat(400,bind(&Test::impact, this));
}
void impact() {
auto p1 = random_surface_point();
select_sphere(p1,random_float() * 2 + 1,1.0);
normalize(p1);
translate_selection(-p1 * random_float() * 0.4);
}
};
The problem lies in the function BaseModel::combine, that combines (via constructive solid geometry) two new objects (1st asteroid and 2nd asteroid):
void BaseModel::combine(function<void()> left, function<void()> right)
{
BaseModel *leftModel = (BaseModel*) ::operator new (sizeof(BaseModel));
BaseModel *rightModel = (BaseModel*) ::operator new (sizeof(BaseModel));
leftModel->initWithStartOBB(*this->obb);
rightModel->initWithStartOBB(*this->obb);
auto newLeft = bind(left, leftModel); // This does not work
auto newRight = bind(right, rightModel); // This does not work
newLeft();
newRight();
// ... CSG stuff
}
As leftModel and rightModel have to be new models of the same class, I need to rebind the first parameter I previously give in my automatically transpiled class Test::scene.
Perhaps I'm on the wrong track. I hope that additional context could explain why I've run into that problem.
As #tobi303 and others have noted, your function signature for the argument of second is too constrained, as it takes a nullary function. There is nothing to rebind - it doesn't take any parameters.
In order to achieve something like it looks like you're trying to do, you need to have the argument of second be less constricted. There are several ways of doing so (making it take a function, or a pointer to a member function); the following shows it template-parameterized by a function that takes a unary argument:
#include <functional>
using namespace std;
class Test
{
public:
void first()
{
second([](Test *p){p->third();});
}
template<class Fn>
void second(Fn fn)
{
Test *const other = new Test();
fn(other);
}
void third()
{
// This is called in context of "other"
}
};
int main()
{
Test t;
t.first();
}
Personal viewpoint (one that earned me several downvotes): I think the use of many libraries and techniques, most cases of bind for sure, most cases of function - simply precede current lambda functions, and there is less and less of a need for them.
How can I do the fun->rebindLastParameter(other); part (replace this pointer with other)?
You can't, in general.
std::function relies on type-erasure which means the original type of the object that was stored in the std::function is not part of the type, and not easily accessible.
If you know for certain that the fun definitely stores an object returned by bind(&Test::third, this) then there's no need to rebind the argument, just modify fun to hold a completely different function object with the right argument, i.e.
fun = bind(&Test::third, other);
If you know it definitely stores an object returned by bind( &Test::???, other) where &Test::??? is any member function with exactly the same signature as Test::third then you could do something like this:
using binder_type = decltype(bind(&Test::third, this));
if (auto target = fun.target<binder_type>())
{
// *target is the result of the bind() expression
}
But there's still no way to modify the object at *target to replace the Test* pointer it holds.
If you know the set of functions that could have been used then you could do:
using binder_foo_type = decltype(bind(&Test::foo, this));
using binder_bar_type = decltype(bind(&Test::bar, this));
using binder_baz_type = decltype(bind(&Test::baz, this));
if (fun.target<binder_foo_type>())
{
fun = std::bind(&Test::foo, other);
}
else if (fun.target<binder_bar_type>())
{
fun = std::bind(&Test::bar, other);
}
else if (fun.target<binder_baz_type>())
{
fun = std::bind(&Test::baz, other);
}
But these are not general purpose solutions and not very maintainable.
std::mem_fn is what you are looking for, as it generates wrapper objects for pointers to members.
std::function<void(Test*)> f = std::mem_fn(&Test::third);
f(this);
Test *other = new Test();
f(other);
With std::bind, use fun with a reference to Test object. This way you can call it with a new object
void second(std::function<void(const Test&)> fun)
{
Test *other = new Test();
fun(*other);
}
Or with this object
fun(*this);

Missing call to bound pointer to member function

I am trying to implement a generic event handling system with templates, but I get an error at compile time when I try to add the function to a list.
error C2298: missing call to bound pointer to member function
class EventManager
{
public:
template <class OBJECT>
void subscribe(std::string eventName, OBJECT *obj, void(OBJECT::*newEvent)(Event))
{
(obj->*newEvent)(Event()); // I can call the event just fine if I execute it alone
abc.push_back(obj->*newEvent); // Error c2298 here
}
static EventManager* Get();
private:
std::vector<void(*)(Event)> eventsList;
};
And this is where I call it:
EventManager::Get()->subscribe("EventName", this, &TestClass::eventTest);
void ATideManager::eventTest(Event event)
{
//Test
}
I am quite new to C++ and templates, so I'm sure the solution is easy, but I don't understand why I can call the event but not add it to the vector. Do you know how I could possibly do that?
As the documentation for that error message says:
A pointer to member-function expression must call the member function.
In other words, you cannot store a pointer to member-function including the object on which to call it, for later use.
Here is a simpler example using names similar to yours:
struct Object
{
void f() {}
};
int main()
{
Object obj;
using member_function_pointer = void (Object::*)();
member_function_pointer ptr = &Object::f;
(obj.*ptr)();
(obj.*ptr); // error
}
And this makes a lot of sense. Your abc is probably a vector of pointers to member-function (or just a vector of function pointers); it cannot magically store an object along with each pointer in it.
Generally, pointers to member functions are not exactly the nicest, cleanest or best feature of C++, and the awful syntax renders every piece of code using it completely unreadable. Fortunately, C++11 introduced std::function and lambdas, which gives you a much better alternative:
#include <functional>
#include <iostream>
#include <string>
#include <vector>
struct Event
{
int i;
};
class EventManager
{
public:
void subscribe(std::string const& eventName,
std::function<void(Event const&)> event)
{
abc.push_back(event);
}
static EventManager& get()
{
static EventManager instance;
return instance;
}
void onEvent(Event const& event)
{
for (auto&& f : abc)
{
f(event);
}
}
private:
EventManager() {}
EventManager(EventManager const&) = delete;
EventManager& operator=(EventManager const&) = delete;
std::vector<std::function<void(Event const&)>> abc;
};
struct ATideManager
{
void f()
{
EventManager::get().subscribe("EventName",
[=](Event const& event) { eventTest(event); });
}
void eventTest(Event const& event)
{
std::cout << "eventTest: " << event.i << "\n";
}
};
int main()
{
ATideManager manager;
manager.f();
Event some_event{ 123 };
EventManager::get().onEvent(some_event);
}
I've also fixed your needless use of pointers where references can be used, and some const-correctness issues.
obj->*newEvent is invalid. A member function pointer can be used in this way only to call the pointed-to member function.
You can however use std::vector<std::function<void(Event)>> and
abc.push_back(std::bind(newEvent, obj, std::placeholders::_1);
std::bind reference

Submitting a task to a Thread Pool Implementation Issue

I'm using thread pools for the first time, working out of Anthony Williams' Concurrency In Action book. He provides a basic thread pool class that I'm trying to use but not an implementation - just the class. The issue is that I'm new to templates and thread-pools. This is probably a simple question/answer but I can't figure it out. I have this function to submit jobs to the pool:
class SimpleThreadPool
{
public:
...
// -- Submit a task to the thread pool
template <typename FunctionType>
void submit(FunctionType f);
...
};
I'm trying to call it but honestly don't know how (have tried a few different things):
boost::interprocess::scoped_lock<std::mutex> lock(m_mtx_map);
for(const auto& elem : m_logger_map)
{
m_thread_pool->submit< std::function< void > >(elem.second->operator());
}
Here the m_thread_pool is a pointer to the thread pool and the map contains (string,pointer) pairs where the pointer points to a logging object which has it's main run/processing method in operator().
I'm getting a:
error: no matching function call 'SimpleThreadPool::submit(< unresolved overloaded function type >)'
How do I correctly use this submit function?
Thank you!
UPDATE -----
Here's the implementation in the thread pool class:
// -- Submit Method
/** void submit(FunctionType f)
* #desc : Submit a job (function pointer) to the pool
*/
template <typename FunctionType> void SimpleThreadPool::submit(FunctionType f)
{
m_q_work.push(std::function<void()>(f));
}
m_q_work is a thread-safe Queue.
// -- Launch a new worker thread
/** void m_worker_thread()
* #desc : Worker thread main method for getting tasks and executing
*/
void SimpleThreadPool::m_worker_thread()
{
while(!m_done)
{
std::function<void()> task;
if(m_q_work.try_pop(task))
{
task();
}
else
{
std::this_thread::yield();
}
}
}
I'm guessing I probably need to change the implementation based on my comment to the response below.
The following compiled in g++
#include <map>
#include <string>
#include <functional>
class SimpleThreadPool {
public:
template <typename FunctionType>
void submit(FunctionType f) { }
};
class Logger {
public:
void operator()() { }
};
int main(int argc,char **argv) {
std::map<std::string,Logger*> m_logger_map;
m_logger_map["one"]=new Logger();
SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
for (const auto& elem: m_logger_map) {
m_thread_pool->submit<std::function< void() > >(*elem.second);
}
}
Changes are:
1.- std::function< void() >, instead of std::function<void> (yours only had the return type, but not the parameters (note that I've defined the operator() with empty parameters).
2.- *elem.second as the argument to submit (instead of elem.second->operator()). Note that a function object (i.e. an object of class with an operator() defined) can be used as a std::function (refer to the examples in the std::function reference)
Edit: avoid the lack of copy constructor
Instead of using directly the Logger object that cannot be copy-constructed, we can use a Wrapper object. This Wrapper object contains a reference to the Logger class.
I've also changed the code to use shared_ptr, because memory ownership becomes more complex:
#include <map>
#include <string>
#include <functional>
#include <memory>
class SimpleThreadPool {
public:
template <typename FunctionType>
void submit(FunctionType f) { }
};
class Logger {
public:
Logger() { }
Logger(const Logger&) = delete; // Logger cannot be copied
void operator()() { }
};
template <typename T>
class Wrapper {
public:
Wrapper(const std::shared_ptr<T> &l):mWrapped(l) { } // Wraps a T reference
void operator()() {
(*mWrapped)(); // expected to be a function object
}
private:
std::shared_ptr<T> mWrapped;
};
int main(int argc,char **argv) {
// Need to change the definition of the map
// to contain shared_ptr.
std::map<std::string,std::shared_ptr<Logger> > m_logger_map;
m_logger_map["one"]=std::make_shared<Logger>();
SimpleThreadPool *m_thread_pool=new SimpleThreadPool();
for (const auto& elem: m_logger_map) {
// Create the Wrapper object from the reference we've
// obtained from the map.... The wrapper can be copied
// around, but the reference will not change.
std::function<void()> f=Wrapper<Logger>(elem.second);
m_thread_pool->submit<std::function< void() > >(f);
}
}

generic c++11 function wrapper for task based parallelism

I am implementing a work stealing algorithm and am writing a generic function wrapper that takes a promise as one of the variadic arguments to the wrapper template. I want to create tasks with these function wrappers and get each node to communicate to dependent nodes using promises. Each node maintains a list of dependent nodes and promises/futures. Each node can run by checking if all futures have been set. promises can vary depending on the job the function wrapper is doing returning different objects. If a single algorithm can be broken into separate operations like read message and decode message, perform checks on object, return result of all checks, each of these actions will return a different promise (object, boolean, result).
The book, C++ Concurrency in Action, has a function wrapper implementation however, that doesn't handle this use case. In other references online, I've seen hardcoded references to promises like std::promise which is only one type.
Can someone advise how I can write a wrapper to achieve the following...
void add(int a, int b, std::promise<int>&& prms)
{
int res = a + b;
try {
prms.set_value(res);
}
catch(...)
{
prms.set_exception(std::current_exception());
}
}
int main()
{
std::promise<int> prms;
std::future<int> fut = prms.get_future();
FunctionWrapper myFunctor(a, 10, 20, std::move(prms));
// add the functor to the queue and it will be retrieved by a thread
// that executes the task. since i have the future, i can pass it to the
// dependent worknode
}
I tried writing the code like below...but was facing difficulties in getting this to work.
#ifndef FUNCTIONWRAPPER_HPP
#define FUNCTIONWRAPPER_HPP
template<typename F, typename R, typename... Args>
class FunctionWrapper
{
class implbase
{
public:
virtual ~implbase();
virtual R execute(Args...)=0;
};
class impl : public implbase
{
public:
impl(F&& f) : func(std::move(f)) {}
virtual R execute(Args... args) { return func(args...); }
private:
F func;
};
std::shared_ptr<impl> internalFunc;
public:
FunctionWrapper(F&& f) : internalFunc(0)
{
internalFunc = new impl<F, R, Args...>(f);
}
FunctionWrapper(const FunctionWrapper& other)
: internalFunc(std::move(other.internalFunc))
{}
~FunctionWrapper()
{
if(internalFunc)
delete internalFunc;
}
R operator()(Args... args)
{
return internalFunc->execute(args...);
}
void swap(FunctionWrapper& other)
{
impl<R, Args...>* tmp = internalFunc;
internalFunc = other.internalFunc;
other.internalFunc = tmp;
}
FunctionWrapper& operator=(const FunctionWrapper& other)
{
FunctionWrapper(other).swap(*this);
return *this;
}
FunctionWrapper& operator=(const F& f)
{
FunctionWrapper(f).swap(*this);
return *this;
}
};
#endif // FUNCTIONWRAPPER_HPP
C++11 has a wrapper for doing just this! It is called packaged_task.
What it does, is it wraps a callable object (function objects, lambdas, function pointers, bind expressions, etc...) and provides you a future via the get_future() method that matches the return type of the function passed in.
Consider the following example:
#include <thread>
#include <future>
#include <functional>
#include <iostream>
using namespace std;
int add(int a, int b)
{
return a + b;
}
int main()
{
// Create a std::packaged_task and grab the future out of it.
packaged_task<int()> myTask(bind(add, 10, 20));
future<int> myFuture = myTask.get_future();
// Here, is where you would queue up the task in your example.
// I'll launch it on another thread just to demonstrate how.
thread myThread(std::move(myTask));
myThread.detach();
// myFuture.get() will block until the task completes.
// ...or throw if the task throws an exception.
cout << "The result is: " << myFuture.get() << endl;
return 0;
}
As you can see, rather than passing in a promise, we are counting on the packaged_task to create the promise and give us the future.
Also, using a bind expression has allowed us to effectively hand arguments to the task to hold onto until it is called.
Using packaged_task also puts the burden pushing exceptions through the future into the hands of the packaged_task. That way, your functions do not need to call set_exception(). They only have to return or throw.