On Tue, 15 Nov 2016 07:18:13 -0600
  "Hartmut Kaiser" <[email protected]> wrote:
> 
>> in our current HPX driven project we encounter the
>> following runtime error:
>> 
>>      data has already been set for this future:
>> HPX(promise_already_satisfied)
>> 
>> The relevant code is as follows:
>> 
>> void Image::compose ( const Image& other);
>> hpx::future<Image> Container::render();
>> 
>> [...]
>> 
>>   std::vector<hpx::future<Image>> imageFutures;
>>   for (int i = 0; i < containers.size(); ++i)
>>         imageFutures.push_back(containers[i].render());
>> 
>>    Image image;
>>    hpx::lcos::local::spinlock mtx;
>> 
>>    hpx::lcos::wait_each([&](hpx::future<Image> img)
>>    {
>>        std::lock_guard<hpx::lcos::local::spinlock>
>> lk(mtx);
>>        image.compose(img.get());
>>    }, imageFutures);
>> 
>>    return image;
>> 
>> The runtime error does not occur, when the line
>> "image.compose(img.get());" is substituted with just
>> "img.get();"
>> Note the argument of compose is a const reference.
>> 
>> So what exactly does the error message mean? At no point
>> are we explicitly setting or modifying the data of a
>> future.
>> The error only occurs when actually using the future,
>> getting the future without further usage is safe.
>> 
>> The Container Class is a client side representation of a
>> Container Component, so the render methods could run in
>> parallel and possibly on remote machines.
>> The error only occurs if the vector imageFutures has 
>>more
>> than one element, so only if there are multiple futures 
>>to
>> wait on / multiple instances of render running.
>> 
>> What can cause this error in general? How to go about
>> debugging it and what could be the problem with our
>> implementation.
> 
> This error is thrown whenever a promise (the other end 
>of a future) has its
> value set more than once. I.e. essentially something 
>like:
> 
> void set_value(promise<int> p)
> {
>    p.set_value(42);
>    p.set_value(42);   // <-- here
> }
> 
> void foo()
> {
>    promise<int> p;
>    future<int> f = p.get_promise();
>    async(&set_value, std::move(p));
>    f.get();
> }
> 
> or similar.
> 
>>From what I see from your code, the only explanation 
>>would be a bug in
> wait_each() which manifests itself under certain timings 
>only. Could you
> create a small reproducing use case for use to debug 
>things?
> 
> Thanks!
> Regards Hartmut
> ---------------
> http://boost-spirit.com
> http://stellar.cct.lsu.edu
> 
> 
> 
> _______________________________________________
> hpx-users mailing list
> [email protected]
> https://mail.cct.lsu.edu/mailman/listinfo/hpx-users


 From what I've learned in the meantime, the bug seems not 
to be in wait_each.

While trying to narrow the problem down to your requested 
minimal example I observed, that the vector of futures 
"containerImageFutures" itsels seems to be corrupt.

Consider the following Code:

std::vector<hpx::shared_future<Image>> 
containerImageFutures;

for (int i = 0; i < containers.size(); ++i)
      containerImageFutures.push_back(containers[i].render());

LogDebug() << "Size: " << containerImageFutures.size();

int i = 0;
for ( const hpx::shared_future<Image>& future : 
containerImageFutures) {
      try {
            future.get();
            LogDebug() << "ForEach Loop verifies existence 
of " << i << " while obvserving length " << 
containerImageFutures.size();
             i++;
      }
             catch (const std::out_of_range& oor) {
                    std::cerr << "Out of Range error: " << 
oor.what() << '\n';
             }
      }

LogDebug() << "Size: " << containerImageFutures.size();

return;

It produces the output:

[15:54:50] Size: 2
[15:54:56] ForEach Loop verifies existence of 0 while 
obvserving length 2
Out of Range error: vector::_M_range_check: __n (which is 
0) >= this->size() (which is 0)
[15:54:56] Size: 2

When deleting the line "future.get()" from the loop and 
instead using 
"hpx::lcos::wait_all(containerImageFutures);" before 
calling the loop the output is:
[15:58:55] Size: 2
[15:58:55] ForEach Loop verifies existence of 0 while 
obvserving length 2
[15:58:55] ForEach Loop verifies existence of 1 while 
obvserving length 2
[15:58:55] Size: 2

This leads to the conclusion, that the second element of 
the vector is only valid and reachable if .get() was not 
called on the first element.
A vector that is distorted in such a way would of course 
omit invalid behavior for a wait_each command working on 
it.
However it is unclear how this underlying error is 
created.

For your information. The HPX version we are working with 
was compiled from the master branch, june this year. We 
will try to update and see if the error changed somehow.
Also note, that for testing we’re running two localities 
locally using mpirun -np 2 program.

Best Regards,

Kilian Werner
_______________________________________________
hpx-users mailing list
[email protected]
https://mail.cct.lsu.edu/mailman/listinfo/hpx-users

Reply via email to