ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

176 lines
4.4 KiB

  1. #define CPPCMS_SOURCE
  2. #include "config.h"
  3. #include "thread_cache.h"
  4. #ifdef CPPCMS_USE_EXTERNAL_BOOST
  5. # include <boost/thread.hpp>
  6. # include <boost/format.hpp>
  7. #else // Internal Boost
  8. # include <cppcms_boost/thread.hpp>
  9. # include <cppcms_boost/format.hpp>
  10. namespace boost = cppcms_boost;
  11. #endif
  12. using namespace std;
  13. namespace cppcms {
  14. namespace impl {
  15. class thread_cache : public base_cache {
  16. boost::mutex lru_mutex;
  17. boost::shared_mutex access_lock;
  18. struct container {
  19. string data;
  20. typedef std::map<string,container>::iterator pointer;
  21. list<pointer>::iterator lru;
  22. list<multimap<string,pointer>::iterator> triggers;
  23. multimap<time_t,pointer>::iterator timeout;
  24. };
  25. typedef container::pointer pointer;
  26. std::map<string,container> primary;
  27. multimap<string,pointer> triggers;
  28. typedef multimap<string,pointer>::iterator triggers_ptr;
  29. multimap<time_t,pointer> timeout;
  30. typedef multimap<time_t,pointer>::iterator timeout_ptr;
  31. list<pointer> lru;
  32. typedef list<pointer>::iterator lru_ptr;
  33. unsigned limit;
  34. string const *get(string const &key,set<string> *triggers);
  35. void delete_node(pointer p);
  36. public:
  37. thread_cache(unsigned pages=0) : limit(pages) {}
  38. void set_size(unsigned l) { limit=l; };
  39. virtual bool fetch(string const &key,string &a,std::set<std::string> *tags);
  40. virtual void rise(string const &trigger);
  41. virtual void clear();
  42. virtual void stats(unsigned &keys,unsigned &triggers);
  43. virtual void store(string const &key,std::string const &a,set<string> const &triggers,time_t timeout);
  44. virtual ~thread_cache();
  45. }; // thread cache
  46. thread_cache::~thread_cache()
  47. {
  48. }
  49. std::string const *thread_cache::get(string const &key,set<string> *triggers)
  50. {
  51. pointer p;
  52. time_t now;
  53. time(&now);
  54. if((p=primary.find(key))==primary.end() || p->second.timeout->first < now) {
  55. return NULL;
  56. }
  57. if(triggers) {
  58. list<triggers_ptr>::iterator tp;
  59. for(tp=p->second.triggers.begin();tp!=p->second.triggers.end();tp++) {
  60. triggers->insert((*tp)->first);
  61. }
  62. }
  63. {
  64. boost::unique_lock<boost::mutex> lock(lru_mutex);
  65. lru.erase(p->second.lru);
  66. lru.push_front(p);
  67. p->second.lru=lru.begin();
  68. }
  69. return &(p->second.data);
  70. }
  71. bool thread_cache::fetch(string const &key,std::string &a,set<string> *tags)
  72. {
  73. boost::shared_lock<boost::shared_mutex> lock(access_lock);
  74. string const *r=get(key,tags);
  75. if(!r) return false;
  76. a = *r;
  77. return true;
  78. }
  79. void thread_cache::clear()
  80. {
  81. boost::unique_lock<boost::shared_mutex> lock(access_lock);
  82. timeout.clear();
  83. lru.clear();
  84. primary.clear();
  85. triggers.clear();
  86. }
  87. void thread_cache::stats(unsigned &keys,unsigned &triggers)
  88. {
  89. boost::shared_lock<boost::shared_mutex> lock(access_lock);
  90. keys=primary.size();
  91. triggers=this->triggers.size();
  92. }
  93. void thread_cache::rise(string const &trigger)
  94. {
  95. boost::unique_lock<boost::shared_mutex> lock(access_lock);
  96. pair<triggers_ptr,triggers_ptr> range=triggers.equal_range(trigger);
  97. triggers_ptr p;
  98. list<pointer> kill_list;
  99. for(p=range.first;p!=range.second;p++) {
  100. kill_list.push_back(p->second);
  101. }
  102. list<pointer>::iterator lptr;
  103. for(lptr=kill_list.begin();lptr!=kill_list.end();lptr++) {
  104. delete_node(*lptr);
  105. }
  106. }
  107. void thread_cache::store(string const &key,std::string const &a,set<string> const &triggers_in,time_t timeout_in)
  108. {
  109. boost::unique_lock<boost::shared_mutex> lock(access_lock);
  110. pointer main;
  111. main=primary.find(key);
  112. if(main==primary.end() && primary.size()>=limit && limit>0) {
  113. time_t now;
  114. time(&now);
  115. if(timeout.begin()->first<now) {
  116. main=timeout.begin()->second;
  117. }
  118. else {
  119. main=lru.back();
  120. }
  121. }
  122. if(main!=primary.end())
  123. delete_node(main);
  124. pair<pointer,bool> res=primary.insert(pair<string,container>(key,container()));
  125. main=res.first;
  126. container &cont=main->second;
  127. cont.data=a;
  128. lru.push_front(main);
  129. cont.lru=lru.begin();
  130. cont.timeout=timeout.insert(pair<time_t,pointer>(timeout_in,main));
  131. if(triggers_in.find(key)==triggers_in.end()){
  132. cont.triggers.push_back(triggers.insert(pair<string,pointer>(key,main)));
  133. }
  134. set<string>::const_iterator si;
  135. for(si=triggers_in.begin();si!=triggers_in.end();si++) {
  136. cont.triggers.push_back(triggers.insert(pair<string,pointer>(*si,main)));
  137. }
  138. }
  139. void thread_cache::delete_node(pointer p)
  140. {
  141. lru.erase(p->second.lru);
  142. timeout.erase(p->second.timeout);
  143. list<triggers_ptr>::iterator i;
  144. for(i=p->second.triggers.begin();i!=p->second.triggers.end();i++) {
  145. triggers.erase(*i);
  146. }
  147. primary.erase(p);
  148. }
  149. intrusive_ptr<base_cache> thread_cache_factory(unsigned items)
  150. {
  151. return new thread_cache(items);
  152. }
  153. } // impl
  154. } // cppcms