PageRenderTime 36ms CodeModel.GetById 6ms RepoModel.GetById 0ms app.codeStats 0ms

/src/runtime/base/shared/process_shared_variant.cpp

https://github.com/zsj888/hiphop-php
C++ | 363 lines | 320 code | 23 blank | 20 comment | 34 complexity | 99f7e6ecc2b0547bfc416e5144eeacc2 MD5 | raw file
  1. /*
  2. +----------------------------------------------------------------------+
  3. | HipHop for PHP |
  4. +----------------------------------------------------------------------+
  5. | Copyright (c) 2010 Facebook, Inc. (http://www.facebook.com) |
  6. +----------------------------------------------------------------------+
  7. | This source file is subject to version 3.01 of the PHP license, |
  8. | that is bundled with this package in the file LICENSE, and is |
  9. | available through the world-wide-web at the following url: |
  10. | http://www.php.net/license/3_01.txt |
  11. | If you did not receive a copy of the PHP license and are unable to |
  12. | obtain it through the world-wide-web, please send a note to |
  13. | license@php.net so we can mail you a copy immediately. |
  14. +----------------------------------------------------------------------+
  15. */
  16. #include <runtime/base/shared/process_shared_variant.h>
  17. #include <runtime/ext/ext_variable.h>
  18. #include <runtime/base/shared/shared_map.h>
  19. #include <runtime/base/runtime_option.h>
  20. using namespace std;
  21. namespace HPHP {
  22. ///////////////////////////////////////////////////////////////////////////////
  23. ProcessSharedVariant::ProcessSharedVariant(SharedMemoryString& source) {
  24. m_lock = putPtr((ProcessSharedVariantLock*)NULL);
  25. m_type = KindOfString;
  26. m_data.str = putPtr(&source);
  27. }
  28. ProcessSharedVariant::ProcessSharedVariant(CVarRef source,
  29. ProcessSharedVariantLock* lock)
  30. : m_lock(putPtr(lock)) {
  31. switch (source.getType()) {
  32. case KindOfBoolean:
  33. {
  34. m_type = KindOfBoolean;
  35. m_data.num = source.toBoolean();
  36. break;
  37. }
  38. case KindOfByte:
  39. case KindOfInt16:
  40. case KindOfInt32:
  41. case KindOfInt64:
  42. {
  43. m_type = KindOfInt64;
  44. m_data.num = source.toInt64();
  45. break;
  46. }
  47. case KindOfDouble:
  48. {
  49. m_type = KindOfDouble;
  50. m_data.dbl = source.toDouble();
  51. break;
  52. }
  53. case LiteralString:
  54. case KindOfStaticString:
  55. case KindOfString:
  56. {
  57. String s = source.toString();
  58. m_type = KindOfString;
  59. if (lock) {
  60. m_data.str = putPtr(SharedMemoryManager::GetSegment()
  61. ->construct<SharedMemoryString>
  62. (boost::interprocess::anonymous_instance)
  63. (s.data(), s.size()));
  64. } else {
  65. // Just need this string to live long enough for the key lookup so
  66. // don't store in shared memory.
  67. m_data.str = putPtr(new SharedMemoryString(s.data(), s.size()));
  68. }
  69. break;
  70. }
  71. case KindOfArray:
  72. {
  73. ASSERT(lock);
  74. m_type = KindOfArray;
  75. ArrayData *arr = source.getArrayData();
  76. PointerSet seen;
  77. if (arr->hasInternalReference(seen)) {
  78. m_serializedArray = true;
  79. m_shouldCache = true;
  80. String s = f_serialize(source);
  81. m_data.str = putPtr(SharedMemoryManager::GetSegment()
  82. ->construct<SharedMemoryString>
  83. (boost::interprocess::anonymous_instance)
  84. (s.data(), s.size()));
  85. break;
  86. }
  87. uint i = 0;
  88. ProcessSharedVariantMapData* mapData = SharedMemoryManager::GetSegment()
  89. ->construct<ProcessSharedVariantMapData>
  90. (boost::interprocess::anonymous_instance)();
  91. m_data.map = putPtr(mapData);
  92. ProcessSharedVariantToIntMap* map = SharedMemoryManager::GetSegment()
  93. ->construct<ProcessSharedVariantToIntMap>
  94. (boost::interprocess::anonymous_instance)();
  95. mapData->map = putPtr(map);
  96. SharedMemoryVector<SharedVariant*>* keys =
  97. SharedMemoryManager::GetSegment()
  98. ->construct<SharedMemoryVector<SharedVariant*> >
  99. (boost::interprocess::anonymous_instance)();
  100. mapData->keys = putPtr(keys);
  101. SharedMemoryVector<SharedVariant*>* vals =
  102. SharedMemoryManager::GetSegment()
  103. ->construct<SharedMemoryVector<SharedVariant*> >
  104. (boost::interprocess::anonymous_instance)();
  105. mapData->vals = putPtr(vals);
  106. for (ArrayIterPtr it = source.begin(); !it->end(); it->next()) {
  107. ProcessSharedVariant* key = SharedMemoryManager::GetSegment()
  108. ->construct<ProcessSharedVariant>
  109. (boost::interprocess::anonymous_instance)
  110. (it->first(), getLock());
  111. ProcessSharedVariant* val = SharedMemoryManager::GetSegment()
  112. ->construct<ProcessSharedVariant>
  113. (boost::interprocess::anonymous_instance)
  114. (it->second(), getLock());
  115. if (val->shouldCache()) m_shouldCache = true;
  116. (*map)[key] = i++;
  117. keys->push_back(putPtr(key));
  118. vals->push_back(putPtr(val));
  119. }
  120. break;
  121. }
  122. default:
  123. {
  124. m_type = KindOfObject;
  125. m_shouldCache = true;
  126. String s = f_serialize(source);
  127. m_data.str = putPtr(SharedMemoryManager::GetSegment()
  128. ->construct<SharedMemoryString>
  129. (boost::interprocess::anonymous_instance)
  130. (s.data(), s.size()));
  131. break;
  132. }
  133. }
  134. }
  135. Variant ProcessSharedVariant::toLocal() {
  136. ASSERT(getLock());
  137. switch (m_type) {
  138. case KindOfBoolean:
  139. {
  140. return (bool)m_data.num;
  141. }
  142. case KindOfInt64:
  143. {
  144. return m_data.num;
  145. }
  146. case KindOfDouble:
  147. {
  148. return m_data.dbl;
  149. }
  150. case KindOfString:
  151. {
  152. return NEW(StringData)(this);
  153. }
  154. case KindOfArray:
  155. {
  156. if (m_serializedArray) {
  157. return f_unserialize(String(m_data.str->data(), m_data.str->size(),
  158. AttachLiteral));
  159. }
  160. return NEW(SharedMap)(this);
  161. }
  162. default:
  163. {
  164. ASSERT(m_type == KindOfObject);
  165. SharedMemoryString* s = getString();
  166. return f_unserialize(String(s->c_str(), s->size(), AttachLiteral));
  167. }
  168. }
  169. }
  170. void ProcessSharedVariant::dump(std::string &out) {
  171. out += "ref(";
  172. out += boost::lexical_cast<string>(m_ref);
  173. out += ") ";
  174. switch (m_type) {
  175. case KindOfBoolean:
  176. out += "boolean: ";
  177. out += m_data.num ? "true" : "false";
  178. break;
  179. case KindOfInt64:
  180. out += "int: ";
  181. out += boost::lexical_cast<string>(m_data.num);
  182. break;
  183. case KindOfDouble:
  184. out += "double: ";
  185. out += boost::lexical_cast<string>(m_data.dbl);
  186. break;
  187. case KindOfString:
  188. out += "string(";
  189. out += boost::lexical_cast<string>(stringLength());
  190. out += "): ";
  191. out += stringData();
  192. break;
  193. case KindOfArray:
  194. if (m_serializedArray) {
  195. out += "array: ";
  196. out += getString()->c_str();
  197. } else {
  198. incRef();
  199. SharedMap(this).dump(out);
  200. }
  201. break;
  202. default:
  203. out += "object: ";
  204. out += getString()->c_str();
  205. break;
  206. }
  207. out += "\n";
  208. }
  209. ProcessSharedVariant::~ProcessSharedVariant() {
  210. switch (m_type) {
  211. case KindOfString:
  212. case KindOfObject:
  213. {
  214. if (getLock()) {
  215. SharedMemoryManager::GetSegment()->destroy_ptr(getString());
  216. }
  217. }
  218. break;
  219. case KindOfArray:
  220. {
  221. if (m_serializedArray) {
  222. if (getLock()) {
  223. SharedMemoryManager::GetSegment()->destroy_ptr(getString());
  224. }
  225. break;
  226. }
  227. ASSERT(getLock());
  228. BOOST_FOREACH(SharedVariant* v, keys()) {
  229. getPtr(v)->decRef();
  230. }
  231. BOOST_FOREACH(SharedVariant* v, vals()) {
  232. getPtr(v)->decRef();
  233. }
  234. SharedMemoryManager::GetSegment()->destroy_ptr(&map());
  235. SharedMemoryManager::GetSegment()->destroy_ptr(&keys());
  236. SharedMemoryManager::GetSegment()->destroy_ptr(&vals());
  237. SharedMemoryManager::GetSegment()->destroy_ptr(getMapData());
  238. }
  239. break;
  240. default:
  241. break;
  242. }
  243. }
  244. void ProcessSharedVariant::loadElems(ArrayData *&elems,
  245. const SharedMap &sharedMap,
  246. bool keepRef /* = false */) {
  247. ASSERT(is(KindOfArray));
  248. const SharedMemoryVector<SharedVariant*>& ks = keys();
  249. uint count = ks.size();
  250. ArrayInit ai(count, false, keepRef);
  251. for (uint i = 0; i < count; i++) {
  252. SharedVariant *k = getPtr(ks[i]);
  253. ai.set(i, k->toLocal(), sharedMap.getValue(i), -1, true);
  254. }
  255. elems = ai.create();
  256. if (elems->isStatic()) elems = elems->copy();
  257. }
  258. ProcessSharedVariantToIntMap::const_iterator
  259. ProcessSharedVariant::lookup(CVarRef key) {
  260. ProcessSharedVariantToIntMap::const_iterator it;
  261. if (key.isString()) {
  262. SharedMemoryString ks;
  263. if (key.is(KindOfString) || key.is(KindOfStaticString)) {
  264. StringData* sd = key.getStringData();
  265. ks = SharedMemoryString(sd->data(), sd->size());
  266. } else {
  267. ks = SharedMemoryString(key.getLiteralString());
  268. }
  269. ProcessSharedVariant svk(ks);
  270. it = map().find(&svk);
  271. } else {
  272. ProcessSharedVariant svk(key, NULL);
  273. it = map().find(&svk);
  274. }
  275. return it;
  276. }
  277. void ProcessSharedVariant::incRef() {
  278. getLock()->lock();
  279. ++m_ref;
  280. getLock()->unlock();
  281. }
  282. void ProcessSharedVariant::decRef() {
  283. ASSERT(m_ref);
  284. getLock()->lock();
  285. --m_ref;
  286. if (m_ref == 0) {
  287. getLock()->unlock();
  288. SharedMemoryManager::GetSegment()->destroy_ptr(this);
  289. } else {
  290. getLock()->unlock();
  291. }
  292. }
  293. bool ProcessSharedVariant::operator<(const SharedVariant& svother) const {
  294. ProcessSharedVariant const * other =
  295. dynamic_cast<ProcessSharedVariant const *>(&svother);
  296. ASSERT(other);
  297. if (m_type != other->m_type) {
  298. return m_type < other->m_type;
  299. }
  300. switch (m_type) {
  301. case KindOfInt64: return m_data.num < other->m_data.num;
  302. case KindOfString: return *getString() < *other->getString();
  303. default:
  304. break;
  305. }
  306. // No other types are legitimate keys
  307. ASSERT(false);
  308. return false;
  309. }
  310. int ProcessSharedVariant::getIndex(CVarRef key) {
  311. ASSERT(is(KindOfArray));
  312. ProcessSharedVariantToIntMap::const_iterator it = lookup(key);
  313. if (it == map().end()) {
  314. return -1;
  315. }
  316. return it->second;
  317. }
  318. SharedVariant* ProcessSharedVariant::get(CVarRef key) {
  319. int idx = getIndex(key);
  320. if (idx != -1) {
  321. return getPtr(vals()[idx]);
  322. }
  323. return NULL;
  324. }
  325. bool ProcessSharedVariant::exists(CVarRef key) {
  326. ASSERT(is(KindOfArray));
  327. ProcessSharedVariantToIntMap::const_iterator it = lookup(key);
  328. return it != map().end();
  329. }
  330. Variant ProcessSharedVariant::getKey(ssize_t pos) const {
  331. return getPtr(keys()[pos])->toLocal();
  332. }
  333. SharedVariant* ProcessSharedVariant::getKeySV(ssize_t pos) const {
  334. return getPtr(keys()[pos]);
  335. }
  336. SharedVariant* ProcessSharedVariant::getValue(ssize_t pos) const {
  337. return getPtr(vals()[pos]);
  338. }
  339. ///////////////////////////////////////////////////////////////////////////////
  340. }