Why am I Getting error in async, future in C++

727 views Asked by At

I am using std::async and std::future for the first time and am getting the error, Can somone help me rectify it.

The error:

** terminate called after throwing an instance of 'std::future_error'
what():  std::future_error: No associated state**

The code:

long long best_move(int depth, int start_score, char state[8][9],
        int state_score[8][8], long long alpha, long long beta){

    long long curr = 0;
    for(int i=0; i<8; ++i){
        for(int j=0; j<8; ++j){
            curr += state_score[i][j];
        }
    }
    if(depth == 5){
        //printf("Return value in the last node = %lld\n", current_score);
        return curr;
    }

    // TURN OF THE PLAYER THAT MAXIMIZES THE SCORE :
    int mid[] = {0, 7, 1, 6, 2, 5, 3, 4};
    if(depth % 2 == 0){
        //printf("Reached the maximizing player\n");
        long long ans = -1e8;
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isUpper(state[i][mid[j]]) && state_score[i][mid[j]]>0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], state);
                    if(possible_moves.size() == 0) continue;
                    int co = -1;
                    std::future<long long> fut[possible_moves.size()];
                    for(auto u : possible_moves){
                        co = co + 1;
                        int x = u.first, y = u.second;
                        long long removed_points = state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=8) state_score_copy[k][io] = state_score[k][io];
                                state_copy[k][io] = state[k][io];
                            }
                        }
                        long long new_score = curr - state_score[x][y];
                        if(depth >= 3 && new_score == start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);
                        fut[co] = std::async (std::launch::async, best_move, depth+1, start_score, state_copy, state_score_copy, alpha, beta);
                        //long long res = best_move(depth+1, start_score, state_copy, state_score_copy, alpha, beta);
                        //printf("%lld\n", res);
                    }
                    co = 0;
                    for(co = 0; co < possible_moves.size(); ++co){
                        long long res = fut[co].get();
                        ans = max(ans, res);
                        alpha = max(alpha, ans);
                        if(beta <= alpha) break;
                        if(depth == 0 && ans == res){
                            printf("got the answer = %lld\n", ans);
                            moveX = i;
                            moveY = mid[j];
                            toX = possible_moves[i].first;
                            toY = possible_moves[i].second;
                        }
                    }
                }
            }
        }
        return ans;
    }


    else{

        long long ans = +1e8;
        //printf("Reached the minimizing player\n");
        for(int i=0; i<8; ++i){
            for(int j=0; j<8; ++j){
                if(isLower(state[i][mid[j]]) && state_score[i][mid[j]]<0){
                    vector<pair<int, int>> possible_moves = get_moves(i, mid[j], state);
                    if(possible_moves.size() == 0) continue;
                    int co = -1;
                    std::future<long long> fut[possible_moves.size()];
                    for(auto u : possible_moves){
                        co = co + 1;
                        int x = u.first, y = u.second;
                        long long removed_points = state_score[x][y];
                        char state_copy[8][9];
                        int state_score_copy[8][8];
                        for(int k=0; k<8; ++k){
                            for(int io=0; io<9; ++io){
                                if(io!=9) state_score_copy[k][io] = state_score[k][io];
                                state_copy[k][io] = state[k][io];
                            }
                        }
                        long long new_score = curr - state_score[x][y];
                        if(depth >= 3 && new_score == start_score) continue;

                        state_copy[x][y] = state_copy[i][mid[j]];
                        state_copy[i][mid[j]] = '_';
                        state_score_copy[x][y] = state_score_copy[i][mid[j]];
                        state_score_copy[i][mid[j]] = 0;

                        //long long res = best_move(depth+1, state_copy, state_score_copy, alpha, beta);
                        fut[co] = std::async (std::launch::async, best_move, depth+1, start_score, state_copy, state_score_copy, alpha, beta);
                        //long long res = best_move(depth+1, start_score, state_copy, state_score_copy, alpha, beta);
                        //ans = min(ans, res);
                        //beta = min(res, beta);
                        //if(beta <= alpha) break;
                    }
                    co = 0;
                    for(co = 0; co < possible_moves.size(); ++co){
                        long long res = fut[co].get();
                        ans = min(ans, res);
                        beta = min(res, beta);
                        if(beta <= alpha) break;
                    }
                }
            }
        }
        return ans;

    }

}
1

There are 1 answers

0
Michaël Roy On

It looks like you are trying to get the value of an unitialized future.

This is due to this line of code in your inner loop:

if (depth >= 3 && new_score == start_score) continue; // skips call to async().

This line means there is no guarantee that fut[] will hold possible_moves.size() initialized futures.

To ensure you do not have uninitialized futures, you could store your futures in a vector.

As in

//...
std::vector<std::future<long long>> fut;
fut.reserve(possible_moves.size());

//...
fut.push_back(std::async(/* ... */));

//...
for (size_t i = 0; i < fut.size(); ++i)
{
    long long res = fut[i].get();
    ans = min(ans, res);
    beta = min(res, beta);
    if (beta <= alpha) break;  
 }