I'd like to build a simple boost::lockfree::queue of functions that take no arguments and return no values.
It appears that boost::lockfree::queue requires the item type to be trivially assignable and destructible, requirements that boost::function<void ()> unfortunately doesn' meet.
In the spirit of https://stackoverflow.com/a/21406186/393756, I'm now trying to achieve this by a boost::lockfree::queue of plain function pointers:
boost::lockfree::queue<void (*)()> queue;
Can I push a boost::function<void ()> into this queue? If so, how?
Can I push a boost::function<void()> into this queue?
Not directly, as boost::function<void()> is an heavyweight owning type-erased wrapper that is not implicitly convertible to a function pointer and also stores some data.
If you need a trivially-assignable an trivially-destructible type that can refer to any function object, you could implement a function_view class that points to some function object without owning it. If you're careful with lifetimes and guarantee that function_view always points to "live objects" you can safely store instances of that in your queue.
Conceptually, function_view is a pair of pointers. I have an implementation in my "passing functions to functions" article, which I'm pasting below:
template <typename TReturn, typename... TArgs>
class function_view<TReturn(TArgs...)> final
{
private:
using signature_type = TReturn(void*, TArgs...);
void* _ptr;
TReturn (*_erased_fn)(void*, TArgs...);
public:
template <typename T, typename = std::enable_if_t<
std::is_callable<T&(TArgs...)>{} &&
!std::is_same<std::decay_t<T>, function_view>{}>>
function_view(T&& x) noexcept : _ptr{(void*)std::addressof(x)}
{
_erased_fn = [](void* ptr, TArgs... xs) -> TReturn {
return (*reinterpret_cast<std::add_pointer_t<T>>(ptr))(
std::forward<TArgs>(xs)...);
};
}
decltype(auto) operator()(TArgs... xs) const
noexcept(noexcept(_erased_fn(_ptr, std::forward<TArgs>(xs)...)))
{
return _erased_fn(_ptr, std::forward<TArgs>(xs)...);
}
};
This class passes the following tests:
using type = function_view<void()>;
static_assert(is_trivially_assignable<type, type>{});
static_assert(is_trivially_destructible<type>{});
live example on wandbox
no, but you can use dynamic memory allocation + type erasure for that cause:
struct callback_back{
virtual void execute() = 0;
~callback_base() = default;
};
template<class F>
class callback{
private:
F m_function;
public:
callback(F&& function) : m_function(std::forward<F>(function)){}
virtual void execute() {
m_function();
}
}
template<class F>
std::unique_ptr<callback_base> make_callback(F&& f){
return std::unique_ptr<callback_base>(
new callback<F>(std::forward<F>(f));
);
}
use callback_base as a noexcept-movable type (aka boost::lockfree::queue<std::unique_ptr<callback_base>>).
The only way I found so far is to make a raw pointer of the function object
boost::lockfree::queue<std::function<void(void)> *> tasks_; // the queue
// let f = stack allocated std::function<T(T)> instance
tasks_.push(new std::function<void(void)>(f));
// pop
std::function<void(void)> * f;
tasks_.pop(f);
// execute in try/catch make sure to delete in case of exception?
(*f)();
// you should delete f here if you are done with it
// in the destructor of the class that owns tasks_ you should delete the remaining std::function instances
The challenge here is to when to delete this instance with exception safety in mind
Related
I've been trying to expand a non value parameter pack recently in C++. Is this possible? And if it's not, why?
I mean, as you can see, in the line with the comment //, given a parameter pack for the TypeMap class, how can I call addType<T>() with each type of the parameter pack? Thanks in advance!
template <typename... T>
class TypeMap
{
using vari_cmps = std::variant<T*...>;
private:
template<typename Type>
void addType()
{
typemap[typeid(Type).name()] = std::make_unique<Type>(0).get();
}
public:
std::map<const char*, vari_cmps> typemap{};
TypeMap()
{
(addType<T,...>()); // Idk how to use this in order to make it work
}
~TypeMap()
{
typemap.clear();
}
};
As #HolyBlackCat has already answered in the comments, you can expand it like this:
TypeMap() {
(addType<T>(), ...);
}
If T is std::string, int, float this would expand to:
TypeMap() {
(addType<std::string>(), addType<int>(), addType<float>());
}
There are however a few more issues in this code-snippet:
1. addType()
addType() will not work as you'd expect, due to the unique_ptr deleteing your object after you put it into the map.
.get() only retrieves the pointer that the unique_ptr manages but does not transfer ownership, so the unique_ptr will still delete the pointed-to object once it gets out of scope, leaving a dangling pointer in your map.
so your addType() is roughly equivalent to:
template<typename Type>
void addType() {
Type* tptr = new Type(0); // unique pointer constructs object
typemap[typeid(Type).name()] = tptr; // insert pointer value of unique pointer
delete tptr; // unique pointer destructs
}
You could fix this by releasing the unique_ptr after inserting its value into the map & then cleaning it up in the destructor:
template<typename Type>
void addType() {
auto ptr = std::make_unique<Type>(0);
typemap[typeid(Type).name()] = ptr.get();
ptr.release(); // now unique_ptr won't delete the object
}
~TypeMap() {
// cleanup all pointers
for(auto& [name, ptrVariant] : typemap)
std::visit([](auto ptr) { delete ptr; }, ptrVariant);
}
2. Consider using std::type_index instead of const char* as map key
std::type_info::name() returns an implementation-defined name for the given type, so you have no guarantee that you will get an unique name for a given type.
Returns an implementation defined null-terminated character string containing the name of the type. No guarantees are given; in particular, the returned string can be identical for several types and change between invocations of the same program.
std::type_index on the other hand is build specifically for this purpose - using types as keys - and comes with all comparison operators & a std::hash specialization, so you can use it with std::map & std::unordered_map out of the box.
e.g.:
template <class... T>
class TypeMap
{
using vari_cmps = std::variant<T*...>;
private:
template<typename Type>
void addType()
{
typemap[std::type_index(typeid(Type))] = /* something */;
}
public:
std::map<std::type_index, vari_cmps> typemap{};
TypeMap() { /* ... */ }
~TypeMap() { /* ... */ }
template<class U>
U* get() {
auto it = typemap.find(std::type_index(typeid(U)));
return std::get<U*>(it->second);
}
};
Consider using std::tuple
std::tuple is basically built for this task, storing a list of arbitrary types:
e.g.:
template <class... T>
class TypeMap
{
private:
std::tuple<std::unique_ptr<T>...> values;
public:
TypeMap() : values(std::make_unique<T>(0)...) {
}
template<class U> requires (std::is_same_v<U, T> || ...)
U& get() { return *std::get<std::unique_ptr<U>>(values); }
template<class U> requires (std::is_same_v<U, T> || ...)
U const& get() const { return *std::get<std::unique_ptr<U>>(values); }
};
usage:
TypeMap<int, double, float> tm;
tm.get<int>() = 12;
If you want you can also store T's directly in the tuple, avoiding the additional allocations.
As per the documentation(http://www.cplusplus.com/reference/functional/function/), which says that:
Class that can wrap any kind of callable element (such as functions
and function objects) into a copyable object, and whose type depends
solely on its call signature (and not on the callable element type
itself).
How to comprehend that the type of std::function depends solely on its call signature(and not on the callable element type itself)? Could somebody make it clear by giving some simple examples?I would be greatful to have some help with this question.
The template type effectively denotes a function signature (excluding name of course).
std::function<bool(Bar const&, Foo const&)>
Can hold a functor, member function pointer, function pointer or lambda. But the callable must have the bool (Bar const&, Foo const&) signature.
class Foo {};
class Bar {};
class FunctorEx
{
public:
bool operator()(Bar const&, Foo const&)
{
return true;
}
} FunctorExInst;
class MemFunction
{
public:
bool MemFunctionEx(Bar const&, Foo const&)
{
return true;
}
} MemFunctionInst;
bool FunctionEx(Bar const&, Foo const&)
{
return true;
}
int main()
{
auto LambdaEx = [] (Bar const&, Foo const&) -> bool
{
return true;
};
std::function<bool(Bar const&, Foo const&)> exFunctionVar;
exFunctionVar = std::bind(&MemFunction::MemFunctionEx, &MemFunctionInst, std::placeholders::_1, std::placeholders::_2);
exFunctionVar = FunctorExInst;
exFunctionVar = FunctionEx;
exFunctionVar = LambdaEx;
}
Despite MemFunctionInst, FunctorExInst, FunctionEx, LambdaEx all being of different types, they can all be assigned to the same std::function variable due to a technique called type erasure.
There are different kinds of callable's, namely functions and functors. std::function was designed to not mater which of those you give to it, for example, lets consider a std::function <void()>. Here we say the function is one that return nothing and takes nothing, which means that
void foo() {}
auto bar = []{};
struct { void operator()(){} } baz;
are all things that can be assigned to it, even though they are all different types.
These two "callable elements" have the same call signatures (namely, int(float)), even though they have different types:
struct Functor {
int operator()(float arg) {
...
}
};
int function(float arg) {
...
}
This means you can use the same std::function type to represent either of them:
std::function<int(float)> f;
f = Functor();
f = function;
If we forget all gory details, then the important method of std::function is operator().
Consider you write a wrapper for callables with signature double (int,int), then the wrapper will be something similar to:
struct example_wrapper {
double operator()(int a,int b) { return 42; }
};
The details I left out is what enables you to make std::function wrap any kind of callable. If the callables have the same signature, then the wrapper can have the exact same public interface (ie it is the same type). If the callables have different signature, the wrapper needs a different public interface (ie it is a different type).
This means simply that the type of the callable stored in std::function does not impact the type of std::function itself, only the function signature does.
This can for example be implemented as such non-optimized:
template<class F, class Ret, class... Args>
Ret invoke_functor(void* func, Args&& ...args)
{
return (*reinterpret_cast<F*>(f))(std::forward<Args>(args)...);
}
template<class Ret, class... Args>
Ret invoke_function(void* func, Args&& ...args)
{
return reinterpret_cast<Ret(*)(Args...)>(func)(std::forward<Args>(args...);
}
template<class Ret, class... Args> //wrong but close enough
class function
{
public:
template<class Functor>
function(Functor&& f) :
m_func(new Functor(f)), //leak
m_invoke(&invoke_functor<Functor, Ret, Args...>)
{ }
function(Ret(*ptr)(Args...)) :
m_func(ptr),
m_invoke(&invoke_function<Ret, Args...>)
{ }
Ret
operator()(const Args& ...args)
{
return m_invoke(m_func, args);
}
private:
void* m_func;
Ret(*m_invoke)(void*, Args...);
}
Here std::function can be created from both functions and callable structures as shown by the other answers.
For a Packaged_Task implementation in C++11
i want to achieve what i've expressed in C++14 Code below. In other words i want to forward into a lambda expression.
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = [f = std::forward<F>(f)]() mutable { return std::move(f); };
///...
I'm aware of workarounds for moving into a lambda (but unfortenately this workarounds need a default constructible Object, in my case the object is most often a lambda expression without default-constructor)
How about creating a wrapper struct which does a move during copy construction:(. (I know that's bad, makes me remember of auto_ptr)
template <typename F>
struct Wrapped {
using Ftype = typename std::remove_reference<F>::type;
Wrapped(Ftype&& f): f_(std::move(f)) {}
Wrapped(const Wrapped& o): f_(std::move(o.f_)) {}
mutable Ftype f_;
};
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
Wrapped<std::remove_reference<decltype(f)>::type> wrap(std::forward<F>(f));
auto f_holder = [wrap]() mutable { return std::move(wrap.f_); };
This is just a rough idea. Not compiled or tested.
NOTE: I have seen this technique before, do not remember whether it was on SO itself or on some blog.
First, let's boil down the question to its core: the function object is somewhat of a distraction. Essentially, you want to be able to create a lambda with a capture holding a move-only object. In C++11 that isn't directly supported which gave raise to the C++14 approach of allowing specification of how the capture is build.
For C++11 it is necessary to use a copy. Since the underlying type doesn't support copying, it become necessary to actually move the object instead of copying it. Doing so can be achieved by a suitable wrapper defining a copy constructor not really copying but rather moving. Here is an example showing that:
#include <utility>
struct foo {
foo(int) {}
foo(foo&&) = default;
foo(foo const&) = delete;
};
template <typename T>
class move_copy
{
T object;
public:
move_copy(T&& object): object(std::move(object)) {}
move_copy(move_copy& other): object(std::move(other.object)) {}
T extract() { return std::forward<T>(this->object); }
};
template <typename T>
void package(T&& object)
{
move_copy<T> mc(std::forward<T>(object));
foo g = [mc]() mutable { return mc.extract(); }();
}
int main()
{
foo f(0);
package(std::move(f));
}
The move_copy<T> wrapper actually just captures the argument the way it is passed: if an lvalue is being passed in, an lvalue is captured. To properly get hold of the contained object, the extract() member std::forward<T>()s the object: the function can be called only once safely as an object is potentially moved from there.
Breaking copy semantics by making it a move is a bad idea. If it was the only option, go for it, but it is not.
Instead, we can pass the moved value in as an argument to the lambda, and move it into the wrapping code.
curry_apply takes some value and a function object, and returns that function object with the value bound to the first argument.
template<class T, class F>
struct curry_apply_t {
T t;
F f;
template<class...Args>
auto operator()(Args&&...args)
-> typename std::result_of_t<F&(T&, Args...)>::type
{
return f(t, std::forward<Args>(args)...);
}
};
template<class T, class F>
curry_apply_t<typename std::decay<T>::type, typename std::decay<F>::type>
curry_apply( T&& t, F&& f ) {
return {std::forward<T>(t), std::forward<F>(f)};
}
Use:
template<class F>
Packaged_Task(F&& f) {
Promise<R> p;
_future = p.get_future();
auto f_holder = curry_apply(
std::move(_future),
[](Future<R>& f) mutable { return std::move(f); };
);
basically we store the moved-in data outside of the lambda in a manually written function object. We then pass it in as an lvalue argument at the front of the lambda's argument list.
Here is a more complex version of the same solution.
I am currently in the process of writing a method execution queue in C++x0. I have implemented and verified the basic queue mechanism but want to amend it with an option to have push() automatically remove all previous calls to a specific method:
queue.push(this, &Obj::foo, 1);
queue.push(this, &Obj::foo, 2);
queue.push(this, &Obj::foo, 3);
should be the same as merely calling
queue.push(this, &Obj::foo, 3);
My code thus far looks like this:
Queue.h:
#pragma once
#include <functional>
#include <vector>
using std::vector;
using std::function;
using std::bind;
class Queue
{
private:
struct functioncall {
std::function<void()> call;
};
vector<functioncall> queue;
public:
Queue();
~Queue();
template<typename T, typename F, typename... Args>
int push(T, F , Args... args);
int pop();
bool empty();
size_t size();
};
template<typename T, typename F, typename... Args>
int Queue::push(T instance, F func, Args... args)
{
functioncall newelem = { bind(func, instance, args...) };
queue.push_back(newelem);
return queue.size();
}
Queue.cpp:
#include "Queue.h"
Queue::Queue() : queue()
{
}
Queue::~Queue()
{
delete &queue;
}
int Queue::pop()
{
if(!queue.empty())
{
queue.front().call();
queue.erase(queue.begin());
return queue.size();
}
return 0;
}
bool Queue::empty()
{
return queue.empty();
}
size_t Queue::size()
{
return queue.size();
}
I have already prepared the vector queue to take a struct in wich I want to not only save the result of std::bind but also the pointer to the method being called so I can look for that pointer and remove the old entries.
The issue is that the functions passed to push() can take an arbitrary amount of arguments. Is there a generic pointer type (it doesn't have to be executable, just be the same when I repeatedly push the same function to the queue) that can do that?
Per 5.2.10p10, you can cast a pointer to member function T::*(A1, A2, ...) to another pointer to member function type U::*(B1, ...) and back with no loss of information; std::less can compare pointers to member functions so by casting to a dummy pointer-to-member type void (Impl::*)() you can compare pointer to member functions with the same signature.
However, it is not guaranteed that pointer to member functions with different signatures will compare different when cast to the same pointer to member type, so you will need to encode the signature in your comparable type. typeid will work here:
auto key = std::make_pair(&typeid(F), reinterpret_cast<void (Queue::*)()>(func));
This assumes that F is indeed a pointer to member function; if the user attempts to pass some other callable object then this will break.
std::function::target<>() can be used to check wrapped function type:
template <class F> bool is_same_call(const functionalcall& prevCall, F newCall)
{
const F* pf = prevCall.call.target<F>();
return pf ? *pf == newCall : false;
}
Note that std::function::target() will return nullptr if function wrapped with std::function object has type different from F.
I just dont know how to do it..
Basically, if each template specialization type (T) have different parameters for its initialization, how can a generalized ResourceCache load/create a resource?
template< class T>
class ResourceCache{
T* cache[100];
T* LoadResource(different parameters for different T ){//used in a cache miss..
Create( different parameters for different T );
}
}
If I use abstraction for, i.e., a IResourceParams class, my ResourceCache will not be able to use its own known type resource data without using polymorphism, its kinda stupid, since at runtime he knows what the type is, id be tottaly doing shit at runtime in prol of a compile time facility...I guess..
On my current try I created a templated IResourceDesc that have a virtual T* Create() method, so you need to derive for add data and specialize the Create method, but it sucks, because I cant have a collection of IResourceDesc in the ResourceCache class ( for comparing current loaded ones, acquiring cached resources by desc, etc)...
In C++11, this is rather easy with a variadic template and perfect-forwarding:
#include <utility>
template<class... Args>
T* LoadResource(Args&&... args){
unsigned dest_index = /* pick it */ 0;
cache[dest_index] = new T(std::forward<Args>(args)...);
return cache[dest_index];
}
For C++03, either provide ~10 overloads with different number of parameters or go for the in-place factory style:
template< class T>
class ResourceCache{
T* cache[100];
template<class Factory>
T* LoadResource(Factory const& f){
unsigned dest_index = /* pick cache slot */ 0;
void* dest = operator new(sizeof(T));
cache[dest_index] = f.construct(dest);
return cache[dest_index];
}
}
template<class T, class A1>
struct in_place_factory1{
in_place_factory1(A1 const& a1) : _arg1(a1) {}
int* construct(void* dest) const{
return new (dest) T(_arg1);
}
private:
A1 const& _arg1; // make sure the original argument outlives the factory
};
// in code
ResourceCache<int> cache;
int arg = 5;
int* res = cache.LoadResource(in_place_factory1<int,int>(arg));
In-place factories are basically an inferior version of perfect-forwarding variadic template functions that can emplace the object directly into the containers storage without requiring an already complete object for a copy.