2 +----------------------------------------------------------------------+
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_ROOT_MAP_H_
18 #define incl_HPHP_ROOT_MAP_H_
20 #include "hphp/runtime/base/req-containers.h"
21 #include "hphp/runtime/base/req-ptr.h"
26 * RootMap wraps a simple id->object hashtable, useful for extensions
27 * that need pass 'handles' to objects or resources into 3rd party apis
28 * masked as integers or void* pointers. The map is intended to be a
29 * field of a thread local, where it will be automatically scanned by
30 * the gc, and must be reset() between requests.
32 template<class T
> struct RootMap
{
33 using RootId
= uintptr_t;
34 using Map
= req::hash_map
<RootId
,req::ptr
<T
>>;
36 RootId
addRoot(req::ptr
<T
>&& ptr
) {
38 const RootId tok
= ptr
->getId();
39 getMap().emplace(tok
, std::move(ptr
));
43 RootId
addRoot(const req::ptr
<T
>& ptr
) {
45 auto tok
= ptr
->getId();
48 static_assert(sizeof(tok
) <= sizeof(RootId
), "");
51 req::ptr
<T
> lookupRoot(const void* vp
) const {
52 return lookupRoot(reinterpret_cast<RootId
>(vp
));
55 req::ptr
<T
> lookupRoot(RootId tok
) const {
56 if (!m_map
) return nullptr;
58 auto it
= map
.find(tok
);
59 return it
!= map
.end() ? unsafe_cast_or_null
<T
>(it
->second
) : nullptr;
62 req::ptr
<T
> removeRoot(RootId tok
) {
64 auto it
= m_map
->find(tok
);
65 if (it
!= m_map
->end()) {
66 auto ptr
= std::move(it
->second
);
68 return unsafe_cast_or_null
<T
>(ptr
);
74 req::ptr
<T
> removeRoot(const void* vp
) {
75 return removeRoot(reinterpret_cast<RootId
>(vp
));
78 bool removeRoot(const req::ptr
<T
>& ptr
) {
79 return removeRoot(ptr
->getId()) != nullptr;
82 bool removeRoot(const T
* ptr
) {
83 return removeRoot(ptr
->getId()) != nullptr;
92 if (UNLIKELY(!m_map
)) {
93 m_map
= req::make_raw
<Map
>();