Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to move a struct with promise inside it?

Recently I have read a part of "Concurrency in action" book concerning parallel quicksort implementation. I tried to check the code mentioned in the book and received an error on this part:

struct listPart
{
    list<T> data;
    promise<list<T>> promise;
};
listPart newLowerPart;
...
parts.push(move(newLowerPart));

The compiler gives the error

std::promise::promise(const std::promise> &) : attempting to reference a deleted function.

The error is occured in generated copy constructor of listPart. I guess trying to move newLowerPart it tries to use deleted copy constructor of promise. I thought creating custom copy constructor would help, but even an attempt to move promise inside it gave me the same error. Could you help me to solve this problem? Thank you in advance

like image 726
D3migod Avatar asked Nov 16 '25 15:11

D3migod


2 Answers

Remember, that correct handling rvalues requires special treatment. So your container should provide at least two versions of push:

void push(const T& t); //'t' is coopied

and

void push(T&& t); //'t' is moved

Also, you should define move constructor for listPart and forbid copying:

Solution:

struct listPart
{
    list<T> data;
    promise<list<T>> promise;

    listPart(const listPart&) = delete;

    listPart(listPart&& source)
    : data(std::move(source.data))
    , promise(std::move(source.promise))
    {  }
};

I thought creating custom copy constructor would help

As I demonstrated, you shouldn't define copy constructor for listPart - it should either be deleted or (in case of pre-C++ 11) private with no implementation provided. That's because copying std::promise is not defined (its copy constructor is deleted), so copying instance of listPart is meaningless in this case.

like image 50
Mateusz Grzejek Avatar answered Nov 18 '25 07:11

Mateusz Grzejek


The problem is likely with your parts container implementation - it tries to copy the push parameter instead of moving it. Here is an example:

#include <list>
#include <future>

struct listPart
{
    std::list<int> data;
    std::promise<std::list<int>> p;
};
template<typename T>
class dummy_container{
T t_;
public:
    void push_back(const T& t){
        t_ = t;       
    }
    void move_back(const T& t){
        t_ = t;    
    }
    void move_back(T&& t){
        t_ = std::move(t);    
    }
};

int main() {
    dummy_container<listPart> dc;
    listPart lp;
    //dc.push_back(std::move(lp)); // won't compile, function only handles const references
    dc.move_back(std::move(lp)); // will compile, because it moves if possible
}
like image 43
hynner Avatar answered Nov 18 '25 06:11

hynner



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!