X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=src%2Futil%2Fthread.h;h=73e9beb806f44d8effc6dd8e3a3bec3f82adf23f;hb=c7bcebb62856ae5fdb23a13e6fa1052eae700ddf;hp=949bb42048dd548552347552ff601a50178880c7;hpb=979ca23f1eae1adeb8b0083dffe7203c54d87395;p=minetest.git diff --git a/src/util/thread.h b/src/util/thread.h index 949bb4204..73e9beb80 100644 --- a/src/util/thread.h +++ b/src/util/thread.h @@ -17,183 +17,122 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#ifndef UTIL_THREAD_HEADER -#define UTIL_THREAD_HEADER +#pragma once -#include "../irrlichttypes.h" -#include -#include -#include +#include "irrlichttypes.h" +#include "threading/thread.h" +#include "threading/mutex_auto_lock.h" +#include "porting.h" +#include "log.h" +#include "container.h" template class MutexedVariable { public: - MutexedVariable(T value): + MutexedVariable(const T &value): m_value(value) - { - m_mutex.Init(); - } + {} T get() { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); return m_value; } - void set(T value) + void set(const T &value) { - JMutexAutoLock lock(m_mutex); + MutexAutoLock lock(m_mutex); m_value = value; } - - // You'll want to grab this in a SharedPtr - JMutexAutoLock * getLock() - { - return new JMutexAutoLock(m_mutex); - } - + // You pretty surely want to grab the lock when accessing this T m_value; - private: - JMutex m_mutex; -}; - -/* - 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); - } + std::mutex m_mutex; }; /* A single worker thread - multiple client threads queue framework. */ - -template -class CallerInfo -{ -public: - Caller caller; - Data data; -}; - template -class GetResult -{ +class GetResult { public: Key key; T item; - core::list > callers; + std::pair caller; }; template -class ResultQueue: public MutexedQueue< GetResult > -{ +class ResultQueue : public MutexedQueue > { +}; + +template +class CallerInfo { +public: + Caller caller; + Data data; + ResultQueue *dest; }; template -class GetRequest -{ +class GetRequest { public: - GetRequest() - { - dest = NULL; - } - GetRequest(ResultQueue *a_dest) - { - dest = a_dest; - } - GetRequest(ResultQueue *a_dest, - Key a_key) - { - dest = a_dest; - key = a_key; - } - ~GetRequest() + GetRequest() = default; + ~GetRequest() = default; + + GetRequest(const Key &a_key): key(a_key) { } - + Key key; - ResultQueue *dest; - core::list > callers; + std::list > callers; }; +/** + * Notes for RequestQueue usage + * @param Key unique key to identify a request for a specific resource + * @param T ? + * @param Caller unique id of calling thread + * @param CallerData data passed back to caller + */ template -class RequestQueue -{ +class RequestQueue { public: - u32 size() + bool empty() { - return m_queue.size(); + return m_queue.empty(); } - void add(Key key, Caller caller, CallerData callerdata, - ResultQueue *dest) + void add(const Key &key, Caller caller, CallerData callerdata, + ResultQueue *dest) { - JMutexAutoLock lock(m_queue.getMutex()); - - /* - If the caller is already on the list, only update CallerData - */ - for(typename core::list< GetRequest >::Iterator - i = m_queue.getList().begin(); - i != m_queue.getList().end(); i++) + typename std::deque >::iterator i; + typename std::list >::iterator j; + { - GetRequest &request = *i; - - if(request.key == key) - { - for(typename core::list< CallerInfo >::Iterator - i = request.callers.begin(); - i != request.callers.end(); i++) - { - CallerInfo &ca = *i; - if(ca.caller == caller) - { + MutexAutoLock lock(m_queue.getMutex()); + + /* + If the caller is already on the list, only update CallerData + */ + for (i = m_queue.getQueue().begin(); i != m_queue.getQueue().end(); ++i) { + GetRequest &request = *i; + if (request.key != key) + continue; + + for (j = request.callers.begin(); j != request.callers.end(); ++j) { + CallerInfo &ca = *j; + if (ca.caller == caller) { ca.data = callerdata; return; } } - CallerInfo ca; + + CallerInfo ca; ca.caller = caller; ca.data = callerdata; + ca.dest = dest; request.callers.push_back(ca); return; } @@ -205,23 +144,85 @@ class RequestQueue GetRequest request; request.key = key; - CallerInfo ca; + CallerInfo ca; ca.caller = caller; ca.data = callerdata; + ca.dest = dest; request.callers.push_back(ca); - request.dest = dest; - - m_queue.getList().push_back(request); + + m_queue.push_back(request); + } + + GetRequest pop(unsigned int timeout_ms) + { + return m_queue.pop_front(timeout_ms); } - GetRequest pop(bool wait_if_empty=false) + GetRequest pop() { - return m_queue.pop_front(wait_if_empty); + return m_queue.pop_frontNoEx(); + } + + void pushResult(GetRequest req, T res) + { + for (typename std::list >::iterator + i = req.callers.begin(); + i != req.callers.end(); ++i) { + CallerInfo &ca = *i; + + GetResult result; + + result.key = req.key; + result.item = res; + result.caller.first = ca.caller; + result.caller.second = ca.data; + + ca.dest->push_back(result); + } } private: - MutexedQueue< GetRequest > m_queue; + MutexedQueue > m_queue; }; -#endif +class UpdateThread : public Thread +{ +public: + UpdateThread(const std::string &name) : Thread(name + "Update") {} + ~UpdateThread() = default; + + void deferUpdate() { m_update_sem.post(); } + + void stop() + { + Thread::stop(); + + // give us a nudge + m_update_sem.post(); + } + + void *run() + { + BEGIN_DEBUG_EXCEPTION_HANDLER + + while (!stopRequested()) { + m_update_sem.wait(); + // Set semaphore to 0 + while (m_update_sem.wait(0)); + + if (stopRequested()) break; + + doUpdate(); + } + + END_DEBUG_EXCEPTION_HANDLER + return NULL; + } + +protected: + virtual void doUpdate() = 0; + +private: + Semaphore m_update_sem; +};