Add some unique_ptr-related support to smart:: containers

- smart::make_unique, returns a unique pointer to smart allocated
    data.

  - Support forwarding in our allocator's construct, so
    smart::vector<foo::unique_ptr<>> works.

  - Move smart containers to their own header.
Esse commit está contido em:
Jordan DeLong
2013-05-31 21:06:03 -07:00
commit de Sara Golemon
commit 0a18064197
15 arquivos alterados com 215 adições e 137 exclusões
+3 -131
Ver Arquivo
@@ -18,6 +18,9 @@
#define incl_HPHP_MEMORY_MANAGER_H_
#include <boost/noncopyable.hpp>
#include "folly/Memory.h"
#include "hphp/util/thread_local.h"
#include "hphp/runtime/base/memory/memory_usage_stats.h"
@@ -395,137 +398,6 @@ 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:
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template <class U>
struct rebind {
typedef SmartStlAlloc<U> other;
};
pointer address (reference value) const {
return &value;
}
const_pointer address (const_reference value) const {
return &value;
}
SmartStlAlloc() throw() {}
SmartStlAlloc(const SmartStlAlloc&) {}
template <class U>
SmartStlAlloc (const SmartStlAlloc<U>&) {}
~SmartStlAlloc() {}
size_type max_size () const {
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
pointer allocate (size_type num, const void* = 0) {
pointer ret = (pointer)smart_malloc(num * sizeof(T));
return ret;
}
void construct (pointer p, const T& value) {
new ((void*)p) T(value);
}
void construct (pointer p) {
new ((void*)p) T();
}
void destroy (pointer p) {
p->~T();
}
void deallocate (pointer p, size_type num) {
smart_free(p);
}
};
template <class T1, class T2>
bool operator== (const SmartStlAlloc<T1>&,
const SmartStlAlloc<T2>&) {
return true;
}
template <class T1, class T2>
bool operator!= (const SmartStlAlloc<T1>&,
const SmartStlAlloc<T2>&) {
return false;
}
}
/*
* 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> > {
typedef std::vector<T, do_not_use_directly::SmartStlAlloc<T> > Base_;
public:
template <typename... A>
explicit vector(A &&... args) : Base_(std::forward<A>(args)...) {}
};
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) {}
};
}
///////////////////////////////////////////////////////////////////////////////
}
+198
Ver Arquivo
@@ -0,0 +1,198 @@
/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010- Facebook, Inc. (http://www.facebook.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
| available through the world-wide-web at the following url: |
| http://www.php.net/license/3_01.txt |
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#ifndef incl_HPHP_RUNTIME_BASE_MEMORY_SMART_CONTAINERS_H_
#define incl_HPHP_RUNTIME_BASE_MEMORY_SMART_CONTAINERS_H_
#include "hphp/runtime/base/memory/memory_manager.h"
namespace HPHP { namespace smart {
//////////////////////////////////////////////////////////////////////
/*
* Defines a family of types similar to std:: collections and
* pointers, except using the request-local allocator, which we
* consider smart.
*
* Replace std:: with smart:: if you know the data is request-local.
*
* You can also use smart::Allocator as a model of folly's
* SimpleAllocator where appropriate.
*/
//////////////////////////////////////////////////////////////////////
// STL-style allocator for the smart allocator. (Unfortunately we
// can't use allocator_traits yet.)
template <class T>
struct Allocator {
typedef T value_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;
template <class U>
struct rebind {
typedef Allocator<U> other;
};
pointer address(reference value) const {
return &value;
}
const_pointer address(const_reference value) const {
return &value;
}
Allocator() noexcept {}
Allocator(const Allocator&) noexcept {}
template<class U> Allocator(const Allocator<U>&) noexcept {}
~Allocator() noexcept {}
size_type max_size() const {
return std::numeric_limits<std::size_t>::max() / sizeof(T);
}
pointer allocate(size_type num, const void* = 0) {
pointer ret = (pointer)smart_malloc(num * sizeof(T));
return ret;
}
template<class... Args>
void construct(pointer p, Args&&... args) {
new ((void*)p) T(std::forward<Args>(args)...);
}
void destroy(pointer p) {
p->~T();
}
void deallocate(pointer p, size_type num) {
smart_free(p);
}
template<class U> bool operator==(const Allocator<U>&) const {
return true;
}
template<class U> bool operator!=(const Allocator<U>&) const {
return false;
}
};
/*
* Shorthand to create a std::unique_ptr to a smart-allocated object.
*
* Usage:
*
* auto ptr = smart::make_unique<Foo>(arg1, arg2);
*
* If you need to make a typedef to one, since we don't have type
* aliases yet in our version of gcc you have to do:
*
* typedef smart::unique_ptr<T>::type type;
*/
template<class T> struct unique_ptr
: folly::AllocatorUniquePtr<T,Allocator<T>>
{};
template<class T, class... Args>
typename unique_ptr<T>::type make_unique(Args&&... args) {
return folly::allocate_unique<T>(
Allocator<T>(),
std::forward<Args>(args)...
);
}
static_assert(
sizeof(unique_ptr<int>::type) == sizeof(std::unique_ptr<int>),
"smart::unique_ptr pointer should not be larger than std::unique_ptr"
);
/*
* 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 the base classes here
* 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.
*
* Derivation from value types is generally bad. We also add no
* functionality to the derived class. Your code will not get past
* code review if you try to do so.
*
* When we upgrade compilers we can change these to C++11 type
* aliases.
*/
template <class Key, class T, class Compare = std::less<Key>>
class map : public std::map<
Key, T, Compare,
Allocator<std::pair<const Key,T>>
> {};
template <class T>
class deque : public std::deque<T,Allocator<T>> {};
template <class T>
class vector : public std::vector<T,Allocator<T>> {
typedef std::vector<T,Allocator<T>> Base;
public:
template <class... A>
explicit vector(A &&... args) : Base(std::forward<A>(args)...) {}
};
template <class T>
class list : public std::list<T,Allocator<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,
Allocator<std::pair<T,U>>
> {
hash_map()
: std::tr1::unordered_map<
T, U, V, W,
Allocator<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,Allocator<T> > {
hash_set()
: std::tr1::unordered_set<T,V,W,Allocator<T>>(0)
{}
};
//////////////////////////////////////////////////////////////////////
}}
#endif
+2
Ver Arquivo
@@ -19,6 +19,7 @@
#include "hphp/runtime/base/types.h"
#include "hphp/runtime/base/util/string_buffer.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/class.h"
#include "hphp/runtime/vm/unit.h"
@@ -107,6 +108,7 @@ public:
void setResourceInfo(CStrRef rsrcName, int rsrcId);
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;
+1
Ver Arquivo
@@ -18,6 +18,7 @@
#define incl_HPHP_VARIABLE_UNSERIALIZER_H_
#include "hphp/runtime/base/types.h"
#include "hphp/runtime/base/memory/smart_containers.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
+1 -1
Ver Arquivo
@@ -14,9 +14,9 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/ext/asio/asio_context.h"
#include "hphp/runtime/ext/ext_asio.h"
#include "hphp/runtime/ext/asio/asio_context.h"
#include "hphp/runtime/ext/asio/asio_session.h"
#include "hphp/system/lib/systemlib.h"
+1
Ver Arquivo
@@ -21,6 +21,7 @@
#include <functional>
#include <queue>
#include "hphp/runtime/base/base_includes.h"
#include "hphp/runtime/base/memory/smart_containers.h"
namespace HPHP {
///////////////////////////////////////////////////////////////////////////////
@@ -15,6 +15,7 @@
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/ext/ext_asio.h"
#include "hphp/runtime/ext/asio/asio_context.h"
#include "hphp/system/lib/systemlib.h"
+1 -1
Ver Arquivo
@@ -17,7 +17,7 @@
#ifndef incl_HPHP_VM_BLOCK_H_
#define incl_HPHP_VM_BLOCK_H_
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/ir.h"
#include "hphp/runtime/vm/jit/edge.h"
#include "hphp/runtime/vm/jit/irinstruction.h"
+1 -1
Ver Arquivo
@@ -19,7 +19,7 @@
#include <boost/dynamic_bitset.hpp>
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/block.h"
#include "hphp/runtime/vm/jit/trace.h"
+1 -1
Ver Arquivo
@@ -16,7 +16,7 @@
#ifndef incl_HPHP_JIT_LAYOUT_H_
#define incl_HPHP_JIT_LAYOUT_H_
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/ir.h"
#include "hphp/runtime/vm/jit/block.h"
+1
Ver Arquivo
@@ -16,6 +16,7 @@
#include "hphp/runtime/vm/jit/linearscan.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/irfactory.h"
#include "hphp/runtime/vm/jit/nativecalls.h"
#include "hphp/runtime/vm/jit/print.h"
+1 -1
Ver Arquivo
@@ -13,9 +13,9 @@
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
*/
#include "hphp/runtime/vm/jit/print.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/ir.h"
#include "hphp/runtime/vm/jit/linearscan.h"
#include "hphp/runtime/vm/jit/codegen.h"
+1
Ver Arquivo
@@ -19,6 +19,7 @@
#include <sstream>
#include <type_traits>
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/base/type_conversions.h"
#include "hphp/runtime/vm/jit/tracebuilder.h"
#include "hphp/runtime/vm/runtime.h"
+1
Ver Arquivo
@@ -17,6 +17,7 @@
#ifndef incl_HPHP_HHVM_HHIR_SIMPLIFIER_H_
#define incl_HPHP_HHVM_HHIR_SIMPLIFIER_H_
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/cse.h"
#include "hphp/runtime/vm/jit/ir.h"
+1 -1
Ver Arquivo
@@ -19,7 +19,7 @@
#include <type_traits>
#include "hphp/runtime/base/memory/memory_manager.h"
#include "hphp/runtime/base/memory/smart_containers.h"
#include "hphp/runtime/vm/jit/irfactory.h"
namespace HPHP { namespace JIT {