More smart containers
And use them for VariableSerializer/VariableUnserializer
Esse commit está contido em:
@@ -398,6 +398,22 @@ void* smart_calloc(size_t count, size_t bytes);
|
||||
void* smart_realloc(void* ptr, size_t nbytes);
|
||||
void smart_free(void* ptr);
|
||||
|
||||
namespace smart {
|
||||
namespace do_not_use_directly {
|
||||
/*
|
||||
* We are deriving from the std::collection classes to get
|
||||
* smart::collection classes that use smart allocation.
|
||||
* To avoid the various issues involved with deriving
|
||||
* from value types, we want to make sure that there are
|
||||
* no references to std::collection<...,SmartStlAlloc<>>
|
||||
* other than the ones below. That way we know that
|
||||
* a pointer to a smart::collection can never decay
|
||||
* to a pointer to a std::collection.
|
||||
*
|
||||
* The namespace do_not_use_directly should remind us
|
||||
* of that.
|
||||
*
|
||||
*/
|
||||
template <class T>
|
||||
class SmartStlAlloc {
|
||||
public:
|
||||
@@ -460,21 +476,50 @@ bool operator!= (const SmartStlAlloc<T1>&,
|
||||
return false;
|
||||
}
|
||||
|
||||
namespace smart {
|
||||
template <class Key, class T, class Compare = std::less<Key>,
|
||||
class Alloc = HPHP::SmartStlAlloc<std::pair<const Key, T> > >
|
||||
class map : public std::map<Key, T, Compare, Alloc> {};
|
||||
|
||||
template <class T, class Alloc = HPHP::SmartStlAlloc<T> >
|
||||
class deque : public std::deque<T, Alloc> {};
|
||||
|
||||
template <class T, class Alloc = HPHP::SmartStlAlloc<T> >
|
||||
class vector : public std::vector<T, Alloc> {};
|
||||
|
||||
template <class T, class Container = deque<T> >
|
||||
class queue : public std::queue<T, Container> {};
|
||||
}
|
||||
/*
|
||||
* Derivation from value types is generally bad.
|
||||
* Here, we derive from classes that do not exist anywhere
|
||||
* else in the code base (see comments above).
|
||||
*
|
||||
* We also add no functionality to the derived class. Your
|
||||
* code will not get past code review if you try to do so.
|
||||
*/
|
||||
template <class Key, class T, class Compare = std::less<Key> >
|
||||
class map : public std::map<
|
||||
Key, T, Compare,
|
||||
do_not_use_directly::SmartStlAlloc<std::pair<const Key, T> > > {};
|
||||
|
||||
template <class T>
|
||||
class deque : public std::deque<T, do_not_use_directly::SmartStlAlloc<T> > {};
|
||||
|
||||
template <class T>
|
||||
class vector : public std::vector<T, do_not_use_directly::SmartStlAlloc<T> > {};
|
||||
|
||||
template <class T>
|
||||
class list : public std::list<T, do_not_use_directly::SmartStlAlloc<T> > {};
|
||||
|
||||
template <class T>
|
||||
class queue : public std::queue<T, deque<T> > {};
|
||||
|
||||
template <class _T, class _U,
|
||||
class _V = hphp_hash<_T>,class _W = std::equal_to<_T> >
|
||||
struct hash_map : std::tr1::unordered_map<
|
||||
_T, _U, _V, _W, do_not_use_directly::SmartStlAlloc<std::pair<_T, _U> > > {
|
||||
hash_map() : std::tr1::unordered_map<
|
||||
_T, _U, _V, _W, do_not_use_directly::SmartStlAlloc<std::pair<_T, _U> >
|
||||
>(0) {}
|
||||
};
|
||||
|
||||
template <class _T,
|
||||
class _V = hphp_hash<_T>,class _W = std::equal_to<_T> >
|
||||
struct hash_set : std::tr1::unordered_set<
|
||||
_T, _V, _W, do_not_use_directly::SmartStlAlloc<_T> > {
|
||||
hash_set() : std::tr1::unordered_set<
|
||||
_T, _V, _W, do_not_use_directly::SmartStlAlloc<_T> >(0) {}
|
||||
};
|
||||
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
}
|
||||
|
||||
|
||||
@@ -45,7 +45,7 @@ VariableSerializer::VariableSerializer(Type type, int option /* = 0 */,
|
||||
m_levelDebugger(0) {
|
||||
m_maxLevelDebugger = g_context->getDebuggerPrintLevel();
|
||||
if (type == Serialize || type == APCSerialize || type == DebuggerSerialize) {
|
||||
m_arrayIds = new PointerCounterMap();
|
||||
m_arrayIds = new SmartPtrCtrMap();
|
||||
} else {
|
||||
m_arrayIds = nullptr;
|
||||
}
|
||||
@@ -477,7 +477,7 @@ void VariableSerializer::writeOverflow(void* ptr, bool isObject /* = false */) {
|
||||
case APCSerialize:
|
||||
{
|
||||
assert(m_arrayIds);
|
||||
PointerCounterMap::const_iterator iter = m_arrayIds->find(ptr);
|
||||
SmartPtrCtrMap::const_iterator iter = m_arrayIds->find(ptr);
|
||||
assert(iter != m_arrayIds->end());
|
||||
int id = iter->second;
|
||||
if (isObject) {
|
||||
|
||||
@@ -108,12 +108,13 @@ public:
|
||||
void getResourceInfo(String &rsrcName, int &rsrcId);
|
||||
Type getType() const { return m_type; }
|
||||
private:
|
||||
typedef smart::hash_map<void*, int, pointer_hash<void> > SmartPtrCtrMap;
|
||||
Type m_type;
|
||||
int m_option; // type specific extra options
|
||||
StringBuffer *m_buf;
|
||||
int m_indent;
|
||||
PointerCounterMap m_counts; // counting seen arrays for recursive levels
|
||||
PointerCounterMap *m_arrayIds; // reference ids for objs/arrays
|
||||
SmartPtrCtrMap m_counts; // counting seen arrays for recursive levels
|
||||
SmartPtrCtrMap *m_arrayIds; // reference ids for objs/arrays
|
||||
int m_valueCount; // Current ref index
|
||||
bool m_referenced; // mark current array element as reference
|
||||
int m_refCount; // current variable's reference count
|
||||
@@ -132,7 +133,7 @@ private:
|
||||
bool first_element; // whether this is first array element
|
||||
int indent_delta; // the extra indent to serialize this object
|
||||
};
|
||||
std::vector<ArrayInfo> m_arrayInfos;
|
||||
smart::vector<ArrayInfo> m_arrayInfos;
|
||||
|
||||
void writePropertyKey(CStrRef prop);
|
||||
};
|
||||
|
||||
@@ -120,8 +120,8 @@ public:
|
||||
Type m_type;
|
||||
const char *m_buf;
|
||||
const char *m_end;
|
||||
std::vector<RefInfo> m_refs;
|
||||
std::list<Variant> m_vars;
|
||||
smart::vector<RefInfo> m_refs;
|
||||
smart::list<Variant> m_vars;
|
||||
bool m_unknownSerializable;
|
||||
|
||||
void check() {
|
||||
|
||||
Referência em uma Nova Issue
Bloquear um usuário