L2TIntObjectHashMap.java 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353
  1. /*
  2. * This program is free software: you can redistribute it and/or modify it under
  3. * the terms of the GNU General Public License as published by the Free Software
  4. * Foundation, either version 3 of the License, or (at your option) any later
  5. * version.
  6. *
  7. * This program is distributed in the hope that it will be useful, but WITHOUT
  8. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  10. * details.
  11. *
  12. * You should have received a copy of the GNU General Public License along with
  13. * this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. package com.l2jserver.gameserver.util;
  16. import gnu.trove.TIntObjectHashMap;
  17. import gnu.trove.TIntObjectProcedure;
  18. import gnu.trove.TIntProcedure;
  19. import gnu.trove.TObjectFunction;
  20. import gnu.trove.TObjectProcedure;
  21. import java.util.concurrent.locks.Lock;
  22. import java.util.concurrent.locks.ReentrantReadWriteLock;
  23. /**
  24. * Custom extension of TIntObjectHashMap that is synchronised via ReentrantReadWriteLock.
  25. * The purpose of this map is to replace the use of FastMap<K,V>.shared() which requires a lot of resources.
  26. *
  27. * @author Nik
  28. *
  29. * @param <V> value object.
  30. */
  31. public class L2TIntObjectHashMap<V extends Object> extends TIntObjectHashMap<V>
  32. {
  33. private final Lock _readLock;
  34. private final Lock _writeLock;
  35. private boolean _tempWritesLockDisable;
  36. public L2TIntObjectHashMap()
  37. {
  38. super();
  39. ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
  40. _readLock = lock.readLock();
  41. _writeLock = lock.writeLock();
  42. _tempWritesLockDisable = false;
  43. }
  44. public V put(int key, V value)
  45. {
  46. _writeLock.lock();
  47. try
  48. {
  49. return super.put(key, value);
  50. }
  51. finally
  52. {
  53. _writeLock.unlock();
  54. }
  55. }
  56. /**
  57. * Unsynchronized operation, its free from any locks. <br>
  58. * Its useful while the readLock is taken by a thread (forEach operation for example) and you need to put
  59. * something in the map without causing a deadlock by taking the writeLock before the readLock is unlocked.
  60. */
  61. public V unsynchronizedPut(int key, V value)
  62. {
  63. return super.put(key, value);
  64. }
  65. public V get(int key)
  66. {
  67. if (!_tempWritesLockDisable)
  68. _readLock.lock();
  69. try
  70. {
  71. return super.get(key);
  72. }
  73. finally
  74. {
  75. if (!_tempWritesLockDisable)
  76. _readLock.unlock();
  77. }
  78. }
  79. public void clear()
  80. {
  81. _writeLock.lock();
  82. try
  83. {
  84. super.clear();
  85. }
  86. finally
  87. {
  88. _writeLock.unlock();
  89. }
  90. }
  91. public V remove(int key)
  92. {
  93. if (!_tempWritesLockDisable)
  94. _writeLock.lock();
  95. try
  96. {
  97. return super.remove(key);
  98. }
  99. finally
  100. {
  101. if (!_tempWritesLockDisable)
  102. _writeLock.unlock();
  103. }
  104. }
  105. /**
  106. * Unsynchronized operation, its free from any locks. <br>
  107. * Its useful while the readLock is taken by a thread (forEach operation for example) and you need to remove
  108. * something in the map without causing a deadlock by taking the writeLock before the readLock is unlocked.
  109. */
  110. public V unsynchronizedRemove(int key)
  111. {
  112. return super.remove(key);
  113. }
  114. public boolean equals(Object other)
  115. {
  116. _readLock.lock();
  117. try
  118. {
  119. return super.equals(other);
  120. }
  121. finally
  122. {
  123. _readLock.unlock();
  124. }
  125. }
  126. public Object[] getValues()
  127. {
  128. _readLock.lock();
  129. try
  130. {
  131. return super.getValues();
  132. }
  133. finally
  134. {
  135. _readLock.unlock();
  136. }
  137. }
  138. public <T> T[] getValues(T[] arg0)
  139. {
  140. _readLock.lock();
  141. try
  142. {
  143. return super.getValues(arg0);
  144. }
  145. finally
  146. {
  147. _readLock.unlock();
  148. }
  149. }
  150. public int[] keys()
  151. {
  152. _readLock.lock();
  153. try
  154. {
  155. return super.keys();
  156. }
  157. finally
  158. {
  159. _readLock.unlock();
  160. }
  161. }
  162. public int[] keys(int[] arg0)
  163. {
  164. _readLock.lock();
  165. try
  166. {
  167. return super.keys(arg0);
  168. }
  169. finally
  170. {
  171. _readLock.unlock();
  172. }
  173. }
  174. public boolean contains(int val)
  175. {
  176. _readLock.lock();
  177. try
  178. {
  179. return super.contains(val);
  180. }
  181. finally
  182. {
  183. _readLock.unlock();
  184. }
  185. }
  186. public boolean containsValue(V arg0)
  187. {
  188. _readLock.lock();
  189. try
  190. {
  191. return super.containsValue(arg0);
  192. }
  193. finally
  194. {
  195. _readLock.unlock();
  196. }
  197. }
  198. public boolean containsKey(int key)
  199. {
  200. _readLock.lock();
  201. try
  202. {
  203. return super.containsKey(key);
  204. }
  205. finally
  206. {
  207. _readLock.unlock();
  208. }
  209. }
  210. public boolean forEachKey(TIntProcedure procedure)
  211. {
  212. _readLock.lock();
  213. try
  214. {
  215. return super.forEachKey(procedure);
  216. }
  217. finally
  218. {
  219. _readLock.unlock();
  220. }
  221. }
  222. /**
  223. * A safe from deadlock loop. put and remove synchronizers are disabled while this loop is running.<br>
  224. * Keep in mind that this uses writeLock instead of readLock, and its intended only if you are trying to
  225. * put/remove something while looping the values of this map.
  226. */
  227. public boolean safeForEachKey(TIntProcedure procedure)
  228. {
  229. _writeLock.lock();
  230. try
  231. {
  232. _tempWritesLockDisable = true;
  233. return super.forEachKey(procedure);
  234. }
  235. finally
  236. {
  237. _tempWritesLockDisable = false;
  238. _writeLock.unlock();
  239. }
  240. }
  241. public boolean forEachValue(TObjectProcedure<V> arg0)
  242. {
  243. _readLock.lock();
  244. try
  245. {
  246. return super.forEachValue(arg0);
  247. }
  248. finally
  249. {
  250. _readLock.unlock();
  251. }
  252. }
  253. /**
  254. * A safe from deadlock loop. put and remove synchronizers are disabled while this loop is running.<br>
  255. * Keep in mind that this uses writeLock instead of readLock, and its intended only if you are trying to
  256. * put/remove something while looping the values of this map.
  257. */
  258. public boolean safeForEachValue(TObjectProcedure<V> arg0)
  259. {
  260. _writeLock.lock();
  261. try
  262. {
  263. _tempWritesLockDisable = true;
  264. return super.forEachValue(arg0);
  265. }
  266. finally
  267. {
  268. _tempWritesLockDisable = false;
  269. _writeLock.unlock();
  270. }
  271. }
  272. public boolean forEachEntry(TIntObjectProcedure<V> arg0)
  273. {
  274. _readLock.lock();
  275. try
  276. {
  277. return super.forEachEntry(arg0);
  278. }
  279. finally
  280. {
  281. _readLock.unlock();
  282. }
  283. }
  284. /**
  285. * A safe from deadlock loop. put and remove synchronizers are disabled while this loop is running.<br>
  286. * Keep in mind that this uses writeLock instead of readLock, and its intended only if you are trying to
  287. * put/remove something while looping the values of this map.
  288. */
  289. public boolean safeForEachEntry(TIntObjectProcedure<V> arg0)
  290. {
  291. _writeLock.lock();
  292. try
  293. {
  294. _tempWritesLockDisable = true;
  295. return super.forEachEntry(arg0);
  296. }
  297. finally
  298. {
  299. _tempWritesLockDisable = false;
  300. _writeLock.unlock();
  301. }
  302. }
  303. public boolean retainEntries(TIntObjectProcedure<V> arg0)
  304. {
  305. _writeLock.lock();
  306. try
  307. {
  308. return super.retainEntries(arg0);
  309. }
  310. finally
  311. {
  312. _writeLock.unlock();
  313. }
  314. }
  315. public void transformValues(TObjectFunction<V,V> arg0)
  316. {
  317. _writeLock.lock();
  318. try
  319. {
  320. super.transformValues(arg0);
  321. }
  322. finally
  323. {
  324. _writeLock.unlock();
  325. }
  326. }
  327. }