rng_paraqueue_pool.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274
  1. //
  2. // C++ Implementation: rng_queue_pool
  3. //
  4. // Description:
  5. //
  6. //
  7. // Author: Frank Michler,,, <frank@pc13365>, (C) 2010
  8. //
  9. // Copyright: See COPYING file that comes with this distribution
  10. //
  11. //
  12. #include <iostream>
  13. #include <QSemaphore>
  14. #include <QMutex>
  15. #include <QThread>
  16. #include "rng_paraqueue_pool.hpp"
  17. #include "rngqueue.hpp"
  18. using namespace std;
  19. RngParaQueuePool::RngQueueInfo::RngQueueInfo(gsl_rng * _GslR, RngType Type, double Parameter, int NVectors, int NumbersPerVector):
  20. mGslR(_GslR), mType(Type), mParameter(Parameter), mNRndVectors(NVectors), mkNumbersPerVector(NumbersPerVector)
  21. {
  22. mRNVectorPool = vector<vector<double> >(mNRndVectors, vector<double>(mkNumbersPerVector, 0));
  23. for (int i=0; i<mNRndVectors; ++i) {
  24. mUsedNumbers.push_back(i);
  25. }
  26. // initialize random number pool with first vector
  27. int VectorNum=mUsedNumbers.front();
  28. mUsedNumbers.pop_front();
  29. switch (mType) {
  30. case kRngPoisson:
  31. for(vector<double>::iterator it=mRNVectorPool[VectorNum].begin();it!=mRNVectorPool[VectorNum].end();++it) {
  32. (*it) = gsl_ran_poisson(mGslR, mParameter);
  33. }
  34. break;
  35. default:
  36. cerr << "ERROR: not yet supported\n";
  37. break;
  38. }
  39. mLeasedNumber = VectorNum;
  40. }
  41. /** @brief returns current random number vector, only for use in getRngQueue(...)
  42. *
  43. * @return pointer to random number vector
  44. */
  45. vector<double>* RngParaQueuePool::RngQueueInfo::getCurrentRandomNumberVector()
  46. {
  47. return &(mRNVectorPool[mLeasedNumber]);
  48. }
  49. /** @brief returns current number of used random numbers, only for use in getRngQueue(...)
  50. *
  51. * @return number of used numbers
  52. */
  53. int RngParaQueuePool::RngQueueInfo::NUsedNumbers()
  54. {
  55. return mUsedNumbers.size();
  56. }
  57. vector<double>* RngParaQueuePool::RngQueueInfo::getRandomNumberVector()
  58. {
  59. if (!mSemFreshNumbers.tryAcquire()) {
  60. //cout << "-";
  61. mSemFreshNumbers.acquire();
  62. }
  63. mMutFreshNumbers.lock();
  64. int VectorNum=mFreshNumbers.front();
  65. mFreshNumbers.pop_front();
  66. mMutFreshNumbers.unlock();
  67. // cout << "f" << VectorNum << " \n";
  68. mMutUsedNumbers.lock();
  69. mUsedNumbers.push_back(mLeasedNumber);
  70. mMutUsedNumbers.unlock();
  71. // cout << "l" << mLeasedNumber << " \n";
  72. mLeasedNumber = VectorNum;
  73. return &(mRNVectorPool[VectorNum]);
  74. }
  75. bool RngParaQueuePool::RngQueueInfo::refreshRandomNumbers()
  76. {
  77. // cout << "RngParaQueuePool::refreshRandomNumbers\n";
  78. // are there used vectors? which vector should be refreshed?
  79. int VectorNum=-1;
  80. mMutUsedNumbers.lock();
  81. if (mUsedNumbers.empty()) {
  82. mMutUsedNumbers.unlock();
  83. cout << "x";
  84. return false;
  85. } else {
  86. VectorNum = mUsedNumbers.front();
  87. mUsedNumbers.pop_front();
  88. /* cout << "r" << VectorNum ;*/
  89. }
  90. mMutUsedNumbers.unlock();
  91. switch (mType) {
  92. case kRngPoisson:
  93. for(vector<double>::iterator it=mRNVectorPool[VectorNum].begin();it!=mRNVectorPool[VectorNum].end();++it) {
  94. (*it) = gsl_ran_poisson(mGslR, mParameter);
  95. }
  96. break;
  97. default:
  98. cerr << "ERROR: not yet supported\n";
  99. break;
  100. }
  101. mMutFreshNumbers.lock();
  102. mFreshNumbers.push_back(VectorNum);
  103. mMutFreshNumbers.unlock();
  104. mSemFreshNumbers.release();
  105. return true;
  106. }
  107. RngParaQueuePool::RngParaQueuePool(): mIsDead(false)
  108. {
  109. cout << "Singleton-Constructor: RngParaQueuePool::RngParaQueuePool()\n";
  110. // initialize global random generator
  111. const gsl_rng_type * T;
  112. gsl_rng_env_setup();
  113. T = gsl_rng_default;
  114. gslr = gsl_rng_alloc (T);
  115. #ifdef SEED_RNG_WITH_42
  116. unsigned long int seed = (long)(42);
  117. #else
  118. unsigned long int seed = (long)(time( NULL ));
  119. #endif
  120. gsl_rng_set(gslr, seed);
  121. }
  122. RngParaQueuePool::~RngParaQueuePool()
  123. {
  124. cout << "\n Destructor\n";
  125. mIsDead=true;
  126. mTotalUsedNumbers.release();
  127. wait();
  128. }
  129. IRngQueuePool* RngParaQueuePool::getRngQueuePool()
  130. {
  131. cout << "Singleton-Request\n";
  132. static RngParaQueuePool instanz;
  133. if (!instanz.isRunning()) {
  134. cout << "Starting random number generator thread\n";
  135. instanz.start();
  136. }
  137. return &instanz;
  138. }
  139. IRngQueue* RngParaQueuePool::getRngQueue()
  140. {
  141. return getRngQueue(kRngPoisson, 3, 10, 2000);
  142. }
  143. IRngQueue* RngParaQueuePool::getRngQueue(RngType _RType, double _Parameter, int NVectors, int NumbersPerVector)
  144. {
  145. RngQueueInfo* NewQueueInfo = new RngQueueInfo(gslr, _RType, _Parameter, NVectors, NumbersPerVector);
  146. RngQueue* NewQueue = new RngQueue(this, NewQueueInfo->getCurrentRandomNumberVector());
  147. /*
  148. mNotFullMutex.lock();
  149. mNUsedNumbers += NewQueueInfo->NUsedNumbers();
  150. mNotFullMutex.unlock();
  151. */
  152. int UsedNumbers = NewQueueInfo->NUsedNumbers();
  153. mTotalUsedNumbers.release(UsedNumbers);
  154. cout << "UsedNumbers=" << UsedNumbers << "\n";
  155. mMutQueueInfoMap.lock();
  156. mQueueInfoMap[NewQueue] = NewQueueInfo;
  157. mMutQueueInfoMap.unlock();
  158. // mNotFull.wakeAll();
  159. return NewQueue;
  160. }
  161. vector<double>* RngParaQueuePool::getRandomNumberVector(IRngQueue* _RngQueue)
  162. {
  163. IterQueInfoMap it = mQueueInfoMap.find(_RngQueue);
  164. if (it!=mQueueInfoMap.end()) {
  165. vector<double>* RandomVect = (*it).second->getRandomNumberVector();
  166. mTotalUsedNumbers.release();
  167. /* mNotFullMutex.lock();
  168. ++mNUsedNumbers;
  169. cout << "'" << mNUsedNumbers ;
  170. mNotFullMutex.unlock();
  171. mNotFull.wakeAll();*/
  172. return RandomVect;
  173. }
  174. cout << "RngParaQueuePool::getRandomNumberVector failed\n";
  175. return 0;
  176. }
  177. /** release RngQueue, is called in destructor of RngQueue
  178. *
  179. * clean up housekeeping information for RngQueue
  180. *
  181. * @param _RngQueue pointer Random Number Queue object
  182. */
  183. void RngParaQueuePool::releaseRngQueue(IRngQueue* _RngQueue)
  184. {
  185. /**
  186. @todo test this
  187. */
  188. IterQueInfoMap it = mQueueInfoMap.find(_RngQueue);
  189. if (it!=mQueueInfoMap.end()) {
  190. mTotalUsedNumbers.release((*it).second->NUsedNumbers());
  191. delete (*it).second;
  192. mQueueInfoMap.erase(it);
  193. }
  194. }
  195. void RngParaQueuePool::refillRNumberPool()
  196. {
  197. while (!mIsDead) {
  198. /* mNotFullMutex.lock();
  199. if (mNUsedNumbers == 0) {
  200. // cout << "\nRngQueuePool::refillRNumberPool waiting for used numbers\n";
  201. cout << "+";
  202. mNotFull.wait(&mNotFullMutex);
  203. }
  204. mNotFullMutex.unlock();
  205. */
  206. // jede Queue in der map einmal auffüllen
  207. //cout << "a" << mTotalUsedNumbers.available() << " ";
  208. mMutQueueInfoMap.lock();
  209. for (IterQueInfoMap it=mQueueInfoMap.begin(); it!= mQueueInfoMap.end();++it) {
  210. if (!mTotalUsedNumbers.tryAcquire()) {
  211. //cout << "+";
  212. mTotalUsedNumbers.acquire();
  213. }
  214. if (!(*it).second->refreshRandomNumbers()) {
  215. mTotalUsedNumbers.release();
  216. cout << "b" << mTotalUsedNumbers.available() << " ";
  217. /* mNotFullMutex.lock();
  218. --mNUsedNumbers;
  219. mNotFullMutex.unlock();
  220. cout << "|" << mNUsedNumbers;
  221. */
  222. }
  223. }
  224. mMutQueueInfoMap.unlock();
  225. }
  226. cout << "finish thread loop \n";
  227. }
  228. void RngParaQueuePool::run()
  229. {
  230. refillRNumberPool();
  231. }