# It's usually sufficient to change just the target name and source file list\r
# and be sure that CXX is set to a valid compiler\r
TARGET = test\r
-SOURCE_FILES = guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp\r
+SOURCE_FILES = irrlichtwrapper.cpp guiPauseMenu.cpp defaultsettings.cpp mapnode.cpp tile.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp client.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp main.cpp test.cpp\r
SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
-BUILD_DIR = build/\r
+BUILD_DIR = build\r
OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
#OBJECTS = $(SOURCES:.cpp=.o)\r
\r
SERVER_TARGET = server\r
SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp\r
SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))\r
-SERVER_BUILD_DIR = serverbuild/\r
+SERVER_BUILD_DIR = serverbuild\r
SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))\r
#SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o)\r
\r
#fps_max = 60
#viewing_range_nodes_max = 300
#viewing_range_nodes_min = 50
-#screenW =
-#screenH =
+#screenW = 800
+#screenH = 600
#host_game =
#port = 30000
#address = kray.dy.fi
// Viewing range stuff
-//#define FREETIME_RATIO 0.2
-#define FREETIME_RATIO 0.15
+//#define FREETIME_RATIO 0.15
+#define FREETIME_RATIO 0.0
// Sectors are split to SECTOR_HEIGHTMAP_SPLIT^2 heightmaps
#define SECTOR_HEIGHTMAP_SPLIT 2
#include <jmutexautolock.h>
#include <iostream>
#include "common_irrlicht.h"
-
-/*
- Compatibility stuff
-*/
-
-#if (defined(WIN32) || defined(_WIN32_WCE))
-typedef DWORD threadid_t;
-#define __NORETURN __declspec(noreturn)
-#define __FUNCTION_NAME __FUNCTION__
-#else
-typedef pthread_t threadid_t;
-#define __NORETURN __attribute__ ((__noreturn__))
-#define __FUNCTION_NAME __PRETTY_FUNCTION__
-#endif
-
-inline threadid_t get_current_thread_id()
-{
-#if (defined(WIN32) || defined(_WIN32_WCE))
- return GetCurrentThreadId();
-#else
- return pthread_self();
-#endif
-}
+#include "threads.h"
/*
Debug output
g_settings.setDefault("fps_max", "60");
g_settings.setDefault("viewing_range_nodes_max", "300");
g_settings.setDefault("viewing_range_nodes_min", "35");
- g_settings.setDefault("screenW", "");
- g_settings.setDefault("screenH", "");
+ g_settings.setDefault("screenW", "800");
+ g_settings.setDefault("screenH", "600");
g_settings.setDefault("host_game", "");
g_settings.setDefault("port", "");
g_settings.setDefault("address", "");
{}
};
+class ItemNotFoundException : public BaseException
+{
+public:
+ ItemNotFoundException(const char *s):
+ BaseException(s)
+ {}
+};
+
/*
Some "old-style" interrupts:
*/
video::ITexture * MapBlockObjectItem::getImage()
{
if(m_inventorystring.substr(0,3) == "Rat")
- return g_device->getVideoDriver()->getTexture("../data/rat.png");
+ //return g_device->getVideoDriver()->getTexture("../data/rat.png");
+ return g_irrlicht->getTexture("../data/rat.png");
if(m_inventorystring.substr(0,4) == "Sign")
- return g_device->getVideoDriver()->getTexture("../data/sign.png");
+ //return g_device->getVideoDriver()->getTexture("../data/sign.png");
+ return g_irrlicht->getTexture("../data/sign.png");
return NULL;
}
if(m_content >= USEFUL_CONTENT_COUNT)
return NULL;
- return g_texturecache.get(g_content_inventory_textures[m_content]);
+ return g_irrlicht->getTexture(g_content_inventory_textures[m_content]);
}
#endif
std::string getText()
- TODO: A way to generate new textures by combining textures\r
- TODO: Mesh update to fetch cracked faces from the former\r
\r
+TODO: A thread-safe wrapper for irrlicht for threads, to get rid of\r
+ g_device\r
+\r
======================================================================\r
\r
*/\r
#include "porting.h"\r
#include "guiPauseMenu.h"\r
\r
-IrrlichtDevice *g_device = NULL;\r
-\r
-/*const char *g_content_filenames[MATERIALS_COUNT] =\r
-{\r
- "../data/stone.png",\r
- "../data/grass.png",\r
- "../data/water.png",\r
- "../data/torch_on_floor.png",\r
- "../data/tree.png",\r
- "../data/leaves.png",\r
- "../data/grass_footsteps.png",\r
- "../data/mese.png",\r
- "../data/mud.png",\r
- "../data/water.png", // CONTENT_OCEAN\r
-};\r
-\r
-// Material cache\r
-video::SMaterial g_materials[MATERIALS_COUNT];*/\r
-\r
-// Texture cache\r
-TextureCache g_texturecache;\r
-\r
+IrrlichtWrapper *g_irrlicht;\r
\r
// All range-related stuff below is locked behind this\r
JMutex g_range_mutex;\r
\r
static bool fraction_is_good = false;\r
\r
- float fraction_good_threshold = 0.1;\r
+ //float fraction_good_threshold = 0.1;\r
//float fraction_bad_threshold = 0.25;\r
- float fraction_bad_threshold = 0.1;\r
+ float fraction_good_threshold = 0.075;\r
+ float fraction_bad_threshold = 0.125;\r
float fraction_limit;\r
// Use high limit if fraction is good AND the fraction would\r
// lower the range. We want to keep the range fairly high.\r
/*\r
Resolution selection\r
*/\r
+ \r
+ bool fullscreen = false;\r
+ u16 screenW = atoi(g_settings.get("screenW").c_str());\r
+ u16 screenH = atoi(g_settings.get("screenH").c_str());\r
\r
+#if 0\r
u16 screenW;\r
u16 screenH;\r
bool fullscreen = false;\r
screenH = resolutions[r0-1][1];\r
fullscreen = resolutions[r0-1][2];\r
}\r
+#endif\r
\r
//\r
\r
\r
if (device == 0)\r
return 1; // could not create selected driver.\r
+ \r
+ g_irrlicht = new IrrlichtWrapper(device);\r
\r
- g_device = device;\r
+ //g_device = device;\r
\r
device->setResizable(true);\r
\r
/*\r
Preload some random textures that are used in threads\r
*/\r
- \r
+#if 0\r
g_texturecache.set("torch", driver->getTexture("../data/torch.png"));\r
g_texturecache.set("torch_on_floor", driver->getTexture("../data/torch_on_floor.png"));\r
g_texturecache.set("torch_on_ceiling", driver->getTexture("../data/torch_on_ceiling.png"));\r
+ g_texturecache.set("crack", driver->getTexture("../data/crack.png"));\r
\r
/*\r
Load tile textures\r
g_texturecache.set(name, driver->getTexture(filename.c_str()));\r
}\r
\r
- tile_materials_preload(g_texturecache);\r
+#endif\r
+\r
+ //tile_materials_preload(g_texturecache);\r
+ tile_materials_preload(g_irrlicht);\r
+ //tile_materials_init();\r
\r
/*\r
Make a scope here for the client so that it gets removed\r
\r
while(device->run())\r
{\r
+ /*\r
+ Run global IrrlichtWrapper's main thread processing stuff\r
+ */\r
+ g_irrlicht->Run();\r
+\r
/*\r
Random calculations\r
*/\r
// Info text\r
std::wstring infotext;\r
\r
- //TimeTaker //timer1("//timer1", device);\r
+ //TimeTaker //timer1("//timer1", g_irrlicht);\r
\r
// Time of frame without fps limit\r
float busytime;\r
*/\r
\r
{\r
- //TimeTaker timer("client.step(dtime)", device);\r
+ //TimeTaker timer("client.step(dtime)", g_irrlicht);\r
client.step(dtime);\r
//client.step(dtime_avg1);\r
}\r
\r
if(server != NULL)\r
{\r
- //TimeTaker timer("server->step(dtime)", device);\r
+ //TimeTaker timer("server->step(dtime)", g_irrlicht);\r
server->step(dtime);\r
}\r
\r
v3f player_position = client.getPlayerPosition();\r
\r
- //TimeTaker //timer2("//timer2", device);\r
+ //TimeTaker //timer2("//timer2", g_irrlicht);\r
\r
/*\r
Mouse and camera control\r
}\r
else{\r
//client.m_env.getMap().updateCamera(camera_position, camera_direction);\r
- //TimeTaker timer("client.updateCamera", device);\r
+ //TimeTaker timer("client.updateCamera", g_irrlicht);\r
client.updateCamera(camera_position, camera_direction);\r
}\r
\r
//timer2.stop();\r
- //TimeTaker //timer3("//timer3", device);\r
+ //TimeTaker //timer3("//timer3", g_irrlicht);\r
\r
/*\r
Calculate what block is the crosshair pointing to\r
Update gui stuff (0ms)\r
*/\r
\r
- //TimeTaker guiupdatetimer("Gui updating", device);\r
+ //TimeTaker guiupdatetimer("Gui updating", g_irrlicht);\r
\r
{\r
wchar_t temptext[150];\r
Drawing begins\r
*/\r
\r
- TimeTaker drawtimer("Drawing", device);\r
+ TimeTaker drawtimer("Drawing", g_irrlicht);\r
\r
\r
{\r
- TimeTaker timer("beginScene", device);\r
- driver->beginScene(true, true, bgcolor);\r
- //driver->beginScene(false, true, bgcolor);\r
- beginscenetime = timer.stop(true);\r
+ TimeTaker timer("beginScene", g_irrlicht);\r
+ driver->beginScene(true, true, bgcolor);\r
+ //driver->beginScene(false, true, bgcolor);\r
+ beginscenetime = timer.stop(true);\r
}\r
\r
//timer3.stop();\r
//std::cout<<DTIME<<"smgr->drawAll()"<<std::endl;\r
\r
{\r
- TimeTaker timer("smgr", device);\r
- smgr->drawAll();\r
- scenetime = timer.stop(true);\r
+ TimeTaker timer("smgr", g_irrlicht);\r
+ smgr->drawAll();\r
+ scenetime = timer.stop(true);\r
}\r
\r
{\r
- //TimeTaker timer9("auxiliary drawings", device);\r
+ //TimeTaker timer9("auxiliary drawings", g_irrlicht);\r
// 0ms\r
\r
driver->draw2DLine(displaycenter - core::vector2d<s32>(10,0),\r
video::SColor(255,255,255,255));\r
\r
//timer9.stop();\r
- //TimeTaker //timer10("//timer10", device);\r
+ //TimeTaker //timer10("//timer10", g_irrlicht);\r
\r
video::SMaterial m;\r
m.Thickness = 10;\r
}\r
\r
//timer10.stop();\r
- //TimeTaker //timer11("//timer11", device);\r
+ //TimeTaker //timer11("//timer11", g_irrlicht);\r
\r
/*\r
Draw gui\r
\r
// End drawing\r
{\r
- TimeTaker timer("endScene", device);\r
- driver->endScene();\r
- endscenetime = timer.stop(true);\r
+ TimeTaker timer("endScene", g_irrlicht);\r
+ driver->endScene();\r
+ endscenetime = timer.stop(true);\r
}\r
\r
drawtime = drawtimer.stop(true);\r
#define dout_server (*dout_server_ptr)
#define derr_server (*derr_server_ptr)
-#ifndef SERVER
+/*#ifndef SERVER
#include "utility.h"
extern TextureCache g_texturecache;
-#endif
+#endif*/
-extern IrrlichtDevice *g_device;
+#include "irrlichtwrapper.h"
+//extern IrrlichtDevice *g_device;
+extern IrrlichtWrapper *g_irrlicht;
#endif
}
{
- //TimeTaker timer("unspreadLight", g_device);
+ //TimeTaker timer("unspreadLight", g_irrlicht);
unspreadLight(bank, unlight_from, light_sources, modified_blocks);
}
// - Find out why it works
{
- //TimeTaker timer("spreadLight", g_device);
+ //TimeTaker timer("spreadLight", g_irrlicht);
spreadLight(bank, light_sources, modified_blocks);
}
#ifndef SERVER
void Map::expireMeshes(bool only_daynight_diffed)
{
- TimeTaker timer("expireMeshes()", g_device);
+ TimeTaker timer("expireMeshes()", g_irrlicht);
core::map<v2s16, MapSector*>::Iterator si;
si = m_sectors.getIterator();
#if 1
void MapVoxelManipulator::emerge(VoxelArea a, s32 caller_id)
{
- TimeTaker timer1("emerge", g_device, &emerge_time);
+ TimeTaker timer1("emerge", g_irrlicht, &emerge_time);
// Units of these are MapBlocks
v3s16 p_min = getNodeBlockPos(a.MinEdge);
bool block_data_inexistent = false;
try
{
- TimeTaker timer1("emerge load", g_device, &emerge_load_time);
+ TimeTaker timer1("emerge load", g_irrlicht, &emerge_load_time);
/*dstream<<"Loading block (caller_id="<<caller_id<<")"
<<" ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
#if 0
void MapVoxelManipulator::emerge(VoxelArea a)
{
- TimeTaker timer1("emerge", g_device, &emerge_time);
+ TimeTaker timer1("emerge", g_irrlicht, &emerge_time);
v3s16 size = a.getExtent();
continue;
try
{
- TimeTaker timer1("emerge load", g_device, &emerge_load_time);
+ TimeTaker timer1("emerge load", g_irrlicht, &emerge_load_time);
MapNode n = m_map->getNode(a.MinEdge + p);
m_data[i] = n;
m_flags[i] = 0;
if(m_area.getExtent() == v3s16(0,0,0))
return;
- //TimeTaker timer1("blitBack", g_device);
+ //TimeTaker timer1("blitBack", g_irrlicht);
/*
Initialize block cache
if(f.tile.feature == TILEFEAT_NONE)
{
- collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
+ /*collector.append(g_tile_materials[f.tile.id], f.vertices, 4,
+ indices, 6);*/
+ collector.append(tile_material_get(f.tile.id), f.vertices, 4,
indices, 6);
}
else
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
if(dir == v3s16(0,-1,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_floor"));
+ g_irrlicht->getTexture("../data/torch_on_floor.png"));
+ //g_texturecache.get("torch_on_floor"));
else if(dir == v3s16(0,1,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_ceiling"));
+ g_irrlicht->getTexture("../data/torch_on_ceiling.png"));
+ //g_texturecache.get("torch_on_ceiling"));
// For backwards compatibility
else if(dir == v3s16(0,0,0))
buf->getMaterial().setTexture(0,
- g_texturecache.get("torch_on_floor"));
+ g_irrlicht->getTexture("../data/torch_on_floor.png"));
+ //g_texturecache.get("torch_on_floor"));
else
- buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
+ buf->getMaterial().setTexture(0,
+ g_irrlicht->getTexture("../data/torch.png"));
+ //buf->getMaterial().setTexture(0, g_texturecache.get("torch"));
// Add to mesh
mesh_new->addMeshBuffer(buf);
const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] =
{
- "stone",
- "grass",
- "water",
- "torch_on_floor",
- "tree_top",
- "leaves",
- "grass_footsteps",
- "mese",
- "mud",
- "water",
- "cloud",
+ "../data/stone.png",
+ "../data/grass.png",
+ "../data/water.png",
+ "../data/torch_on_floor.png",
+ "../data/tree_top.png",
+ "../data/leaves.png",
+ "../data/grass_footsteps.png",
+ "../data/mese.png",
+ "../data/mud.png",
+ "../data/water.png",
+ "../data/cloud.png",
};
*/
/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
+ Random portability stuff
*/
#ifndef PORTING_HEADER
*/
#include "tile.h"
+#include "irrlichtwrapper.h"
-const char * g_tile_texture_names[TILES_COUNT] =
+// A mapping from tiles to paths of textures
+const char * g_tile_texture_paths[TILES_COUNT] =
{
NULL,
- "stone",
- "water",
- "grass",
- "tree",
- "leaves",
- "grass_footsteps",
- "mese",
- "mud",
- "tree_top",
- "mud_with_grass",
- "cloud",
+ "../data/stone.png",
+ "../data/water.png",
+ "../data/grass.png",
+ "../data/tree.png",
+ "../data/leaves.png",
+ "../data/grass_footsteps.png",
+ "../data/mese.png",
+ "../data/mud.png",
+ "../data/tree_top.png",
+ "../data/mud_with_grass.png",
+ "../data/cloud.png",
};
+// A mapping from tiles to materials
+// Initialized at run-time.
video::SMaterial g_tile_materials[TILES_COUNT];
-void tile_materials_preload(TextureCache &cache)
+void tile_materials_preload(IrrlichtWrapper *irrlicht)
{
for(s32 i=0; i<TILES_COUNT; i++)
{
- const char *name = g_tile_texture_names[i];
+ const char *path = g_tile_texture_paths[i];
video::ITexture *t = NULL;
- if(name != NULL)
+ if(path != NULL)
{
- t = cache.get(name);
+ t = irrlicht->getTexture(path);
assert(t != NULL);
}
//g_tile_materials[TILE_WATER].MaterialType = video::EMT_TRANSPARENT_ADD_COLOR;
}
+video::SMaterial & tile_material_get(u32 i)
+{
+ assert(i < TILES_COUNT);
+
+ return g_tile_materials[i];
+}
+
} param;
};
-// A mapping from tiles to names of cached textures
-extern const char * g_tile_texture_names[TILES_COUNT];
-
-// A mapping from tiles to materials
-// Initialized at run-time.
-extern video::SMaterial g_tile_materials[TILES_COUNT];
+/*extern const char * g_tile_texture_paths[TILES_COUNT];
+extern video::SMaterial g_tile_materials[TILES_COUNT];*/
/*
Functions
*/
// Initializes g_tile_materials
-void tile_materials_preload(TextureCache &cache);
+void tile_materials_preload(IrrlichtWrapper *irrlicht);
+
+video::SMaterial & tile_material_get(u32 i);
#endif
*/
#include "utility.h"
+#include "irrlichtwrapper.h"
+
+TimeTaker::TimeTaker(const char *name, IrrlichtWrapper *irrlicht, u32 *result)
+{
+ m_name = name;
+ m_irrlicht = irrlicht;
+ m_result = result;
+ m_running = true;
+ if(irrlicht == NULL)
+ {
+ m_time1 = 0;
+ return;
+ }
+ m_time1 = m_irrlicht->getTime();
+}
+
+u32 TimeTaker::stop(bool quiet)
+{
+ if(m_running)
+ {
+ if(m_irrlicht == NULL)
+ {
+ /*if(quiet == false)
+ std::cout<<"Couldn't measure time for "<<m_name
+ <<": irrlicht==NULL"<<std::endl;*/
+ return 0;
+ }
+ u32 time2 = m_irrlicht->getTime();
+ u32 dtime = time2 - m_time1;
+ if(m_result != NULL)
+ {
+ (*m_result) += dtime;
+ }
+ else
+ {
+ if(quiet == false)
+ std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
+ }
+ m_running = false;
+ return dtime;
+ }
+ return 0;
+}
const v3s16 g_26dirs[26] =
{
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
-*/
-
#ifndef UTILITY_HEADER
#define UTILITY_HEADER
TimeTaker
*/
+class IrrlichtWrapper;
+
class TimeTaker
{
public:
- TimeTaker(const char *name, IrrlichtDevice *dev, u32 *result=NULL)
- {
- m_name = name;
- m_dev = dev;
- m_result = result;
- m_running = true;
- if(dev == NULL)
- {
- m_time1 = 0;
- return;
- }
- m_time1 = m_dev->getTimer()->getRealTime();
- }
+ TimeTaker(const char *name, IrrlichtWrapper *irrlicht, u32 *result=NULL);
+
~TimeTaker()
{
stop();
}
- u32 stop(bool quiet=false)
- {
- if(m_running)
- {
- if(m_dev == NULL)
- {
- /*if(quiet == false)
- std::cout<<"Couldn't measure time for "<<m_name
- <<": dev==NULL"<<std::endl;*/
- return 0;
- }
- u32 time2 = m_dev->getTimer()->getRealTime();
- u32 dtime = time2 - m_time1;
- if(m_result != NULL)
- {
- (*m_result) += dtime;
- }
- else
- {
- if(quiet == false)
- std::cout<<m_name<<" took "<<dtime<<"ms"<<std::endl;
- }
- m_running = false;
- return dtime;
- }
- return 0;
- }
+
+ u32 stop(bool quiet=false);
+
private:
const char *m_name;
- IrrlichtDevice *m_dev;
+ IrrlichtWrapper *m_irrlicht;
u32 m_time1;
bool m_running;
u32 *m_result;
return atoi(s.c_str());
}
+/*
+ A base class for simple background thread implementation
+*/
+
+class SimpleThread : public JThread
+{
+ bool run;
+ JMutex run_mutex;
+
+public:
+
+ SimpleThread():
+ JThread(),
+ run(true)
+ {
+ run_mutex.Init();
+ }
+
+ virtual ~SimpleThread()
+ {}
+
+ virtual void * Thread() = 0;
+
+ bool getRun()
+ {
+ JMutexAutoLock lock(run_mutex);
+ return run;
+ }
+ void setRun(bool a_run)
+ {
+ JMutexAutoLock lock(run_mutex);
+ run = a_run;
+ }
+
+ void stop()
+ {
+ setRun(false);
+ while(IsRunning())
+ sleep_ms(100);
+ }
+};
+
/*
Config stuff
*/
};
/*
- A thread-safe texture cache.
-
- This is used so that irrlicht doesn't get called from many threads
+ A thread-safe queue
*/
-class TextureCache
+template<typename T>
+class MutexedQueue
{
public:
- TextureCache()
+ MutexedQueue()
{
m_mutex.Init();
- assert(m_mutex.IsInitialized());
+ m_is_empty_mutex.Init();
}
-
- void set(std::string name, video::ITexture *texture)
+ u32 size()
{
- JMutexAutoLock lock(m_mutex);
-
- m_textures[name] = texture;
+ return m_list.size();
}
-
- video::ITexture* get(std::string name)
+ void push_back(T t)
{
JMutexAutoLock lock(m_mutex);
+ m_list.push_back(t);
+
+ if(m_list.size() == 1)
+ m_is_empty_mutex.Unlock();
+ }
+ T pop_front(bool wait_if_empty=false)
+ {
+ for(;;)
+ {
+ {
+ JMutexAutoLock lock(m_mutex);
- core::map<std::string, video::ITexture*>::Node *n;
- n = m_textures.find(name);
+ if(m_list.size() > 0)
+ {
+ if(m_list.size() == 1)
+ m_is_empty_mutex.Lock();
+
+ typename core::list<T>::Iterator begin = m_list.begin();
+ T t = *begin;
+ m_list.erase(begin);
+ return t;
+ }
- if(n != NULL)
- return n->getValue();
+ if(wait_if_empty == false)
+ throw ItemNotFoundException("MutexedQueue: item not found");
+ }
+
+ // To wait for an empty list, we're gonna hang on this mutex
+ m_is_empty_mutex.Lock();
+ m_is_empty_mutex.Unlock();
- return NULL;
+ // Then loop to the beginning and hopefully return something
+ }
}
-private:
- core::map<std::string, video::ITexture*> m_textures;
+ JMutex & getMutex()
+ {
+ return m_mutex;
+ }
+
+ JMutex & getIsEmptyMutex()
+ {
+ return m_is_empty_mutex;
+ }
+
+ core::list<T> & getList()
+ {
+ return m_list;
+ }
+
+protected:
JMutex m_mutex;
+ // This is locked always when the list is empty
+ JMutex m_is_empty_mutex;
+ core::list<T> m_list;
};
-class SimpleThread : public JThread
+template<typename Caller, typename Data>
+class CallerInfo
{
- bool run;
- JMutex run_mutex;
+public:
+ Caller caller;
+ Data data;
+};
+template<typename Key, typename T, typename Caller, typename CallerData>
+class GetResult
+{
public:
+ Key key;
+ T item;
+ core::list<CallerInfo<Caller, CallerData> > callers;
+};
- SimpleThread():
- JThread(),
- run(true)
+template<typename Key, typename T, typename Caller, typename CallerData>
+class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
+{
+};
+
+template<typename Key, typename T, typename Caller, typename CallerData>
+class GetRequest
+{
+public:
+ GetRequest()
{
- run_mutex.Init();
+ dest = NULL;
}
+ GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest)
+ {
+ dest = a_dest;
+ }
+ GetRequest(ResultQueue<Key,T, Caller, CallerData> *a_dest,
+ Key a_key)
+ {
+ dest = a_dest;
+ key = a_key;
+ }
+ ~GetRequest()
+ {
+ }
+
+ Key key;
+ ResultQueue<Key, T, Caller, CallerData> *dest;
+ core::list<CallerInfo<Caller, CallerData> > callers;
+};
- virtual ~SimpleThread()
- {}
-
- virtual void * Thread() = 0;
+/*
+ Quickhands for typical request-result queues.
+ Used for distributing work between threads.
+*/
- bool getRun()
+template<typename Key, typename T, typename Caller, typename CallerData>
+class RequestQueue
+{
+public:
+ u32 size()
{
- JMutexAutoLock lock(run_mutex);
- return run;
+ return m_queue.size();
}
- void setRun(bool a_run)
+
+ void add(Key key, Caller caller, CallerData callerdata,
+ ResultQueue<Key, T, Caller, CallerData> *dest)
{
- JMutexAutoLock lock(run_mutex);
- run = a_run;
+ JMutexAutoLock lock(m_queue.getMutex());
+
+ /*
+ If the caller is already on the list, only update CallerData
+ */
+ for(typename core::list< GetRequest<Key, T, Caller, CallerData> >::Iterator
+ i = m_queue.getList().begin();
+ i != m_queue.getList().end(); i++)
+ {
+ GetRequest<Key, T, Caller, CallerData> &request = *i;
+
+ if(request.key == key)
+ {
+ for(typename core::list< CallerInfo<Caller, CallerData> >::Iterator
+ i = request.callers.begin();
+ i != request.callers.end(); i++)
+ {
+ CallerInfo<Caller, CallerData> &ca = *i;
+ if(ca.caller == caller)
+ {
+ ca.data = callerdata;
+ return;
+ }
+ }
+ CallerInfo<Caller, CallerData> ca;
+ ca.caller = caller;
+ ca.data = callerdata;
+ request.callers.push_back(ca);
+ return;
+ }
+ }
+
+ /*
+ Else add a new request to the queue
+ */
+
+ GetRequest<Key, T, Caller, CallerData> request;
+ request.key = key;
+ CallerInfo<Caller, CallerData> ca;
+ ca.caller = caller;
+ ca.data = callerdata;
+ request.callers.push_back(ca);
+ request.dest = dest;
+
+ m_queue.getList().push_back(request);
+
+ if(m_queue.getList().size() == 1)
+ m_queue.getIsEmptyMutex().Unlock();
}
- void stop()
+ GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
{
- setRun(false);
- while(IsRunning())
- sleep_ms(100);
+ return m_queue.pop_front(wait_if_empty);
}
+
+private:
+ MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
};
#endif
if(m_area.contains(area))
return;
- TimeTaker timer("addArea", g_device, &addarea_time);
+ TimeTaker timer("addArea", g_irrlicht, &addarea_time);
// Calculate new area
VoxelArea new_area;
void VoxelManipulator::clearFlag(u8 flags)
{
// 0-1ms on moderate area
- TimeTaker timer("clearFlag", g_device, &clearflag_time);
+ TimeTaker timer("clearFlag", g_irrlicht, &clearflag_time);
v3s16 s = m_area.getExtent();
core::map<v3s16, u8> &active_nodes,
bool checked3_is_clear)
{
- TimeTaker timer("updateAreaWaterPressure", g_device,
+ TimeTaker timer("updateAreaWaterPressure", g_irrlicht,
&updateareawaterpressure_time);
emerge(a, 3);
try
{
// 0-1ms @ recur_count <= 100
- //TimeTaker timer("getWaterPressure", g_device);
+ //TimeTaker timer("getWaterPressure", g_irrlicht);
pr = getWaterPressure(p, highest_y, recur_count);
}
catch(ProcessingLimitException &e)
try
{
// 0ms
- //TimeTaker timer("spreadWaterPressure", g_device);
+ //TimeTaker timer("spreadWaterPressure", g_irrlicht);
spreadWaterPressure(p, pr, a, active_nodes, 0);
}
catch(ProcessingLimitException &e)
//dstream<<"s1="<<s1<<", s2="<<s2<<std::endl;
{
- TimeTaker timer1("flowWater pre", g_device, &flowwater_pre_time);
+ TimeTaker timer1("flowWater pre", g_irrlicht, &flowwater_pre_time);
// Load neighboring nodes
emerge(VoxelArea(removed_pos - v3s16(1,1,1), removed_pos + v3s16(1,1,1)), 4);
debugprint, stoptime);
}
- if(stoptime != 0 && g_device != NULL)
+ if(stoptime != 0 && g_irrlicht != NULL)
{
- u32 timenow = g_device->getTimer()->getRealTime();
+ u32 timenow = g_irrlicht->getTime();
if(timenow >= stoptime ||
(stoptime < 0x80000000 && timenow > 0x80000000))
{
return;
}
- //TimeTaker timer1("flowWater (active_nodes)", g_device);
+ //TimeTaker timer1("flowWater (active_nodes)", g_irrlicht);
//dstream<<"active_nodes.size() = "<<active_nodes.size()<<std::endl;
u32 stoptime = 0;
- if(g_device != NULL)
+ if(g_irrlicht != NULL)
{
- stoptime = g_device->getTimer()->getRealTime() + timelimit;
+ stoptime = g_irrlicht->getTime() + timelimit;
}
// Count of handled active nodes