summaryrefslogtreecommitdiff
path: root/src/utility.h
diff options
context:
space:
mode:
authorPerttu Ahola <celeron55@gmail.com>2010-12-20 22:03:49 +0200
committerPerttu Ahola <celeron55@gmail.com>2010-12-20 22:03:49 +0200
commit123e8fdf53ffb40c7464d0559a49e048fed79d7d (patch)
tree98df766999e684e46629bfa886195427adda2967 /src/utility.h
parent6350c5d7a606924a12ba41468d126ff94d9e6d36 (diff)
downloadminetest-123e8fdf53ffb40c7464d0559a49e048fed79d7d.tar.gz
minetest-123e8fdf53ffb40c7464d0559a49e048fed79d7d.tar.bz2
minetest-123e8fdf53ffb40c7464d0559a49e048fed79d7d.zip
framework for modifying textures
Diffstat (limited to 'src/utility.h')
-rw-r--r--src/utility.h301
1 files changed, 215 insertions, 86 deletions
diff --git a/src/utility.h b/src/utility.h
index e4494948c..cde555760 100644
--- a/src/utility.h
+++ b/src/utility.h
@@ -17,10 +17,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-/*
-(c) 2010 Perttu Ahola <celeron55@gmail.com>
-*/
-
#ifndef UTILITY_HEADER
#define UTILITY_HEADER
@@ -403,56 +399,23 @@ private:
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;
@@ -674,6 +637,48 @@ inline s32 stoi(std::string s)
}
/*
+ 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
*/
@@ -1070,81 +1075,205 @@ private:
};
/*
- 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