2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-2013 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_RESOURCE_DATA_H_
18 #define incl_HPHP_RESOURCE_DATA_H_
20 #include "hphp/runtime/base/complex_types.h"
21 #include "hphp/runtime/base/sweepable.h"
24 ///////////////////////////////////////////////////////////////////////////////
27 * Base class of all PHP resources.
31 static const bool IsResourceClass
= true;
33 static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_resource_id
);
39 // Disallow copy construction
40 ResourceData(const ResourceData
&) = delete;
43 void setStatic() const { assert(false); }
44 bool isStatic() const { return false; }
45 IMPLEMENT_COUNTABLENF_METHODS_NO_STATIC
47 virtual ~ResourceData(); // all PHP resources need vtables
49 void operator delete(void* p
) { ::operator delete(p
); }
52 assert(getCount() == 0);
56 Class
* getVMClass() const {
60 static size_t getVMClassOffset() {
61 // For assembly linkage.
62 size_t res
= offsetof(ResourceData
, m_cls
);
63 assert(res
== ObjectData::getVMClassOffset());
67 int32_t o_getId() const { return o_id
; }
68 void o_setId(int id
); // only for BuiltinFiles
69 static int GetMaxResourceId() ATTRIBUTE_COLD
;
71 CStrRef
o_getClassName() const;
72 virtual CStrRef
o_getClassNameHook() const;
73 virtual CStrRef
o_getResourceName() const;
74 virtual bool isInvalid() const { return false; }
76 bool o_toBoolean() const { return 1; }
77 int64_t o_toInt64() const { return o_id
; }
78 double o_toDouble() const { return o_id
; }
79 String
o_toString() const {
80 return String("Resource id #") + String(o_id
);
82 Array
o_toArray() const;
84 void serialize(VariableSerializer
* serializer
) const;
85 void serializeImpl(VariableSerializer
* serializer
) const;
89 static void compileTimeAssertions() {
90 static_assert(offsetof(ResourceData
, m_count
) == FAST_REFCOUNT_OFFSET
, "");
93 //============================================================================
94 // ResourceData fields
97 // Numeric identifier of resource object (used by var_dump() and other
100 // Counter to keep track of the number of references to this resource
101 // (i.e. the resource's "refcount")
102 mutable RefCount m_count
;
103 // Pointer to the __resource class; this field is needed (and must be at
104 // the same offset as ObjectData::m_cls) so that backup gc and other things
105 // that walk the SmartAllocator heaps can distinguish between objects and
108 // Storage for dynamic properties
111 } __attribute__((aligned(16)));
114 * Rules to avoid memory problems/leaks from ResourceData classes
115 * ==============================================================
117 * 1. If a ResourceData is entirely smart allocated, for example,
119 * class EntirelySmartAllocated : public ResourceData {
121 * int number; // primitives are allocated together with "this"
122 * String str; // smart-allocated objects are fine
125 * Then, the best choice is to use these two macros to make sure the object
126 * is always collected during request shutdown time:
128 * DECLARE_OBJECT_ALLOCATION(T);
129 * IMPLEMENT_OBJECT_ALLOCATION(T);
131 * This object doesn't participate in sweep(), as object allocator doesn't
132 * have any callback installed.
134 * 2. If a ResourceData is entirely not smart allocated, for example,
136 * class NonSmartAllocated : public SweepableResourceData {
138 * int number; // primitives are always not in consideration
139 * std::string str; // this has malloc() in its own
140 * std::vector<int> vec; // all STL collection classes belong here
141 * HANDLE ptr; // raw pointers that need to be free-d somehow
144 * Then it has to derive from SweepableResourceData, so sweep() will be
145 * called. By default, it will call this object's destructor automatically,
146 * so everything will be free-d.
148 * When deriving from SweepableResourceData, either "new" or "NEW" can
149 * be used, but we prefer people use NEW with these macros:
151 * DECLARE_OBJECT_ALLOCATION(T);
152 * IMPLEMENT_OBJECT_ALLOCATION(T);
154 * 3. If a ResourceData is a mix of smart allocated data members and non-
155 * smart allocated data members, sweep() has to be overwritten to only
156 * free non-smart allocated data members. This is because smart allocated
157 * data members may have their own sweep() defined to destruct, and another
158 * destruction from this ResourceData's default sweep() will cause double-
159 * free problems on these smart allocated data members.
161 * This means, std::vector<String> is almost always wrong, because there is
162 * no way to free up vector's memory without touching String, which is
165 * class MixedSmartAllocated : public SweepableResourceData {
167 * int number; // primitives are always not in consideration
169 * // STL classes need to new/delete to have clean sweep
170 * std::string *stdstr;
171 * std::vector<int> *vec;
173 * HANDLE ptr; // raw pointers that need to be free-d somehow
174 * String str; // smart-allocated objects are fine
176 * DECLARE_OBJECT_ALLOCATION(T);
178 * IMPLEMENT_OBJECT_ALLOCATION_NO_DEFAULT_SWEEP(T);
179 * void MixedSmartAllocated::sweep() {
183 * // without doing anything with Strings, Arrays, or Objects
186 * 4. If a ResourceData may be persistent, it cannot use object allocation. It
187 * then has to derive from SweepableResourceData, because a new-ed pointer
188 * can only be collected/deleted by sweep().
191 class SweepableResourceData
: public ResourceData
, public Sweepable
{};
193 typedef std::map
<std::string
, ResourceData
*> ResourceMap
;
194 typedef std::map
<std::string
, ResourceMap
> ResourceMapMap
;
196 ///////////////////////////////////////////////////////////////////////////////
198 // Suppress the default implementation of the SmartPtr destructor so that
199 // derived classes (ex. HPHP::Resource) can manually handle decReffing the
201 template<> inline SmartPtr
<ResourceData
>::~SmartPtr() {}
203 ALWAYS_INLINE
inline void decRefRes(ResourceData
* res
) {
204 if (res
->decRefCount() == 0) res
->release();
207 ///////////////////////////////////////////////////////////////////////////////
210 #endif // incl_HPHP_RESOURCE_DATA_H_