Replace stray tab with whitespace in guiFormSpecMenu.cpp (#9317)
[oweals/minetest.git] / src / util / thread.h
index bb8e03317b8a685a2c3834b72903d85ee1fee175..73e9beb806f44d8effc6dd8e3a3bec3f82adf23f 100644 (file)
@@ -17,54 +17,46 @@ 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 "../jthread/jthread.h"
-#include "../jthread/jmutex.h"
-#include "../jthread/jmutexautolock.h"
+#include "irrlichttypes.h"
+#include "threading/thread.h"
+#include "threading/mutex_auto_lock.h"
+#include "porting.h"
+#include "log.h"
+#include "container.h"
 
 template<typename T>
 class MutexedVariable
 {
 public:
-       MutexedVariable(value):
+       MutexedVariable(const T &value):
                m_value(value)
-       {
-       }
+       {}
 
        T get()
        {
-               JMutexAutoLock lock(m_mutex);
+               MutexAutoLock lock(m_mutex);
                return m_value;
        }
 
-       void set(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;
+       std::mutex m_mutex;
 };
 
 /*
        A single worker thread - multiple client threads queue framework.
 */
 template<typename Key, typename T, typename Caller, typename CallerData>
-class GetResult
-{
+class GetResult {
 public:
        Key key;
        T item;
@@ -72,34 +64,27 @@ public:
 };
 
 template<typename Key, typename T, typename Caller, typename CallerData>
-class ResultQueue: public MutexedQueue< GetResult<Key, T, Caller, CallerData> >
-{
+class ResultQueue : public MutexedQueue<GetResult<Key, T, Caller, CallerData> > {
 };
 
 template<typename Caller, typename Data, typename Key, typename T>
-class CallerInfo
-{
+class CallerInfo {
 public:
        Caller caller;
        Data data;
-       ResultQueue< Key, T, Caller, Data>* dest;
+       ResultQueue<Key, T, Caller, Data> *dest;
 };
 
 template<typename Key, typename T, typename Caller, typename CallerData>
-class GetRequest
-{
+class GetRequest {
 public:
-       GetRequest()
-       {
-       }
-       GetRequest(Key a_key)
-       {
-               key = a_key;
-       }
-       ~GetRequest()
+       GetRequest() = default;
+       ~GetRequest() = default;
+
+       GetRequest(const Key &a_key): key(a_key)
        {
        }
-       
+
        Key key;
        std::list<CallerInfo<Caller, CallerData, Key, T> > callers;
 };
@@ -112,41 +97,38 @@ public:
  * @param CallerData data passed back to caller
  */
 template<typename Key, typename T, typename Caller, typename CallerData>
-class RequestQueue
-{
+class RequestQueue {
 public:
        bool empty()
        {
                return m_queue.empty();
        }
 
-       void add(Key key, Caller caller, CallerData callerdata,
-                       ResultQueue<Key, T, Caller, CallerData> *dest)
+       void add(const Key &key, Caller caller, CallerData callerdata,
+               ResultQueue<Key, T, Caller, CallerData> *dest)
        {
-               JMutexAutoLock lock(m_queue.getMutex());
-               
-               /*
-                       If the caller is already on the list, only update CallerData
-               */
-               for(typename std::list< GetRequest<Key, T, Caller, CallerData> >::iterator
-                               i = m_queue.getList().begin();
-                               i != m_queue.getList().end(); ++i)
+               typename std::deque<GetRequest<Key, T, Caller, CallerData> >::iterator i;
+               typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator j;
+
                {
-                       GetRequest<Key, T, Caller, CallerData> &request = *i;
-
-                       if(request.key == key)
-                       {
-                               for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
-                                               i = request.callers.begin();
-                                               i != request.callers.end(); ++i)
-                               {
-                                       CallerInfo<Caller, CallerData, Key, T> &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<Key, T, Caller, CallerData> &request = *i;
+                               if (request.key != key)
+                                       continue;
+
+                               for (j = request.callers.begin(); j != request.callers.end(); ++j) {
+                                       CallerInfo<Caller, CallerData, Key, T> &ca = *j;
+                                       if (ca.caller == caller) {
                                                ca.data = callerdata;
                                                return;
                                        }
                                }
+
                                CallerInfo<Caller, CallerData, Key, T> ca;
                                ca.caller = caller;
                                ca.data = callerdata;
@@ -167,22 +149,25 @@ public:
                ca.data = callerdata;
                ca.dest = dest;
                request.callers.push_back(ca);
-               
-               m_queue.getList().push_back(request);
+
+               m_queue.push_back(request);
        }
 
-       GetRequest<Key, T, Caller, CallerData> pop(bool wait_if_empty=false)
+       GetRequest<Key, T, Caller, CallerData> pop(unsigned int timeout_ms)
        {
-               return m_queue.pop_front(wait_if_empty);
+               return m_queue.pop_front(timeout_ms);
        }
 
-       void pushResult(GetRequest<Key, T, Caller, CallerData> req,
-                                       T res) {
+       GetRequest<Key, T, Caller, CallerData> pop()
+       {
+               return m_queue.pop_frontNoEx();
+       }
 
-               for(typename std::list< CallerInfo<Caller, CallerData, Key, T> >::iterator
+       void pushResult(GetRequest<Key, T, Caller, CallerData> req, T res)
+       {
+               for (typename std::list<CallerInfo<Caller, CallerData, Key, T> >::iterator
                                i = req.callers.begin();
-                               i != req.callers.end(); ++i)
-               {
+                               i != req.callers.end(); ++i) {
                        CallerInfo<Caller, CallerData, Key, T> &ca = *i;
 
                        GetResult<Key,T,Caller,CallerData> result;
@@ -197,8 +182,47 @@ public:
        }
 
 private:
-       MutexedQueue< GetRequest<Key, T, Caller, CallerData> > m_queue;
+       MutexedQueue<GetRequest<Key, T, Caller, CallerData> > 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;
+};