From b9d8e59bbf727fcc1a073bbf27e5d1703b9490ef Mon Sep 17 00:00:00 2001 From: kwolekr Date: Wed, 13 Feb 2013 22:43:15 -0500 Subject: Add emerge.cpp, initial EmergeThread changes - Neatly placed all emerge related code into a new file, emerge.cpp - Greatly cleaned up the code in EmergeThread::Thread() - Reworked Emerge queue. Now an actual std::queue of v3s16 block positions - Removed the completely unnecessary map of peer ids requesting blocks --- src/emerge.cpp | 677 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 677 insertions(+) create mode 100644 src/emerge.cpp (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp new file mode 100644 index 000000000..728ea7196 --- /dev/null +++ b/src/emerge.cpp @@ -0,0 +1,677 @@ +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + + +#include "server.h" +#include +#include +#include "clientserver.h" +#include "map.h" +#include "jmutexautolock.h" +#include "main.h" +#include "constants.h" +#include "voxel.h" +#include "config.h" +#include "mapblock.h" +#include "serverobject.h" +#include "settings.h" +#include "script.h" +#include "scriptapi.h" +#include "profiler.h" +#include "log.h" +#include "nodedef.h" +#include "biome.h" +#include "emerge.h" +#include "mapgen_v6.h" + + +EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { + //register built-in mapgens + registerMapgen("v6", new MapgenFactoryV6()); + + this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef); + this->params = NULL; + this->mapgen = NULL; + + queuemutex.Init(); + emergethread = new EmergeThread((Server *)gamedef); +} + + +EmergeManager::~EmergeManager() { + emergethread->setRun(false); + emergethread->stop(); + + delete emergethread; + delete biomedef; + delete mapgen; + delete params; +} + + +void EmergeManager::initMapgens(MapgenParams *mgparams) { + if (mapgen) + return; + + this->params = mgparams; + this->mapgen = getMapgen(); //only one mapgen for now! +} + + +Mapgen *EmergeManager::getMapgen() { + if (!mapgen) { + mapgen = createMapgen(params->mg_name, 0, params, this); + if (!mapgen) { + infostream << "EmergeManager: falling back to mapgen v6" << std::endl; + delete params; + params = createMapgenParams("v6"); + mapgen = createMapgen("v6", 0, params, this); + } + } + return mapgen; +} + + +bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { ///return false if adding failed, or queue full! + u8 flags = 0; + + if (allow_generate) + flags |= BLOCK_EMERGE_ALLOWGEN; + + //TODO: + // add logic to select which emergethread to add it to + // - one with the least queue contents? + // - if a queue is too full, move onto another one + // - use the peer id sometime + + { + JMutexAutoLock queuelock(queuemutex); + + std::map::const_iterator iter = blocks_enqueued.find(p); + if (iter != blocks_enqueued.end()) { + flags |= iter->second; + blocks_enqueued[p] = flags; + return true; + } + + blocks_enqueued.insert(std::make_pair(p, flags)); + emergethread->blockqueue.push(p); + } + emergethread->qevent.signal(); + + return true; +} + + +bool EmergeManager::popBlockEmerge(v3s16 *pos, u8 *flags) { + JMutexAutoLock queuelock(queuemutex); + + if (emergethread->blockqueue.empty()) + return false; + v3s16 p = emergethread->blockqueue.front(); + emergethread->blockqueue.pop(); + + *pos = p; + + std::map::iterator iter = blocks_enqueued.find(p); + if (iter == blocks_enqueued.end()) //uh oh, this isn't right!!!!!!!!!!!!!!!!!! + return false; + + *flags = iter->second; + blocks_enqueued.erase(iter); + + return true; +} + + +int EmergeManager::getGroundLevelAtPoint(v2s16 p) { + if (!mapgen) + return 0; + return mapgen->getGroundLevelAtPoint(p); +} + + +bool EmergeManager::isBlockUnderground(v3s16 blockpos) { + /* + v2s16 p = v2s16((blockpos.X * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2, + (blockpos.Y * MAP_BLOCKSIZE) + MAP_BLOCKSIZE / 2); + int ground_level = getGroundLevelAtPoint(p); + return blockpos.Y * (MAP_BLOCKSIZE + 1) <= min(water_level, ground_level); + */ + + //yuck, but then again, should i bother being accurate? + //the height of the nodes in a single block is quite variable + return blockpos.Y * (MAP_BLOCKSIZE + 1) <= params->water_level; +} + + +u32 EmergeManager::getBlockSeed(v3s16 p) { + return (u32)(params->seed & 0xFFFFFFFF) + + p.Z * 38134234 + + p.Y * 42123 + + p.Y * 23; +} + + +Mapgen *EmergeManager::createMapgen(std::string mgname, int mgid, + MapgenParams *mgparams, EmergeManager *emerge) { + std::map::const_iterator iter = mglist.find(mgname); + if (iter == mglist.end()) { + errorstream << "EmergeManager; mapgen " << mgname << + " not registered" << std::endl; + return NULL; + } + + MapgenFactory *mgfactory = iter->second; + return mgfactory->createMapgen(mgid, mgparams, emerge); +} + + +MapgenParams *EmergeManager::createMapgenParams(std::string mgname) { + std::map::const_iterator iter = mglist.find(mgname); + if (iter == mglist.end()) { + errorstream << "EmergeManager: mapgen " << mgname << + " not registered" << std::endl; + return NULL; + } + + MapgenFactory *mgfactory = iter->second; + return mgfactory->createMapgenParams(); +} + + +MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { + std::string mg_name = settings->get("mg_name"); + MapgenParams *mgparams = createMapgenParams(mg_name); + + mgparams->mg_name = mg_name; + mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); + mgparams->water_level = settings->getS16("water_level"); + mgparams->chunksize = settings->getS16("chunksize"); + mgparams->flags = settings->getS32("mg_flags"); + + if (!mgparams->readParams(settings)) { + delete mgparams; + return NULL; + } + return mgparams; +} + + +void EmergeManager::setParamsToSettings(Settings *settings) { + settings->set("mg_name", params->mg_name); + settings->setU64("seed", params->seed); + settings->setS16("water_level", params->water_level); + settings->setS16("chunksize", params->chunksize); + settings->setFlagStr("mg_flags", params->flags, flagdesc_mapgen); + + params->writeParams(settings); +} + + +bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { + mglist.insert(std::make_pair(mgname, mgfactory)); + infostream << "EmergeManager: registered mapgen " << mgname << std::endl; +} + + + +class MapEditEventIgnorer +{ +public: + MapEditEventIgnorer(bool *flag): + m_flag(flag) + { + if(*m_flag == false) + *m_flag = true; + else + m_flag = NULL; + } + + ~MapEditEventIgnorer() + { + if(m_flag) + { + assert(*m_flag); + *m_flag = false; + } + } + +private: + bool *m_flag; +}; + +class MapEditEventAreaIgnorer +{ +public: + MapEditEventAreaIgnorer(VoxelArea *ignorevariable, const VoxelArea &a): + m_ignorevariable(ignorevariable) + { + if(m_ignorevariable->getVolume() == 0) + *m_ignorevariable = a; + else + m_ignorevariable = NULL; + } + + ~MapEditEventAreaIgnorer() + { + if(m_ignorevariable) + { + assert(m_ignorevariable->getVolume() != 0); + *m_ignorevariable = VoxelArea(); + } + } + +private: + VoxelArea *m_ignorevariable; +}; + + +#if 1 + +#define EMERGE_DBG_OUT(x) \ + { if (enable_mapgen_debug_info) \ + infostream << "EmergeThread: " x << std::endl; } + +bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, + BlockMakeData *data, bool allow_gen) { + v2s16 p2d(p.X, p.Z); + //envlock: usually takes <=1ms, sometimes 90ms or ~400ms to acquire + JMutexAutoLock envlock(m_server->m_env_mutex); + + // Load sector if it isn't loaded + if (map->getSectorNoGenerateNoEx(p2d) == NULL) + map->loadSectorMeta(p2d); + + // Attempt to load block + MapBlock *block = map->getBlockNoCreateNoEx(p); + if (!block || block->isDummy() || !block->isGenerated()) { + EMERGE_DBG_OUT("not in memory, attempting to load from disk"); + block = map->loadBlock(p); + } + + // If could not load and allowed to generate, + // start generation inside this same envlock + if (allow_gen && (block == NULL || !block->isGenerated())) { + EMERGE_DBG_OUT("generating"); + map->initBlockMake(data, p); + return true; + } + + *b = block; + return false; +} + + +void *EmergeThread::Thread() { + ThreadStarted(); + log_register_thread("EmergeThread"); + DSTACK(__FUNCTION_NAME); + BEGIN_DEBUG_EXCEPTION_HANDLER + + v3s16 last_tried_pos(-32768,-32768,-32768); // For error output + v3s16 p; + u8 flags; + + map = (ServerMap *)&(m_server->m_env->getMap()); + emerge = m_server->m_emerge; + mapgen = emerge->getMapgen(); + + while (getRun()) + try { + while (!emerge->popBlockEmerge(&p, &flags)) + qevent.wait(); + + last_tried_pos = p; + if (blockpos_over_limit(p)) + continue; + + bool allow_generate = flags & BLOCK_EMERGE_ALLOWGEN; + EMERGE_DBG_OUT("p=" PP(p) " allow_generate=" << allow_generate); + + /* + Try to fetch block from memory or disk. + If not found and asked to generate, initialize generator. + */ + BlockMakeData data; + MapBlock *block = NULL; + core::map modified_blocks; + + if (getBlockOrStartGen(p, &block, &data, allow_generate)) { + { + ScopeProfiler sp(g_profiler, "EmergeThread: Mapgen::makeChunk", SPT_AVG); + TimeTaker t("mapgen::make_block()"); + + mapgen->makeChunk(&data); + + if (enable_mapgen_debug_info == false) + t.stop(true); // Hide output + } + + { + //envlock: usually 0ms, but can take either 30 or 400ms to acquire + JMutexAutoLock envlock(m_server->m_env_mutex); + ScopeProfiler sp(g_profiler, "EmergeThread: after " + "mapgen::make_block (envlock)", SPT_AVG); + + map->finishBlockMake(&data, modified_blocks); + + block = map->getBlockNoCreateNoEx(p); + if (block) { + /* + Do some post-generate stuff + */ + v3s16 minp = data.blockpos_min * MAP_BLOCKSIZE; + v3s16 maxp = data.blockpos_max * MAP_BLOCKSIZE + + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); + + // Ignore map edit events, they will not need to be sent + // to anybody because the block hasn't been sent to anybody + MapEditEventAreaIgnorer + ign(&m_server->m_ignore_map_edit_events_area, + VoxelArea(minp, maxp)); + { // takes about 90ms with -O1 on an e3-1230v2 + scriptapi_environment_on_generated(m_server->m_lua, + minp, maxp, emerge->getBlockSeed(minp)); + } + + EMERGE_DBG_OUT("ended up with: " << analyze_block(block)); + + m_server->m_env->activateBlock(block, 0); + } + } + } + + /* + Set sent status of modified blocks on clients + */ + + // NOTE: Server's clients are also behind the connection mutex + //conlock: consistently takes 30-40ms to acquire + JMutexAutoLock lock(m_server->m_con_mutex); + // Add the originally fetched block to the modified list + if (block) + modified_blocks.insert(p, block); + + // Set the modified blocks unsent for all the clients + for (core::map::Iterator + i = m_server->m_clients.getIterator(); + i.atEnd() == false; i++) { + RemoteClient *client = i.getNode()->getValue(); + if (modified_blocks.size() > 0) { + // Remove block from sent history + client->SetBlocksNotSent(modified_blocks); + } + } + } + catch (VersionMismatchException &e) { + std::ostringstream err; + err << "World data version mismatch in MapBlock "<setAsyncFatalError(err.str()); + } + catch (SerializationError &e) { + std::ostringstream err; + err << "Invalid data in MapBlock "<setAsyncFatalError(err.str()); + } + + END_DEBUG_EXCEPTION_HANDLER(errorstream) + log_deregister_thread(); + return NULL; +} + +#else + +void *EmergeThread::Thread() { + ThreadStarted(); + log_register_thread("EmergeThread"); + DSTACK(__FUNCTION_NAME); + BEGIN_DEBUG_EXCEPTION_HANDLER + + bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); + + v3s16 last_tried_pos(-32768,-32768,-32768); // For error output + ServerMap &map = ((ServerMap&)m_server->m_env->getMap()); + EmergeManager *emerge = m_server->m_emerge; + Mapgen *mapgen = emerge->getMapgen(); + + while(getRun()) + try { + QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop(); + if(qptr == NULL) + break; + SharedPtr q(qptr); + + v3s16 &p = q->pos; + v2s16 p2d(p.X,p.Z); + + last_tried_pos = p; + + /* + Do not generate over-limit + */ + if (blockpos_over_limit(p)) + continue; + + //infostream<<"EmergeThread::Thread(): running"<::Iterator i; + for (i=q->s.getIterator(); !i.atEnd(); i++) { + u8 flags = i.getNode()->getValue(); + if (!(flags & BLOCK_EMERGE_FLAG_FROMDISK)) { + only_from_disk = false; + break; + } + } + } + + if (enable_mapgen_debug_info) + infostream<<"EmergeThread: p=" + <<"("<isGenerated() == false)){ + if(enable_mapgen_debug_info) + infostream<<"EmergeThread: generating"<makeChunk(&data); + + if (enable_mapgen_debug_info == false) + t.stop(true); // Hide output + } + + do{ // enable break + // Lock environment again to access the map + JMutexAutoLock envlock(m_server->m_env_mutex); + + ScopeProfiler sp(g_profiler, "EmergeThread: after " + "mapgen::make_block (envlock)", SPT_AVG); + + // Blit data back on map, update lighting, add mobs and + // whatever this does + map.finishBlockMake(&data, modified_blocks); + + // Get central block + block = map.getBlockNoCreateNoEx(p); + + // If block doesn't exist, don't try doing anything with it + // This happens if the block is not in generation boundaries + if(!block) + break; + + /* + Do some post-generate stuff + */ + v3s16 minp = data.blockpos_min * MAP_BLOCKSIZE; + v3s16 maxp = data.blockpos_max * MAP_BLOCKSIZE + + v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); + + /* + Ignore map edit events, they will not need to be + sent to anybody because the block hasn't been sent + to anybody + */ + MapEditEventAreaIgnorer ign( + &m_server->m_ignore_map_edit_events_area, + VoxelArea(minp, maxp)); + { + TimeTaker timer("on_generated"); + scriptapi_environment_on_generated(m_server->m_lua, + minp, maxp, emerge->getBlockSeed(minp)); + //int t = timer.stop(true); + //dstream<<"on_generated took "<m_env->activateBlock(block, 0); + }while(false); + } + + if(block == NULL) + got_block = false; + + /* + Set sent status of modified blocks on clients + */ + + // NOTE: Server's clients are also behind the connection mutex + JMutexAutoLock lock(m_server->m_con_mutex); + + /* + Add the originally fetched block to the modified list + */ + if(got_block) + modified_blocks.insert(p, block); + + /* + Set the modified blocks unsent for all the clients + */ + for(core::map::Iterator + i = m_server->m_clients.getIterator(); + i.atEnd() == false; i++) { + RemoteClient *client = i.getNode()->getValue(); + if(modified_blocks.size() > 0) { + // Remove block from sent history + client->SetBlocksNotSent(modified_blocks); + } + } + + +niters++; + } + catch (VersionMismatchException &e) { + std::ostringstream err; + err << "World data version mismatch in MapBlock "<setAsyncFatalError(err.str()); + } + catch (SerializationError &e) { + std::ostringstream err; + err << "Invalid data in MapBlock "<setAsyncFatalError(err.str()); + } +printf("emergethread iterated %d times\n", niters); + END_DEBUG_EXCEPTION_HANDLER(errorstream) + log_deregister_thread(); + return NULL; +} + +#endif -- cgit v1.2.3 From 3b7a445cd78c6b5ab301b5bf44e1ec54a00427f1 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Thu, 14 Feb 2013 18:32:56 -0500 Subject: Add global and per-peer queue limits --- src/emerge.cpp | 43 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 9 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index 728ea7196..82867be50 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -88,7 +88,10 @@ Mapgen *EmergeManager::getMapgen() { } -bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { ///return false if adding failed, or queue full! +bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate) { + std::map::const_iterator iter; + BlockEmergeData *bedata; + u16 count; u8 flags = 0; if (allow_generate) @@ -103,14 +106,30 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate { JMutexAutoLock queuelock(queuemutex); - std::map::const_iterator iter = blocks_enqueued.find(p); + count = blocks_enqueued.size(); + u16 queuelimit_total = 256; + if (count >= queuelimit_total) + return false; + + count = peer_queue_count[peer_id]; + u16 queuelimit_peer = allow_generate ? 1 : 5; + if (count >= queuelimit_peer) + return false; + + iter = blocks_enqueued.find(p); if (iter != blocks_enqueued.end()) { - flags |= iter->second; - blocks_enqueued[p] = flags; + bedata = iter->second; + bedata->flags |= flags; return true; } + + bedata = new BlockEmergeData; + bedata->flags = flags; + bedata->peer_requested = peer_id; + blocks_enqueued.insert(std::make_pair(p, bedata)); + + peer_queue_count[peer_id] = count + 1; - blocks_enqueued.insert(std::make_pair(p, flags)); emergethread->blockqueue.push(p); } emergethread->qevent.signal(); @@ -120,6 +139,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate bool EmergeManager::popBlockEmerge(v3s16 *pos, u8 *flags) { + std::map::iterator iter; JMutexAutoLock queuelock(queuemutex); if (emergethread->blockqueue.empty()) @@ -128,12 +148,17 @@ bool EmergeManager::popBlockEmerge(v3s16 *pos, u8 *flags) { emergethread->blockqueue.pop(); *pos = p; + + iter = blocks_enqueued.find(p); + if (iter == blocks_enqueued.end()) + return false; //uh oh, queue and map out of sync!! - std::map::iterator iter = blocks_enqueued.find(p); - if (iter == blocks_enqueued.end()) //uh oh, this isn't right!!!!!!!!!!!!!!!!!! - return false; + BlockEmergeData *bedata = iter->second; + *flags = bedata->flags; + + peer_queue_count[bedata->peer_requested]--; - *flags = iter->second; + delete bedata; blocks_enqueued.erase(iter); return true; -- cgit v1.2.3 From 206ec36c8e50a017636a70345b95f79feffb2446 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Thu, 14 Feb 2013 19:22:43 -0500 Subject: Fix EmergeThread hang on exit --- src/emerge.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index 82867be50..e2b9e5a6c 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -56,6 +56,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { EmergeManager::~EmergeManager() { emergethread->setRun(false); + emergethread->qevent.signal(); emergethread->stop(); delete emergethread; @@ -360,8 +361,11 @@ void *EmergeThread::Thread() { while (getRun()) try { - while (!emerge->popBlockEmerge(&p, &flags)) + while (!emerge->popBlockEmerge(&p, &flags)) { qevent.wait(); + if (!getRun()) + goto exit_emerge_loop; + } last_tried_pos = p; if (blockpos_over_limit(p)) @@ -393,7 +397,7 @@ void *EmergeThread::Thread() { //envlock: usually 0ms, but can take either 30 or 400ms to acquire JMutexAutoLock envlock(m_server->m_env_mutex); ScopeProfiler sp(g_profiler, "EmergeThread: after " - "mapgen::make_block (envlock)", SPT_AVG); + "Mapgen::makeChunk (envlock)", SPT_AVG); map->finishBlockMake(&data, modified_blocks); @@ -465,6 +469,7 @@ void *EmergeThread::Thread() { } END_DEBUG_EXCEPTION_HANDLER(errorstream) +exit_emerge_loop: log_deregister_thread(); return NULL; } -- cgit v1.2.3 From 76217939e05bdd8d06fa7113902a74b02deeb915 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Thu, 14 Feb 2013 20:36:58 -0500 Subject: Add emerge queue limit configuration --- src/emerge.cpp | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index e2b9e5a6c..b785c8688 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -49,6 +49,10 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { this->params = NULL; this->mapgen = NULL; + qlimit_total = g_settings->getU16("emergequeue_limit_total"); + qlimit_diskonly = g_settings->getU16("emergequeue_limit_diskonly"); + qlimit_generate = g_settings->getU16("emergequeue_limit_generate"); + queuemutex.Init(); emergethread = new EmergeThread((Server *)gamedef); } @@ -98,23 +102,16 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate if (allow_generate) flags |= BLOCK_EMERGE_ALLOWGEN; - //TODO: - // add logic to select which emergethread to add it to - // - one with the least queue contents? - // - if a queue is too full, move onto another one - // - use the peer id sometime - { JMutexAutoLock queuelock(queuemutex); count = blocks_enqueued.size(); - u16 queuelimit_total = 256; - if (count >= queuelimit_total) + if (count >= qlimit_total) return false; count = peer_queue_count[peer_id]; - u16 queuelimit_peer = allow_generate ? 1 : 5; - if (count >= queuelimit_peer) + u16 qlimit_peer = allow_generate ? qlimit_generate : qlimit_diskonly; + if (count >= qlimit_peer) return false; iter = blocks_enqueued.find(p); -- cgit v1.2.3 From 5ec5b1cbd64a22e628be2cf03391883c44074811 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 17 Feb 2013 01:47:49 -0500 Subject: Add multi-Emerge thread support --- src/emerge.cpp | 99 ++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 61 insertions(+), 38 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index b785c8688..ee6650f9c 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -47,49 +47,56 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef); this->params = NULL; - this->mapgen = NULL; qlimit_total = g_settings->getU16("emergequeue_limit_total"); qlimit_diskonly = g_settings->getU16("emergequeue_limit_diskonly"); qlimit_generate = g_settings->getU16("emergequeue_limit_generate"); queuemutex.Init(); - emergethread = new EmergeThread((Server *)gamedef); + int nthreads = g_settings->get("num_emerge_threads").empty() ? + porting::getNumberOfProcessors() : + g_settings->getU16("num_emerge_threads"); + if (nthreads < 1) + nthreads = 1; + + for (int i = 0; i != nthreads; i++) + emergethread.push_back(new EmergeThread((Server *)gamedef, i)); + + infostream << "EmergeManager: using " << nthreads << " threads" << std::endl; } EmergeManager::~EmergeManager() { - emergethread->setRun(false); - emergethread->qevent.signal(); - emergethread->stop(); + for (int i = 0; i != emergethread.size(); i++) { + emergethread[i]->setRun(false); + emergethread[i]->qevent.signal(); + emergethread[i]->stop(); + delete emergethread[i]; + delete mapgen[i]; + } - delete emergethread; delete biomedef; - delete mapgen; delete params; } void EmergeManager::initMapgens(MapgenParams *mgparams) { - if (mapgen) + Mapgen *mg; + + if (mapgen.size()) return; this->params = mgparams; - this->mapgen = getMapgen(); //only one mapgen for now! -} - - -Mapgen *EmergeManager::getMapgen() { - if (!mapgen) { - mapgen = createMapgen(params->mg_name, 0, params, this); - if (!mapgen) { + for (int i = 0; i != emergethread.size(); i++) { + mg = createMapgen(params->mg_name, 0, params); + if (!mg) { infostream << "EmergeManager: falling back to mapgen v6" << std::endl; delete params; params = createMapgenParams("v6"); - mapgen = createMapgen("v6", 0, params, this); + mg = createMapgen("v6", 0, params); } + mapgen.push_back(mg); } - return mapgen; } @@ -98,6 +105,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate BlockEmergeData *bedata; u16 count; u8 flags = 0; + int idx = 0; if (allow_generate) flags |= BLOCK_EMERGE_ALLOWGEN; @@ -128,45 +136,58 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate peer_queue_count[peer_id] = count + 1; - emergethread->blockqueue.push(p); + int lowestitems = emergethread[0]->blockqueue.size(); + for (int i = 1; i != emergethread.size(); i++) { + int nitems = emergethread[i]->blockqueue.size(); + if (nitems < lowestitems) { + idx = i; + lowestitems = nitems; + } + } + + emergethread[idx]->blockqueue.push(p); } - emergethread->qevent.signal(); + emergethread[idx]->qevent.signal(); return true; } -bool EmergeManager::popBlockEmerge(v3s16 *pos, u8 *flags) { +bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { std::map::iterator iter; - JMutexAutoLock queuelock(queuemutex); + JMutexAutoLock queuelock(emerge->queuemutex); - if (emergethread->blockqueue.empty()) + if (blockqueue.empty()) return false; - v3s16 p = emergethread->blockqueue.front(); - emergethread->blockqueue.pop(); + v3s16 p = blockqueue.front(); + blockqueue.pop(); *pos = p; - iter = blocks_enqueued.find(p); - if (iter == blocks_enqueued.end()) + iter = emerge->blocks_enqueued.find(p); + if (iter == emerge->blocks_enqueued.end()) return false; //uh oh, queue and map out of sync!! BlockEmergeData *bedata = iter->second; *flags = bedata->flags; - peer_queue_count[bedata->peer_requested]--; + emerge->peer_queue_count[bedata->peer_requested]--; delete bedata; - blocks_enqueued.erase(iter); + emerge->blocks_enqueued.erase(iter); return true; } int EmergeManager::getGroundLevelAtPoint(v2s16 p) { - if (!mapgen) + if (!mapgen[0]) { + errorstream << "EmergeManager: getGroundLevelAtPoint() called" + " before mapgen initialized" << std::endl; return 0; - return mapgen->getGroundLevelAtPoint(p); + } + + return mapgen[0]->getGroundLevelAtPoint(p); } @@ -193,8 +214,9 @@ u32 EmergeManager::getBlockSeed(v3s16 p) { Mapgen *EmergeManager::createMapgen(std::string mgname, int mgid, - MapgenParams *mgparams, EmergeManager *emerge) { - std::map::const_iterator iter = mglist.find(mgname); + MapgenParams *mgparams) { + std::map::const_iterator iter; + iter = mglist.find(mgname); if (iter == mglist.end()) { errorstream << "EmergeManager; mapgen " << mgname << " not registered" << std::endl; @@ -202,12 +224,13 @@ Mapgen *EmergeManager::createMapgen(std::string mgname, int mgid, } MapgenFactory *mgfactory = iter->second; - return mgfactory->createMapgen(mgid, mgparams, emerge); + return mgfactory->createMapgen(mgid, mgparams, this); } MapgenParams *EmergeManager::createMapgenParams(std::string mgname) { - std::map::const_iterator iter = mglist.find(mgname); + std::map::const_iterator iter; + iter = mglist.find(mgname); if (iter == mglist.end()) { errorstream << "EmergeManager: mapgen " << mgname << " not registered" << std::endl; @@ -227,7 +250,7 @@ MapgenParams *EmergeManager::getParamsFromSettings(Settings *settings) { mgparams->seed = settings->getU64(settings == g_settings ? "fixed_map_seed" : "seed"); mgparams->water_level = settings->getS16("water_level"); mgparams->chunksize = settings->getS16("chunksize"); - mgparams->flags = settings->getS32("mg_flags"); + mgparams->flags = settings->getFlagStr("mg_flags", flagdesc_mapgen); if (!mgparams->readParams(settings)) { delete mgparams; @@ -354,11 +377,11 @@ void *EmergeThread::Thread() { map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; - mapgen = emerge->getMapgen(); + mapgen = emerge->mapgen[id]; //emerge->getMapgen(); while (getRun()) try { - while (!emerge->popBlockEmerge(&p, &flags)) { + while (!popBlockEmerge(&p, &flags)) { qevent.wait(); if (!getRun()) goto exit_emerge_loop; -- cgit v1.2.3 From 67c59645ecd76cbf7a8186d0850ab5950e9ea22a Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sun, 17 Feb 2013 02:46:08 -0500 Subject: Misc. cleanup and minor fixes --- src/emerge.cpp | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index ee6650f9c..ac654f368 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -48,6 +48,8 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { this->biomedef = bdef ? bdef : new BiomeDefManager(gamedef); this->params = NULL; + mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); + qlimit_total = g_settings->getU16("emergequeue_limit_total"); qlimit_diskonly = g_settings->getU16("emergequeue_limit_diskonly"); qlimit_generate = g_settings->getU16("emergequeue_limit_generate"); @@ -209,7 +211,7 @@ u32 EmergeManager::getBlockSeed(v3s16 p) { return (u32)(params->seed & 0xFFFFFFFF) + p.Z * 38134234 + p.Y * 42123 + - p.Y * 23; + p.X * 23; } @@ -331,10 +333,6 @@ private: #if 1 -#define EMERGE_DBG_OUT(x) \ - { if (enable_mapgen_debug_info) \ - infostream << "EmergeThread: " x << std::endl; } - bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { v2s16 p2d(p.X, p.Z); @@ -356,8 +354,8 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, // start generation inside this same envlock if (allow_gen && (block == NULL || !block->isGenerated())) { EMERGE_DBG_OUT("generating"); - map->initBlockMake(data, p); - return true; + *b = block; + return map->initBlockMake(data, p); } *b = block; @@ -377,14 +375,14 @@ void *EmergeThread::Thread() { map = (ServerMap *)&(m_server->m_env->getMap()); emerge = m_server->m_emerge; - mapgen = emerge->mapgen[id]; //emerge->getMapgen(); + mapgen = emerge->mapgen[id]; + enable_mapgen_debug_info = emerge->mapgen_debug_info; while (getRun()) try { - while (!popBlockEmerge(&p, &flags)) { + if (!popBlockEmerge(&p, &flags)) { qevent.wait(); - if (!getRun()) - goto exit_emerge_loop; + continue; } last_tried_pos = p; @@ -489,7 +487,6 @@ void *EmergeThread::Thread() { } END_DEBUG_EXCEPTION_HANDLER(errorstream) -exit_emerge_loop: log_deregister_thread(); return NULL; } -- cgit v1.2.3 From 60e6284f30d31e11c1a464d9a8b3c5c392ceb3f0 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Thu, 21 Feb 2013 17:44:14 -0500 Subject: Tune queue limits, some other adjustments --- src/emerge.cpp | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index ac654f368..dd97734c5 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -49,18 +49,29 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { this->params = NULL; mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); - - qlimit_total = g_settings->getU16("emergequeue_limit_total"); - qlimit_diskonly = g_settings->getU16("emergequeue_limit_diskonly"); - qlimit_generate = g_settings->getU16("emergequeue_limit_generate"); queuemutex.Init(); - int nthreads = g_settings->get("num_emerge_threads").empty() ? - porting::getNumberOfProcessors() : - g_settings->getU16("num_emerge_threads"); + + int nthreads; + if (g_settings->get("num_emerge_threads").empty()) { + int nprocs = porting::getNumberOfProcessors(); + // leave a proc for the main thread and one for some other misc threads + if (nprocs > 2) + nthreads = nprocs - 2; + } else { + nthreads = g_settings->getU16("num_emerge_threads"); + } if (nthreads < 1) nthreads = 1; + qlimit_total = g_settings->getU16("emergequeue_limit_total"); + qlimit_diskonly = g_settings->get("emergequeue_limit_diskonly").empty() ? + nthreads * 5 + 1 : + g_settings->getU16("emergequeue_limit_diskonly"); + qlimit_generate = g_settings->get("emergequeue_limit_generate").empty() ? + nthreads + 1 : + g_settings->getU16("emergequeue_limit_generate"); + for (int i = 0; i != nthreads; i++) emergethread.push_back(new EmergeThread((Server *)gamedef, i)); @@ -138,6 +149,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate peer_queue_count[peer_id] = count + 1; + // insert into the EmergeThread queue with the least items int lowestitems = emergethread[0]->blockqueue.size(); for (int i = 1; i != emergethread.size(); i++) { int nitems = emergethread[i]->blockqueue.size(); @@ -183,7 +195,7 @@ bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { int EmergeManager::getGroundLevelAtPoint(v2s16 p) { - if (!mapgen[0]) { + if (mapgen.size() == 0 || !mapgen[0]) { errorstream << "EmergeManager: getGroundLevelAtPoint() called" " before mapgen initialized" << std::endl; return 0; @@ -365,7 +377,7 @@ bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, void *EmergeThread::Thread() { ThreadStarted(); - log_register_thread("EmergeThread"); + log_register_thread("EmergeThread" + id); DSTACK(__FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER -- cgit v1.2.3 From f00d136ab1523297fdf4707bbc5d40ec9d4f7afb Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 23 Feb 2013 22:06:16 -0500 Subject: Fix selection of # threads, set default to 1 thread --- src/emerge.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index dd97734c5..dc2bb3e99 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -56,8 +56,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { if (g_settings->get("num_emerge_threads").empty()) { int nprocs = porting::getNumberOfProcessors(); // leave a proc for the main thread and one for some other misc threads - if (nprocs > 2) - nthreads = nprocs - 2; + nthreads = (nprocs > 2) ? nthreads = nprocs - 2 : 1; } else { nthreads = g_settings->getU16("num_emerge_threads"); } -- cgit v1.2.3 From 9b5f182642416add39aab7782b1d155dafead160 Mon Sep 17 00:00:00 2001 From: kwolekr Date: Sat, 23 Feb 2013 22:45:12 -0500 Subject: Remove dead code, relocate some code --- src/emerge.cpp | 332 +++++---------------------------------------------------- 1 file changed, 25 insertions(+), 307 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index dc2bb3e99..250c44fbb 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -41,6 +41,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen_v6.h" +/////////////////////////////// Emerge Manager //////////////////////////////// + EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { //register built-in mapgens registerMapgen("v6", new MapgenFactoryV6()); @@ -166,33 +168,6 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate } -bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { - std::map::iterator iter; - JMutexAutoLock queuelock(emerge->queuemutex); - - if (blockqueue.empty()) - return false; - v3s16 p = blockqueue.front(); - blockqueue.pop(); - - *pos = p; - - iter = emerge->blocks_enqueued.find(p); - if (iter == emerge->blocks_enqueued.end()) - return false; //uh oh, queue and map out of sync!! - - BlockEmergeData *bedata = iter->second; - *flags = bedata->flags; - - emerge->peer_queue_count[bedata->peer_requested]--; - - delete bedata; - emerge->blocks_enqueued.erase(iter); - - return true; -} - - int EmergeManager::getGroundLevelAtPoint(v2s16 p) { if (mapgen.size() == 0 || !mapgen[0]) { errorstream << "EmergeManager: getGroundLevelAtPoint() called" @@ -290,59 +265,34 @@ bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) } +////////////////////////////// Emerge Thread ////////////////////////////////// -class MapEditEventIgnorer -{ -public: - MapEditEventIgnorer(bool *flag): - m_flag(flag) - { - if(*m_flag == false) - *m_flag = true; - else - m_flag = NULL; - } - - ~MapEditEventIgnorer() - { - if(m_flag) - { - assert(*m_flag); - *m_flag = false; - } - } - -private: - bool *m_flag; -}; - -class MapEditEventAreaIgnorer -{ -public: - MapEditEventAreaIgnorer(VoxelArea *ignorevariable, const VoxelArea &a): - m_ignorevariable(ignorevariable) - { - if(m_ignorevariable->getVolume() == 0) - *m_ignorevariable = a; - else - m_ignorevariable = NULL; - } +bool EmergeThread::popBlockEmerge(v3s16 *pos, u8 *flags) { + std::map::iterator iter; + JMutexAutoLock queuelock(emerge->queuemutex); - ~MapEditEventAreaIgnorer() - { - if(m_ignorevariable) - { - assert(m_ignorevariable->getVolume() != 0); - *m_ignorevariable = VoxelArea(); - } - } + if (blockqueue.empty()) + return false; + v3s16 p = blockqueue.front(); + blockqueue.pop(); + + *pos = p; + + iter = emerge->blocks_enqueued.find(p); + if (iter == emerge->blocks_enqueued.end()) + return false; //uh oh, queue and map out of sync!! -private: - VoxelArea *m_ignorevariable; -}; + BlockEmergeData *bedata = iter->second; + *flags = bedata->flags; + + emerge->peer_queue_count[bedata->peer_requested]--; + delete bedata; + emerge->blocks_enqueued.erase(iter); + + return true; +} -#if 1 bool EmergeThread::getBlockOrStartGen(v3s16 p, MapBlock **b, BlockMakeData *data, bool allow_gen) { @@ -501,235 +451,3 @@ void *EmergeThread::Thread() { log_deregister_thread(); return NULL; } - -#else - -void *EmergeThread::Thread() { - ThreadStarted(); - log_register_thread("EmergeThread"); - DSTACK(__FUNCTION_NAME); - BEGIN_DEBUG_EXCEPTION_HANDLER - - bool enable_mapgen_debug_info = g_settings->getBool("enable_mapgen_debug_info"); - - v3s16 last_tried_pos(-32768,-32768,-32768); // For error output - ServerMap &map = ((ServerMap&)m_server->m_env->getMap()); - EmergeManager *emerge = m_server->m_emerge; - Mapgen *mapgen = emerge->getMapgen(); - - while(getRun()) - try { - QueuedBlockEmerge *qptr = m_server->m_emerge_queue.pop(); - if(qptr == NULL) - break; - SharedPtr q(qptr); - - v3s16 &p = q->pos; - v2s16 p2d(p.X,p.Z); - - last_tried_pos = p; - - /* - Do not generate over-limit - */ - if (blockpos_over_limit(p)) - continue; - - //infostream<<"EmergeThread::Thread(): running"<::Iterator i; - for (i=q->s.getIterator(); !i.atEnd(); i++) { - u8 flags = i.getNode()->getValue(); - if (!(flags & BLOCK_EMERGE_FLAG_FROMDISK)) { - only_from_disk = false; - break; - } - } - } - - if (enable_mapgen_debug_info) - infostream<<"EmergeThread: p=" - <<"("<isGenerated() == false)){ - if(enable_mapgen_debug_info) - infostream<<"EmergeThread: generating"<makeChunk(&data); - - if (enable_mapgen_debug_info == false) - t.stop(true); // Hide output - } - - do{ // enable break - // Lock environment again to access the map - JMutexAutoLock envlock(m_server->m_env_mutex); - - ScopeProfiler sp(g_profiler, "EmergeThread: after " - "mapgen::make_block (envlock)", SPT_AVG); - - // Blit data back on map, update lighting, add mobs and - // whatever this does - map.finishBlockMake(&data, modified_blocks); - - // Get central block - block = map.getBlockNoCreateNoEx(p); - - // If block doesn't exist, don't try doing anything with it - // This happens if the block is not in generation boundaries - if(!block) - break; - - /* - Do some post-generate stuff - */ - v3s16 minp = data.blockpos_min * MAP_BLOCKSIZE; - v3s16 maxp = data.blockpos_max * MAP_BLOCKSIZE + - v3s16(1,1,1) * (MAP_BLOCKSIZE - 1); - - /* - Ignore map edit events, they will not need to be - sent to anybody because the block hasn't been sent - to anybody - */ - MapEditEventAreaIgnorer ign( - &m_server->m_ignore_map_edit_events_area, - VoxelArea(minp, maxp)); - { - TimeTaker timer("on_generated"); - scriptapi_environment_on_generated(m_server->m_lua, - minp, maxp, emerge->getBlockSeed(minp)); - //int t = timer.stop(true); - //dstream<<"on_generated took "<m_env->activateBlock(block, 0); - }while(false); - } - - if(block == NULL) - got_block = false; - - /* - Set sent status of modified blocks on clients - */ - - // NOTE: Server's clients are also behind the connection mutex - JMutexAutoLock lock(m_server->m_con_mutex); - - /* - Add the originally fetched block to the modified list - */ - if(got_block) - modified_blocks.insert(p, block); - - /* - Set the modified blocks unsent for all the clients - */ - for(core::map::Iterator - i = m_server->m_clients.getIterator(); - i.atEnd() == false; i++) { - RemoteClient *client = i.getNode()->getValue(); - if(modified_blocks.size() > 0) { - // Remove block from sent history - client->SetBlocksNotSent(modified_blocks); - } - } - - -niters++; - } - catch (VersionMismatchException &e) { - std::ostringstream err; - err << "World data version mismatch in MapBlock "<setAsyncFatalError(err.str()); - } - catch (SerializationError &e) { - std::ostringstream err; - err << "Invalid data in MapBlock "<setAsyncFatalError(err.str()); - } -printf("emergethread iterated %d times\n", niters); - END_DEBUG_EXCEPTION_HANDLER(errorstream) - log_deregister_thread(); - return NULL; -} - -#endif -- cgit v1.2.3 From d31f07bd4b83f858cce589faac56922e12ba670f Mon Sep 17 00:00:00 2001 From: kwolekr Date: Tue, 26 Feb 2013 01:57:59 -0500 Subject: Fix most warnings, re-fix MSVC compile error --- src/emerge.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'src/emerge.cpp') diff --git a/src/emerge.cpp b/src/emerge.cpp index 250c44fbb..6c6863eff 100644 --- a/src/emerge.cpp +++ b/src/emerge.cpp @@ -58,7 +58,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { if (g_settings->get("num_emerge_threads").empty()) { int nprocs = porting::getNumberOfProcessors(); // leave a proc for the main thread and one for some other misc threads - nthreads = (nprocs > 2) ? nthreads = nprocs - 2 : 1; + nthreads = (nprocs > 2) ? nprocs - 2 : 1; } else { nthreads = g_settings->getU16("num_emerge_threads"); } @@ -81,7 +81,7 @@ EmergeManager::EmergeManager(IGameDef *gamedef, BiomeDefManager *bdef) { EmergeManager::~EmergeManager() { - for (int i = 0; i != emergethread.size(); i++) { + for (unsigned int i = 0; i != emergethread.size(); i++) { emergethread[i]->setRun(false); emergethread[i]->qevent.signal(); emergethread[i]->stop(); @@ -101,7 +101,7 @@ void EmergeManager::initMapgens(MapgenParams *mgparams) { return; this->params = mgparams; - for (int i = 0; i != emergethread.size(); i++) { + for (unsigned int i = 0; i != emergethread.size(); i++) { mg = createMapgen(params->mg_name, 0, params); if (!mg) { infostream << "EmergeManager: falling back to mapgen v6" << std::endl; @@ -152,7 +152,7 @@ bool EmergeManager::enqueueBlockEmerge(u16 peer_id, v3s16 p, bool allow_generate // insert into the EmergeThread queue with the least items int lowestitems = emergethread[0]->blockqueue.size(); - for (int i = 1; i != emergethread.size(); i++) { + for (unsigned int i = 1; i != emergethread.size(); i++) { int nitems = emergethread[i]->blockqueue.size(); if (nitems < lowestitems) { idx = i; @@ -259,7 +259,7 @@ void EmergeManager::setParamsToSettings(Settings *settings) { } -bool EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { +void EmergeManager::registerMapgen(std::string mgname, MapgenFactory *mgfactory) { mglist.insert(std::make_pair(mgname, mgfactory)); infostream << "EmergeManager: registered mapgen " << mgname << std::endl; } -- cgit v1.2.3