container.h 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. /*
  2. Minetest
  3. Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License along
  13. with this program; if not, write to the Free Software Foundation, Inc.,
  14. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  15. */
  16. #pragma once
  17. #include "../irrlichttypes.h"
  18. #include "../exceptions.h"
  19. #include "../threading/mutex_auto_lock.h"
  20. #include "../threading/semaphore.h"
  21. #include <list>
  22. #include <vector>
  23. #include <map>
  24. #include <set>
  25. #include <queue>
  26. /*
  27. Queue with unique values with fast checking of value existence
  28. */
  29. template<typename Value>
  30. class UniqueQueue
  31. {
  32. public:
  33. /*
  34. Does nothing if value is already queued.
  35. Return value:
  36. true: value added
  37. false: value already exists
  38. */
  39. bool push_back(const Value& value)
  40. {
  41. if (m_set.insert(value).second)
  42. {
  43. m_queue.push(value);
  44. return true;
  45. }
  46. return false;
  47. }
  48. void pop_front()
  49. {
  50. m_set.erase(m_queue.front());
  51. m_queue.pop();
  52. }
  53. const Value& front() const
  54. {
  55. return m_queue.front();
  56. }
  57. u32 size() const
  58. {
  59. return m_queue.size();
  60. }
  61. private:
  62. std::set<Value> m_set;
  63. std::queue<Value> m_queue;
  64. };
  65. template<typename Key, typename Value>
  66. class MutexedMap
  67. {
  68. public:
  69. MutexedMap() = default;
  70. void set(const Key &name, const Value &value)
  71. {
  72. MutexAutoLock lock(m_mutex);
  73. m_values[name] = value;
  74. }
  75. bool get(const Key &name, Value *result) const
  76. {
  77. MutexAutoLock lock(m_mutex);
  78. typename std::map<Key, Value>::const_iterator n =
  79. m_values.find(name);
  80. if (n == m_values.end())
  81. return false;
  82. if (result)
  83. *result = n->second;
  84. return true;
  85. }
  86. std::vector<Value> getValues() const
  87. {
  88. MutexAutoLock lock(m_mutex);
  89. std::vector<Value> result;
  90. for (typename std::map<Key, Value>::const_iterator
  91. it = m_values.begin();
  92. it != m_values.end(); ++it){
  93. result.push_back(it->second);
  94. }
  95. return result;
  96. }
  97. void clear() { m_values.clear(); }
  98. private:
  99. std::map<Key, Value> m_values;
  100. mutable std::mutex m_mutex;
  101. };
  102. // Thread-safe Double-ended queue
  103. template<typename T>
  104. class MutexedQueue
  105. {
  106. public:
  107. template<typename Key, typename U, typename Caller, typename CallerData>
  108. friend class RequestQueue;
  109. MutexedQueue() = default;
  110. bool empty() const
  111. {
  112. MutexAutoLock lock(m_mutex);
  113. return m_queue.empty();
  114. }
  115. void push_back(T t)
  116. {
  117. MutexAutoLock lock(m_mutex);
  118. m_queue.push_back(t);
  119. m_signal.post();
  120. }
  121. /* this version of pop_front returns a empty element of T on timeout.
  122. * Make sure default constructor of T creates a recognizable "empty" element
  123. */
  124. T pop_frontNoEx(u32 wait_time_max_ms)
  125. {
  126. if (m_signal.wait(wait_time_max_ms)) {
  127. MutexAutoLock lock(m_mutex);
  128. T t = m_queue.front();
  129. m_queue.pop_front();
  130. return t;
  131. }
  132. return T();
  133. }
  134. T pop_front(u32 wait_time_max_ms)
  135. {
  136. if (m_signal.wait(wait_time_max_ms)) {
  137. MutexAutoLock lock(m_mutex);
  138. T t = m_queue.front();
  139. m_queue.pop_front();
  140. return t;
  141. }
  142. throw ItemNotFoundException("MutexedQueue: queue is empty");
  143. }
  144. T pop_frontNoEx()
  145. {
  146. m_signal.wait();
  147. MutexAutoLock lock(m_mutex);
  148. T t = m_queue.front();
  149. m_queue.pop_front();
  150. return t;
  151. }
  152. T pop_back(u32 wait_time_max_ms=0)
  153. {
  154. if (m_signal.wait(wait_time_max_ms)) {
  155. MutexAutoLock lock(m_mutex);
  156. T t = m_queue.back();
  157. m_queue.pop_back();
  158. return t;
  159. }
  160. throw ItemNotFoundException("MutexedQueue: queue is empty");
  161. }
  162. /* this version of pop_back returns a empty element of T on timeout.
  163. * Make sure default constructor of T creates a recognizable "empty" element
  164. */
  165. T pop_backNoEx(u32 wait_time_max_ms)
  166. {
  167. if (m_signal.wait(wait_time_max_ms)) {
  168. MutexAutoLock lock(m_mutex);
  169. T t = m_queue.back();
  170. m_queue.pop_back();
  171. return t;
  172. }
  173. return T();
  174. }
  175. T pop_backNoEx()
  176. {
  177. m_signal.wait();
  178. MutexAutoLock lock(m_mutex);
  179. T t = m_queue.back();
  180. m_queue.pop_back();
  181. return t;
  182. }
  183. protected:
  184. std::mutex &getMutex() { return m_mutex; }
  185. std::deque<T> &getQueue() { return m_queue; }
  186. std::deque<T> m_queue;
  187. mutable std::mutex m_mutex;
  188. Semaphore m_signal;
  189. };
  190. template<typename K, typename V>
  191. class LRUCache
  192. {
  193. public:
  194. LRUCache(size_t limit, void (*cache_miss)(void *data, const K &key, V *dest),
  195. void *data)
  196. {
  197. m_limit = limit;
  198. m_cache_miss = cache_miss;
  199. m_cache_miss_data = data;
  200. }
  201. void setLimit(size_t limit)
  202. {
  203. m_limit = limit;
  204. invalidate();
  205. }
  206. void invalidate()
  207. {
  208. m_map.clear();
  209. m_queue.clear();
  210. }
  211. const V *lookupCache(K key)
  212. {
  213. typename cache_type::iterator it = m_map.find(key);
  214. V *ret;
  215. if (it != m_map.end()) {
  216. // found!
  217. cache_entry_t &entry = it->second;
  218. ret = &entry.second;
  219. // update the usage information
  220. m_queue.erase(entry.first);
  221. m_queue.push_front(key);
  222. entry.first = m_queue.begin();
  223. } else {
  224. // cache miss -- enter into cache
  225. cache_entry_t &entry =
  226. m_map[key];
  227. ret = &entry.second;
  228. m_cache_miss(m_cache_miss_data, key, &entry.second);
  229. // delete old entries
  230. if (m_queue.size() == m_limit) {
  231. const K &id = m_queue.back();
  232. m_map.erase(id);
  233. m_queue.pop_back();
  234. }
  235. m_queue.push_front(key);
  236. entry.first = m_queue.begin();
  237. }
  238. return ret;
  239. }
  240. private:
  241. void (*m_cache_miss)(void *data, const K &key, V *dest);
  242. void *m_cache_miss_data;
  243. size_t m_limit;
  244. typedef typename std::template pair<typename std::template list<K>::iterator, V> cache_entry_t;
  245. typedef std::template map<K, cache_entry_t> cache_type;
  246. cache_type m_map;
  247. // we can't use std::deque here, because its iterators get invalidated
  248. std::list<K> m_queue;
  249. };