Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Premature unwrapping of boost::ref'ed arguments #2118

Closed
hkaiser opened this issue Apr 25, 2016 · 2 comments

Comments

Projects
None yet
2 participants
@hkaiser
Copy link
Member

commented Apr 25, 2016

The following test case demonstrates the issue:

//  Copyright (c) 2016 Hartmut Kaiser
//
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

// This test case demonstrates premature unwrapping of boost::ref'ed arguments .

#include <hpx/hpx_main.hpp>
#include <hpx/hpx.hpp>

#include <utility>

#include <boost/ref.hpp>

struct non_copyable
{
    HPX_NON_COPYABLE(non_copyable);

    non_copyable() {}
};

void test(non_copyable& o)
{
}

struct test_obj
{
    template <typename F, typename ... Ts>
    void operator()(F && f, Ts &&... ts) const
    {
        hpx::async(std::forward<F>(f), std::forward<Ts>(ts)...);
    }
};

template <typename F, typename ... Ts>
hpx::future<void> rebind(F && f, Ts &&... ts)
{
    return hpx::make_ready_future().then(
        hpx::util::bind(
            hpx::util::one_shot(test_obj()),
            hpx::util::protect(std::forward<F>(f)), std::forward<Ts>(ts)...
        )
    );
}

int main()
{
    non_copyable o;
    rebind(&test, boost::ref(o)).get();

    return 0;
}

@hkaiser hkaiser added this to the 0.9.12 milestone Apr 25, 2016

@K-ballo

This comment has been minimized.

Copy link
Member

commented Apr 25, 2016

This code is not supposed to work, bind is supposed to unwrap reference_wrappers which leads to a call to async with a non_copyable& argument.

@hkaiser

This comment has been minimized.

Copy link
Member Author

commented Apr 25, 2016

The implementation has to change to:


template <typename F, typename ... Ts>
hpx::future<void> rebind(F && f, Ts &&... ts)
{
    return hpx::make_ready_future().then(
        hpx::util::bind(
            hpx::util::one_shot(test_obj()),
            hpx::util::deferred_call(std::forward<F>(f), std::forward<Ts>(ts)...)
        )
    );
}

this prevents any arguments from being unwrapped prematurely.

@hkaiser hkaiser closed this Apr 25, 2016

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.