diff --git a/smp/src/islandModel.cpp b/smp/src/islandModel.cpp index 6d1f390f4..fa1c9a67c 100644 --- a/smp/src/islandModel.cpp +++ b/smp/src/islandModel.cpp @@ -27,49 +27,65 @@ ParadisEO WebSite : http://paradiseo.gforge.inria.fr Contact: paradiseo-help@lists.gforge.inria.fr */ +#include +#include + template paradiseo::smp::IslandModel::IslandModel(AbstractTopology& _topo) : - topo(_topo) + topo(_topo), + running(false) { } template void paradiseo::smp::IslandModel::add(AIsland& _island) { - islands.push_back(&_island); - islands.back()->setModel(this); + islands.push_back(std::pair*, bool>(&_island, false)); + islands.back().first->setModel(this); } template void paradiseo::smp::IslandModel::operator()() { + running = true; + std::vector threads(islands.size()); + // Preparing islands + for(auto it : islands) + it.second = true; + // Construct topology according to the number of islands topo.construct(islands.size()); // Create table - table = createTable(topo, islands); + table = createTable(); // Launching threads unsigned i = 0; for(auto it : islands) { - threads[i] = std::thread(&AIsland::operator(), it); + threads[i] = std::thread(&AIsland::operator(), it.first); i++; } - unsigned workingThread = islands.size(); - while(workingThread > 0) + // + std::function workingIslands = [this]() -> int + { + return (int)std::count_if(std::begin(islands), std::end(islands), + [](std::pair*, bool>& i) -> bool + { return i.second; } ); + }; + + while(workingIslands() > 0) { // Count working islands - workingThread = islands.size(); for(auto& it : islands) { // If an island is stopped we need to isolate its node in the topology - if(it->isStopped()) + if(it.second && it.first->isStopped()) { - workingThread--; - topo.isolateNode(table.getLeft()[it]); + it.second = false; + topo.isolateNode(table.getLeft()[it.first]); } } // Check sending @@ -82,7 +98,9 @@ void paradiseo::smp::IslandModel::operator()() thread.join(); for(auto& message : sentMessages) - message.join(); + message.join(); + + running = false; } template @@ -95,7 +113,18 @@ void paradiseo::smp::IslandModel::update(eoPop _data, AIsland* _i template void paradiseo::smp::IslandModel::setTopology(AbstractTopology& _topo) { + // If we change topo, we need to protect it + std::lock_guard lock(m); topo = _topo; + // If we change when the algorithm is running, we need to recontruct the topo + if(running) + { + topo.construct(islands.size()); + // If we change the topology during the algorithm, we need to isolate stopped islands + for(auto it : islands) + if(!it.second) + topo.isolateNode(table.getLeft()[it.first]); + } } template @@ -118,16 +147,21 @@ void paradiseo::smp::IslandModel::send(void) } template -Bimap*> paradiseo::smp::IslandModel::createTable(AbstractTopology& _topo, std::vector*>& _islands) +Bimap*> paradiseo::smp::IslandModel::createTable() { Bimap*> table; unsigned islandId = 0; for(auto it : islands) { - table.add(islandId, it); + table.add(islandId, it.first); islandId++; } return table; } +template +bool paradiseo::smp::IslandModel::isRunning() const +{ + return (bool)running; +} diff --git a/smp/src/islandModel.h b/smp/src/islandModel.h index 8aaaa9c40..d0f8f7f5c 100644 --- a/smp/src/islandModel.h +++ b/smp/src/islandModel.h @@ -80,6 +80,8 @@ public: */ void setTopology(AbstractTopology& _topo); + bool isRunning() const; + protected: /** @@ -87,14 +89,15 @@ protected: */ void send(void); - Bimap*> createTable(AbstractTopology& _topo, std::vector*>& _islands); + Bimap*> createTable(); std::queue,AIsland*>> listEmigrants; Bimap*> table; - std::vector*> islands; + std::vector*, bool>> islands; AbstractTopology& topo; std::vector sentMessages; std::mutex m; + std::atomic running; }; #include