aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSubv <subv2112@gmail.com>2013-12-29 21:37:43 -0500
committerSubv <subv2112@gmail.com>2013-12-29 21:37:43 -0500
commit15d66d19b42759ccbb1900082c736a3953fcd3c9 (patch)
treec170a3c556363e22d164bea438aa1bae667816ac
parent473e4a7b7b72f5e316e0508d5232d4e96fa0168f (diff)
Tools/MeshExtractor: Fixed the threading, threads should no longer behave in a weird way.
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.cpp143
-rw-r--r--src/tools/mesh_extractor/ContinentBuilder.h63
2 files changed, 113 insertions, 93 deletions
diff --git a/src/tools/mesh_extractor/ContinentBuilder.cpp b/src/tools/mesh_extractor/ContinentBuilder.cpp
index e2c5616db31..8321a7924a1 100644
--- a/src/tools/mesh_extractor/ContinentBuilder.cpp
+++ b/src/tools/mesh_extractor/ContinentBuilder.cpp
@@ -16,80 +16,13 @@
*/
#include "ContinentBuilder.h"
-#include "TileBuilder.h"
#include "WDT.h"
#include "Utils.h"
#include "DetourNavMesh.h"
#include "Cache.h"
-#include "ace/Task.h"
#include "Recast.h"
#include "DetourCommon.h"
-#include <ace/Atomic_Op.h>
-#include <ace/Guard_T.h>
-#include <ace/Synch.h>
-
-class BuilderThread : public ACE_Task_Base
-{
-private:
- ACE_Thread_Mutex lock;
- int X, Y, MapId;
- std::string Continent;
- dtNavMeshParams Params;
- ContinentBuilder* cBuilder;
-public:
- BuilderThread(ContinentBuilder* _cBuilder, dtNavMeshParams& params) : Params(params), cBuilder(_cBuilder), Free(true) {}
-
- void SetData(int x, int y, int map, const std::string& cont)
- {
- ACE_GUARD(ACE_Thread_Mutex, g, lock);
- X = x;
- Y = y;
- MapId = map;
- Continent = cont;
- Free = false;
- }
-
- int svc()
- {
- ACE_GUARD_RETURN(ACE_Thread_Mutex, g, lock, 0);
- printf("[%02i,%02i] Building tile\n", X, Y);
- TileBuilder builder(cBuilder, Continent, X, Y, MapId);
- char buff[100];
- sprintf(buff, "mmaps/%03u%02i%02i.mmtile", MapId, Y, X);
- FILE* f = fopen(buff, "r");
- if (f) // Check if file already exists.
- {
- printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
- fclose(f);
- Free = true;
- return 0;
- }
- uint8* nav = builder.BuildTiled(Params);
- if (nav)
- {
- f = fopen(buff, "wb");
- if (!f)
- {
- printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
- return 0;
- }
- MmapTileHeader header;
- Utils::InitializeMmapTileHeader(header);
- header.size = builder.DataSize;
- fwrite(&header, sizeof(MmapTileHeader), 1, f);
- fwrite(nav, sizeof(unsigned char), builder.DataSize, f);
- fclose(f);
- }
- dtFree(nav);
- printf("[%02i,%02i] Tile Built!\n", X, Y);
- Free = true;
- return 0;
- }
-
- ACE_Atomic_Op<ACE_Thread_Mutex, bool> Free;
-};
-
void ContinentBuilder::getTileBounds(uint32 tileX, uint32 tileY, float* verts, int vertCount, float* bmin, float* bmax)
{
// this is for elevation
@@ -136,8 +69,6 @@ void ContinentBuilder::Build()
dtNavMeshParams params;
- std::vector<BuilderThread*> Threads;
-
if (TileMap->IsGlobalModel)
{
printf("Map %s ( %u ) is a WMO. Building with 1 thread.\n", Continent.c_str(), MapId);
@@ -187,36 +118,62 @@ void ContinentBuilder::Build()
fwrite(&params, sizeof(dtNavMeshParams), 1, mmap);
fclose(mmap);
- for (uint32 i = 0; i < NumberOfThreads; ++i)
- Threads.push_back(new BuilderThread(this, params));
+ std::vector<BuilderThread*> _threads;
+ BuilderThreadPool* pool = NumberOfThreads > 0 ? new BuilderThreadPool() : NULL;
+
printf("Map %s ( %u ) has %u tiles. Building them with %u threads\n", Continent.c_str(), MapId, uint32(TileMap->TileTable.size()), NumberOfThreads);
+
for (std::vector<TilePos>::iterator itr = TileMap->TileTable.begin(); itr != TileMap->TileTable.end(); ++itr)
+ pool->Enqueue(new TileBuildRequest(this, Continent, itr->X, itr->Y, MapId, params));
+
+ for (uint32 i = 0; i < NumberOfThreads; ++i)
+ _threads.push_back(new BuilderThread(this, pool->Queue()));
+
+ // Free memory
+ for (std::vector<BuilderThread*>::iterator _th = _threads.begin(); _th != _threads.end(); ++_th)
{
- bool next = false;
- while (!next)
- {
- for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
- {
- if ((*_th)->Free.value())
- {
- (*_th)->SetData(itr->X, itr->Y, MapId, Continent);
- (*_th)->activate();
- next = true;
- break;
- }
- }
- // Wait for 20 seconds
- ACE_OS::sleep(ACE_Time_Value (0, 20000));
- }
+ (*_th)->wait();
+ delete *_th;
}
- }
- // Free memory
- for (std::vector<BuilderThread*>::iterator _th = Threads.begin(); _th != Threads.end(); ++_th)
- {
- (*_th)->wait();
- delete *_th;
+ delete pool;
}
Cache->Clear();
}
+
+int TileBuildRequest::call()
+{
+ printf("[%02i,%02i] Building tile\n", X, Y);
+ // Build the tile and return negative on error
+ TileBuilder tile(_builder, _continent, X, Y, _mapId);
+ char buff[100];
+ sprintf(buff, "mmaps/%03u%02i%02i.mmtile", _mapId, Y, X);
+ FILE* f = fopen(buff, "r");
+ if (f) // Check if file already exists.
+ {
+ printf("[%02i,%02i] Tile skipped, file already exists\n", X, Y);
+ fclose(f);
+ return 0;
+ }
+ uint8* nav = tile.BuildTiled(_params);
+ if (nav)
+ {
+ f = fopen(buff, "wb");
+ if (!f)
+ {
+ printf("Could not create file %s. Check that you have write permissions to the destination folder and try again\n", buff);
+ dtFree(nav);
+ return -1;
+ }
+ MmapTileHeader header;
+ Utils::InitializeMmapTileHeader(header);
+ header.size = tile.DataSize;
+ fwrite(&header, sizeof(MmapTileHeader), 1, f);
+ fwrite(nav, sizeof(unsigned char), tile.DataSize, f);
+ fclose(f);
+ }
+ dtFree(nav);
+ printf("[%02i,%02i] Tile Built!\n", X, Y);
+ return 0;
+}
diff --git a/src/tools/mesh_extractor/ContinentBuilder.h b/src/tools/mesh_extractor/ContinentBuilder.h
index 5349b8e1ba5..ce1eef9b642 100644
--- a/src/tools/mesh_extractor/ContinentBuilder.h
+++ b/src/tools/mesh_extractor/ContinentBuilder.h
@@ -17,9 +17,15 @@
#ifndef CONT_BUILDER_H
#define CONT_BUILDER_H
+
#include <string>
#include "WDT.h"
#include "Define.h"
+#include "TileBuilder.h"
+
+#include <ace/Task.h>
+#include <ace/Activation_Queue.h>
+#include <ace/Method_Request.h>
class ContinentBuilder
{
@@ -44,4 +50,61 @@ private:
int tileXMax;
int tileYMax;
};
+
+class TileBuildRequest : public ACE_Method_Request
+{
+public:
+ TileBuildRequest(ContinentBuilder* builder, std::string& continent, uint32 x, uint32 y, uint32 mapId, dtNavMeshParams& params) : _builder(builder), _continent(continent), X(x), Y(y), _mapId(mapId), _params(params) { }
+
+ virtual int call();
+
+private:
+ uint32 _mapId;
+ ContinentBuilder* _builder;
+ std::string& _continent;
+ uint32 X;
+ uint32 Y;
+ dtNavMeshParams& _params;
+};
+
+class BuilderThreadPool
+{
+public:
+ BuilderThreadPool() : _queue(new ACE_Activation_Queue()) {}
+ ~BuilderThreadPool() { _queue->queue()->close(); delete _queue; }
+
+ void Enqueue(TileBuildRequest* request)
+ {
+ _queue->enqueue(request);
+ }
+
+ ACE_Activation_Queue* Queue() { return _queue; }
+
+private:
+ ACE_Activation_Queue* _queue;
+};
+
+class BuilderThread : public ACE_Task_Base
+{
+private:
+ ContinentBuilder* _builder;
+ ACE_Activation_Queue* _queue;
+public:
+ BuilderThread(ContinentBuilder* builder, ACE_Activation_Queue* queue) : _builder(builder), _queue(queue) { activate(); }
+
+ int svc()
+ {
+ /// @ Set a timeout for dequeue attempts (only used when the queue is empty) as it will never get populated after thread starts
+ ACE_Time_Value timeout(5);
+ ACE_Method_Request* request = NULL;
+ while ((request = _queue->dequeue(&timeout)) != NULL)
+ {
+ request->call();
+ delete request;
+ request = NULL;
+ }
+ return 0;
+ }
+};
+
#endif