Atomically assign and set persistent rds handles
[hiphop-php.git] / hphp / runtime / base / enum-cache.h
blob35d78cdcb9a4b38aa39ecf70cb078266a2305175
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present 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 +----------------------------------------------------------------------+
17 #ifndef incl_HPHP_ENUM_CACHE_H_
18 #define incl_HPHP_ENUM_CACHE_H_
20 #include "hphp/runtime/ext/extension.h"
21 #include "hphp/runtime/vm/class.h"
22 #include <tbb/concurrent_hash_map.h>
24 namespace HPHP {
26 //////////////////////////////////////////////////////////////////////
28 // Values in the TBB map that contain the enum static arrays
29 struct EnumValues {
30 // array from 'enum name' to 'enum value'
31 // e.g. [ 'RED' => 1, 'BLUE' =>2, ...]
32 Array values;
33 // array from 'enum value' to 'enum name'
34 // e.g. [ 1 => 'RED', 2 => 'BLUE', ...]
35 Array names;
38 struct EnumCache {
39 EnumCache() {}
40 ~EnumCache();
42 // TBB hash and compare struct
43 struct clsCompare {
44 bool equal(intptr_t key1, intptr_t key2) const {
45 assert(key1 && key2);
46 bool equal = (key1 == key2);
47 assert(!equal || getClass(key1)->name()->equal(getClass(key2)->name()));
48 return equal;
51 size_t hash(intptr_t key) const {
52 assert(key);
53 return static_cast<size_t>(hash_int64(key));
57 // if the class provided derives from Enum the name/value and value/name
58 // arrays are build, stored in the cache and returned.
59 // If not an error is raised.
60 // If the recurse flag is 'true' array values are loaded up the hierarchy
61 // chain (if any).
62 static const EnumValues* getValues(const Class* klass, bool recurse);
63 // Like above, but for first-class enums
64 static const EnumValues* getValuesBuiltin(const Class* klass);
65 // delete the EnumValues element in the cache for the given class.
66 // If there is no entry this function is a no-op.
67 static void deleteValues(const Class* klass);
69 // Helper that raises a PHP exception
70 [[noreturn]] static void failLookup(const Variant& msg);
72 private:
73 // Class* to intptr_ti key helpers
74 const static intptr_t RECURSE_MASK = 1;
75 static const Class* getClass(intptr_t key) {
76 return reinterpret_cast<const Class*>(key & ~RECURSE_MASK);
79 static intptr_t getKey(const Class* klass, bool recurse) {
80 intptr_t key = reinterpret_cast<intptr_t>(klass);
81 return (recurse) ? key | RECURSE_MASK : key;
84 const EnumValues* cachePersistentEnumValues(
85 const Class* klass,
86 bool recurse,
87 Array&& names,
88 Array&& values);
90 const EnumValues* cacheRequestEnumValues(
91 const Class* klass,
92 bool recurse,
93 Array&& names,
94 Array&& values);
96 const EnumValues* getEnumValuesIfDefined(intptr_t key,
97 bool checkLocal = true) const;
98 const EnumValues* getEnumValues(const Class* klass, bool recurse);
99 const EnumValues* loadEnumValues(const Class* klass, bool recurse);
100 void deleteEnumValues(intptr_t key);
102 // Map that contains associations between Enum classes and their array
103 // values and array names.
104 using EnumValuesMap = tbb::concurrent_hash_map<
105 intptr_t,
106 const EnumValues*,
107 clsCompare>;
109 using ReqEnumValuesMap = req::hash_map<
110 intptr_t,
111 const EnumValues*>;
113 // Persistent values, recursive case. Non-recursive are cached in Class.
114 EnumValuesMap m_enumValuesMap;
116 rds::Link<ReqEnumValuesMap*,true /* normal_only */>
117 m_nonScalarEnumValuesMap{rds::kUninitHandle};
120 //////////////////////////////////////////////////////////////////////
124 #endif