mardi 2 avril 2019

std::shared_ptr not updating its count

I am trying to create a network of a custom class Tile inside another class Board which is storing a std::array<std::shared_ptr<Tile>, 34>. I am using std::shared_ptr<Tile> objects within class Tile to show which nodes are connected. However, when I initialise each of the 34 Tile objects, the not yet initialised objects included in the list do not get updated from nullptr to their own reference.

In Board.hpp:

#ifndef Board_hpp
#define Board_hpp

#include "PlayCard.hpp"

#include <memory>
#include <array>
#include <cstddef>
#include <functional>

// Defines a template for a member function array for a class C (physically C * in parameter list, and so can include void) of size N.
// Each function must return T (can be void), and have the same argument list Args (which cannot include void).

template <const std::size_t N, typename T = void, class C = void, class... Args>
using MemberFnArray = std::array<const std::function<T (C *, Args...)>, N>;

struct Tile;
template <const std::size_t N> using TileLink  = std::array<const std::shared_ptr<const Tile>, N>;
template <const std::size_t N> using TileArray = std::array<std::shared_ptr<const Tile>, N>;

struct Tile {
    std::unique_ptr<UnitCard> unit_card;
    std::unique_ptr<AgentCard> agent_card;
    enum OWNERSHIP { PLAYER_1, PLAYER_2, CONTESTED } territory;
    /* surrounding tiles */
    const std::size_t ID;
    const std::size_t num_adj;
    const TileLink<6> adjacent;
    Tile (OWNERSHIP own, std::size_t id, std::size_t n, const TileLink<6> & arr) : unit_card (nullptr), agent_card (nullptr), territory (own), ID (id), num_adj (n), adjacent (arr) { }
    ~Tile (void) = default;
};

class Board {
private:
    TileArray<34> tiles;
    void create_col_1_and_7 (void);
    void create_col_2 (void);
    void create_col_3 (void);
    void create_col_4 (void);
    void create_col_5 (void);
    void create_col_6 (void);
public:
    Board (void);
    ~Board (void) = default;
};

#endif /* Board_hpp */


In Board.cpp:

#include "Board.hpp"

#include <thread>


void Board :: create_col_1_and_7 (void) {
    /* Column 1 */
    tiles[0]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_2,   0, 3, TileLink<6>{ tiles[1],  tiles[4],  tiles[5],  nullptr,   nullptr,   nullptr   });
    tiles[1]  = std::make_shared<Tile> (Tile::OWNERSHIP::CONTESTED,  1, 4, TileLink<6>{ tiles[0],  tiles[2],  tiles[5],  tiles[6],  nullptr,   nullptr   });
    tiles[2]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_1,   2, 3, TileLink<6>{ tiles[1],  tiles[6],  tiles[7],  nullptr,   nullptr,   nullptr   });
    /* Column 7 */
    tiles[31] = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_2,  31, 3, TileLink<6>{ tiles[26], tiles[27], tiles[32], nullptr,   nullptr,   nullptr   });
    tiles[32] = std::make_shared<Tile> (Tile::OWNERSHIP::CONTESTED, 32, 4, TileLink<6>{ tiles[27], tiles[28], tiles[31], tiles[33], nullptr,   nullptr   });
    tiles[33] = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_1,  33, 3, TileLink<6>{ tiles[28], tiles[29], tiles[32], nullptr,   nullptr,   nullptr   });
}

void Board :: create_col_2 (void) {
    /* Column 2 */
    tiles[3]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_2,   3, 2, TileLink<6>{ tiles[4],  tiles[9],  nullptr,   nullptr,   nullptr,   nullptr   });
    tiles[4]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_2,   4, 5, TileLink<6>{ tiles[0],  tiles[3],  tiles[5],  tiles[9],  tiles[10], nullptr   });
    tiles[5]  = std::make_shared<Tile> (Tile::OWNERSHIP::CONTESTED,  5, 6, TileLink<6>{ tiles[0],  tiles[1],  tiles[4],  tiles[6],  tiles[10], tiles[11] });
    tiles[6]  = std::make_shared<Tile> (Tile::OWNERSHIP::CONTESTED,  6, 6, TileLink<6>{ tiles[1],  tiles[2],  tiles[5],  tiles[7],  tiles[11], tiles[12] });
    tiles[7]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_1,   7, 5, TileLink<6>{ tiles[2],  tiles[6],  tiles[8],  tiles[12], tiles[13], nullptr   });
    tiles[8]  = std::make_shared<Tile> (Tile::OWNERSHIP::PLAYER_1,   8, 2, TileLink<6>{ tiles[7],  tiles[13], nullptr,   nullptr,   nullptr,   nullptr   });
}

...


void create_col_2 (void) is almost identical to void create_col_3 (void), 4, 5, and 6.

Board :: Board (void) {
    const MemberFnArray<6, void, Board> fnArray = {
        &Board :: create_col_1_and_7,
        &Board :: create_col_2,
        &Board :: create_col_3,
        &Board :: create_col_4,
        &Board :: create_col_5,
        &Board :: create_col_6
    };
    std::thread threads[6];
    for (std::size_t i = 0; i < 6; ++i) threads[i] = std::thread (fnArray[i], this);
    for (auto & th : threads) th.join ();

}

The std::array I am passing to the Tile constructor does not change. How would I get it to change?

Any help would be greatly appreciated. Sorry for making the question so long, I didn't really know how to make this a smaller example.

Aucun commentaire:

Enregistrer un commentaire