简体   繁体   English

boost :: lockfree ::函数队列?

[英]boost::lockfree::queue of functions?

I'd like to build a simple boost::lockfree::queue of functions that take no arguments and return no values. 我想构建一个简单的boost::lockfree::queue函数boost::lockfree::queue ,它不带参数并且不返回任何值。

It appears that boost::lockfree::queue requires the item type to be trivially assignable and destructible, requirements that boost::function<void ()> unfortunately doesn' meet. 似乎boost::lockfree::queue要求项类型可以简单地分配和破坏,不幸的是, boost::function<void ()>并不满足。

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: 本着https://stackoverflow.com/a/21406186/393756的精神,我现在试图通过普通函数指针的boost::lockfree::queue来实现这一点:

boost::lockfree::queue<void (*)()> queue;

Can I push a boost::function<void ()> into this queue? 我可以将boost::function<void ()>推入此队列吗? If so, how? 如果是这样,怎么样?

Can I push a boost::function<void()> into this queue? 我可以将boost::function<void()>推入此队列吗?

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. 不是直接的,因为boost::function<void()>是一个重量级拥有类型擦除的包装器,它不能隐式转换为函数指针并且还存储一些数据。

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. 如果你需要一个可以引用任何函数对象的简单可分配类型,你可以实现一个指向某个函数对象而不拥有它的function_view类。 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. 如果您对生命周期保持谨慎并保证function_view始终指向“活动对象”,则可以安全地将其存储在队列中。

Conceptually, function_view is a pair of pointers. 从概念上讲, function_view是一对指针。 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 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>> ). 使用callback_base作为noexcept-movable类型(又名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 这里的挑战是何时删除此实例时考虑到异常安全性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM