Rename files in runtime/base, part 6
[hiphop-php.git] / hphp / runtime / base / resource-data.h
blob333a3c63ec92c0be020a954052daefbf249b0c99
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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"
23 namespace HPHP {
24 ///////////////////////////////////////////////////////////////////////////////
26 /**
27 * Base class of all PHP resources.
29 class ResourceData {
30 public:
31 static const bool IsResourceClass = true;
32 private:
33 static DECLARE_THREAD_LOCAL_NO_CHECK(int, os_max_resource_id);
35 public:
36 ResourceData();
38 private:
39 // Disallow copy construction
40 ResourceData(const ResourceData&) = delete;
42 public:
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); }
51 void release() {
52 assert(getCount() == 0);
53 delete this;
56 Class* getVMClass() const {
57 return m_cls;
60 static size_t getVMClassOffset() {
61 // For assembly linkage.
62 size_t res = offsetof(ResourceData, m_cls);
63 assert(res == ObjectData::getVMClassOffset());
64 return res;
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;
86 void dump() const;
88 private:
89 static void compileTimeAssertions() {
90 static_assert(offsetof(ResourceData, m_count) == FAST_REFCOUNT_OFFSET, "");
93 //============================================================================
94 // ResourceData fields
96 protected:
97 // Numeric identifier of resource object (used by var_dump() and other
98 // output functions)
99 int32_t o_id;
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
106 // resources
107 Class* m_cls;
108 // Storage for dynamic properties
109 ArrNR o_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 {
120 * public:
121 * int number; // primitives are allocated together with "this"
122 * String str; // smart-allocated objects are fine
123 * };
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 {
137 * public:
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
142 * };
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
163 * smart allocated.
165 * class MixedSmartAllocated : public SweepableResourceData {
166 * public:
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);
177 * };
178 * IMPLEMENT_OBJECT_ALLOCATION_NO_DEFAULT_SWEEP(T);
179 * void MixedSmartAllocated::sweep() {
180 * delete stdstr;
181 * delete vec;
182 * close_handle(ptr);
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
200 // ResourceData.
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_