LCOV - code coverage report
Current view: top level - src/util - container.h (source / functions) Hit Total Coverage
Test: report Lines: 69 77 89.6 %
Date: 2015-07-11 18:23:49 Functions: 47 64 73.4 %

          Line data    Source code
       1             : /*
       2             : Minetest
       3             : Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
       4             : 
       5             : This program is free software; you can redistribute it and/or modify
       6             : it under the terms of the GNU Lesser General Public License as published by
       7             : the Free Software Foundation; either version 2.1 of the License, or
       8             : (at your option) any later version.
       9             : 
      10             : This program is distributed in the hope that it will be useful,
      11             : but WITHOUT ANY WARRANTY; without even the implied warranty of
      12             : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      13             : GNU Lesser General Public License for more details.
      14             : 
      15             : You should have received a copy of the GNU Lesser General Public License along
      16             : with this program; if not, write to the Free Software Foundation, Inc.,
      17             : 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
      18             : */
      19             : 
      20             : #ifndef UTIL_CONTAINER_HEADER
      21             : #define UTIL_CONTAINER_HEADER
      22             : 
      23             : #include "../irrlichttypes.h"
      24             : #include "../exceptions.h"
      25             : #include "../jthread/jmutex.h"
      26             : #include "../jthread/jmutexautolock.h"
      27             : #include "../jthread/jsemaphore.h"
      28             : #include <list>
      29             : #include <vector>
      30             : #include <map>
      31             : #include <set>
      32             : #include <queue>
      33             : 
      34             : /*
      35             : Queue with unique values with fast checking of value existence
      36             : */
      37             : 
      38             : template<typename Value>
      39           2 : class UniqueQueue
      40             : {
      41             : public:
      42             : 
      43             :         /*
      44             :         Does nothing if value is already queued.
      45             :         Return value:
      46             :         true: value added
      47             :         false: value already exists
      48             :         */
      49         173 :         bool push_back(const Value& value)
      50             :         {
      51         173 :                 if (m_set.insert(value).second)
      52             :                 {
      53          22 :                         m_queue.push(value);
      54          22 :                         return true;
      55             :                 }
      56         151 :                 return false;
      57             :         }
      58             : 
      59           0 :         void pop_front()
      60             :         {
      61           0 :                 m_set.erase(m_queue.front());
      62           0 :                 m_queue.pop();
      63           0 :         }
      64             : 
      65           0 :         const Value& front() const
      66             :         {
      67           0 :                 return m_queue.front();
      68             :         }
      69             : 
      70           0 :         u32 size() const
      71             :         {
      72           0 :                 return m_queue.size();
      73             :         }
      74             : 
      75             : private:
      76             :         std::set<Value> m_set;
      77             :         std::queue<Value> m_queue;
      78             : };
      79             : 
      80             : template<typename Key, typename Value>
      81           4 : class MutexedMap
      82             : {
      83             : public:
      84           4 :         MutexedMap()
      85           4 :         {
      86           4 :         }
      87             : 
      88        6927 :         void set(const Key &name, const Value &value)
      89             :         {
      90       13854 :                 JMutexAutoLock lock(m_mutex);
      91             : 
      92        6927 :                 m_values[name] = value;
      93        6927 :         }
      94             : 
      95      136349 :         bool get(const Key &name, Value *result)
      96             :         {
      97      272698 :                 JMutexAutoLock lock(m_mutex);
      98             : 
      99      136349 :                 typename std::map<Key, Value>::iterator n;
     100      136349 :                 n = m_values.find(name);
     101             : 
     102      136349 :                 if(n == m_values.end())
     103        4651 :                         return false;
     104             : 
     105      131698 :                 if(result != NULL)
     106      131698 :                         *result = n->second;
     107             : 
     108      131698 :                 return true;
     109             :         }
     110             : 
     111           1 :         std::vector<Value> getValues()
     112             :         {
     113           1 :                 std::vector<Value> result;
     114          23 :                 for(typename std::map<Key, Value>::iterator
     115           1 :                         i = m_values.begin();
     116          16 :                         i != m_values.end(); ++i){
     117           7 :                         result.push_back(i->second);
     118             :                 }
     119           1 :                 return result;
     120             :         }
     121             : 
     122           1 :         void clear ()
     123             :         {
     124           1 :                 m_values.clear();
     125           1 :         }
     126             : 
     127             : private:
     128             :         std::map<Key, Value> m_values;
     129             :         JMutex m_mutex;
     130             : };
     131             : 
     132             : /*
     133             : Generates ids for comparable values.
     134             : Id=0 is reserved for "no value".
     135             : 
     136             : Is fast at:
     137             : - Returning value by id (very fast)
     138             : - Returning id by value
     139             : - Generating a new id for a value
     140             : 
     141             : Is not able to:
     142             : - Remove an id/value pair (is possible to implement but slow)
     143             : */
     144             : template<typename T>
     145             : class MutexedIdGenerator
     146             : {
     147             : public:
     148             :         MutexedIdGenerator()
     149             :         {
     150             :         }
     151             : 
     152             :         // Returns true if found
     153             :         bool getValue(u32 id, T &value)
     154             :         {
     155             :                 if(id == 0)
     156             :                         return false;
     157             :                 JMutexAutoLock lock(m_mutex);
     158             :                 if(m_id_to_value.size() < id)
     159             :                         return false;
     160             :                 value = m_id_to_value[id-1];
     161             :                 return true;
     162             :         }
     163             : 
     164             :         // If id exists for value, returns the id.
     165             :         // Otherwise generates an id for the value.
     166             :         u32 getId(const T &value)
     167             :         {
     168             :                 JMutexAutoLock lock(m_mutex);
     169             :                 typename std::map<T, u32>::iterator n;
     170             :                 n = m_value_to_id.find(value);
     171             :                 if(n != m_value_to_id.end())
     172             :                         return n->second;
     173             :                 m_id_to_value.push_back(value);
     174             :                 u32 new_id = m_id_to_value.size();
     175             :                 m_value_to_id.insert(value, new_id);
     176             :                 return new_id;
     177             :         }
     178             : 
     179             : private:
     180             :         JMutex m_mutex;
     181             :         // Values are stored here at id-1 position (id 1 = [0])
     182             :         std::vector<T> m_id_to_value;
     183             :         std::map<T, u32> m_value_to_id;
     184             : };
     185             : 
     186             : /*
     187             : Thread-safe FIFO queue (well, actually a FILO also)
     188             : */
     189             : 
     190             : template<typename T>
     191           8 : class MutexedQueue
     192             : {
     193             : public:
     194             :         template<typename Key, typename U, typename Caller, typename CallerData>
     195             :         friend class RequestQueue;
     196             : 
     197           8 :         MutexedQueue()
     198           8 :         {
     199           8 :         }
     200        5660 :         bool empty()
     201             :         {
     202       11320 :                 JMutexAutoLock lock(m_mutex);
     203       11320 :                 return (m_queue.size() == 0);
     204             :         }
     205        8074 :         void push_back(T t)
     206             :         {
     207       16148 :                 JMutexAutoLock lock(m_mutex);
     208        8074 :                 m_queue.push_back(t);
     209        8074 :                 m_size.Post();
     210        8074 :         }
     211             : 
     212             :         /* this version of pop_front returns a empty element of T on timeout.
     213             :         * Make sure default constructor of T creates a recognizable "empty" element
     214             :         */
     215        7989 :         T pop_frontNoEx(u32 wait_time_max_ms)
     216             :         {
     217        7989 :                 if (m_size.Wait(wait_time_max_ms)) {
     218        9208 :                         JMutexAutoLock lock(m_mutex);
     219             : 
     220        9208 :                         T t = m_queue.front();
     221        4604 :                         m_queue.pop_front();
     222        4604 :                         return t;
     223             :                 }
     224             :                 else {
     225        3385 :                         return T();
     226             :                 }
     227             :         }
     228             : 
     229        2514 :         T pop_front(u32 wait_time_max_ms)
     230             :         {
     231        2514 :                 if (m_size.Wait(wait_time_max_ms)) {
     232        2648 :                         JMutexAutoLock lock(m_mutex);
     233             : 
     234        2648 :                         T t = m_queue.front();
     235        1324 :                         m_queue.pop_front();
     236        2648 :                         return t;
     237             :                 }
     238             :                 else {
     239        1190 :                         throw ItemNotFoundException("MutexedQueue: queue is empty");
     240             :                 }
     241             :         }
     242             : 
     243        2141 :         T pop_frontNoEx()
     244             :         {
     245        2141 :                 m_size.Wait();
     246             : 
     247        4282 :                 JMutexAutoLock lock(m_mutex);
     248             : 
     249        2141 :                 T t = m_queue.front();
     250        2141 :                 m_queue.pop_front();
     251        4282 :                 return t;
     252             :         }
     253             : 
     254             :         T pop_back(u32 wait_time_max_ms=0)
     255             :         {
     256             :                 if (m_size.Wait(wait_time_max_ms)) {
     257             :                         JMutexAutoLock lock(m_mutex);
     258             : 
     259             :                         T t = m_queue.back();
     260             :                         m_queue.pop_back();
     261             :                         return t;
     262             :                 }
     263             :                 else {
     264             :                         throw ItemNotFoundException("MutexedQueue: queue is empty");
     265             :                 }
     266             :         }
     267             : 
     268             :         /* this version of pop_back returns a empty element of T on timeout.
     269             :         * Make sure default constructor of T creates a recognizable "empty" element
     270             :         */
     271             :         T pop_backNoEx(u32 wait_time_max_ms=0)
     272             :         {
     273             :                 if (m_size.Wait(wait_time_max_ms)) {
     274             :                         JMutexAutoLock lock(m_mutex);
     275             : 
     276             :                         T t = m_queue.back();
     277             :                         m_queue.pop_back();
     278             :                         return t;
     279             :                 }
     280             :                 else {
     281             :                         return T();
     282             :                 }
     283             :         }
     284             : 
     285             :         T pop_backNoEx()
     286             :         {
     287             :                 m_size.Wait();
     288             : 
     289             :                 JMutexAutoLock lock(m_mutex);
     290             : 
     291             :                 T t = m_queue.back();
     292             :                 m_queue.pop_back();
     293             :                 return t;
     294             :         }
     295             : 
     296             : protected:
     297           2 :         JMutex & getMutex()
     298             :         {
     299           2 :                 return m_mutex;
     300             :         }
     301             : 
     302           4 :         std::deque<T> & getQueue()
     303             :         {
     304           4 :                 return m_queue;
     305             :         }
     306             : 
     307             :         std::deque<T> m_queue;
     308             :         JMutex m_mutex;
     309             :         JSemaphore m_size;
     310             : };
     311             : 
     312             : #endif
     313             : 

Generated by: LCOV version 1.11