Arquivos
hhvm/hphp/runtime/base/smart_containers.h
T
Kyle Delong a8e3321fbd HPHP/XHP: 'mixed' type in attribute declarations
We'd like to start using ##mixed## instead of ##var## for attribute types to be consistent with Hack. As a followup to this (once released), we would codemod all ##var## to ##mixed##.
2013-07-18 17:28:37 -07:00

231 linhas
6.5 KiB
C++

/*
+----------------------------------------------------------------------+
| HipHop for PHP |
+----------------------------------------------------------------------+
| Copyright (c) 2010-2013 Facebook, Inc. (http://www.facebook.com) |
| Copyright (c) 1998-2010 Zend Technologies Ltd. (http://www.zend.com) |
+----------------------------------------------------------------------+
| This source file is subject to version 2.00 of the Zend 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.zend.com/license/2_00.txt. |
| If you did not receive a copy of the Zend license and are unable to |
| obtain it through the world-wide-web, please send a note to |
| license@zend.com 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 <boost/container/flat_map.hpp>
#include "hphp/runtime/base/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)...
);
}
#ifndef __APPLE__ // XXX: this affects codegen quality but not correctness
static_assert(
sizeof(unique_ptr<int>::type) == sizeof(std::unique_ptr<int>),
"smart::unique_ptr pointer should not be larger than std::unique_ptr"
);
#endif
/*
* 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 Compare = std::less<T>>
class set : public std::set<
T, Compare, Allocator<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 Container = deque<T>>
class stack : public std::stack<T, Container> {};
template <class T>
class list : public std::list<T,Allocator<T>> {
typedef std::list<T,Allocator<T>> Base;
public:
template<class... A>
explicit list(A&&... args) : Base(std::forward<A>(args)...) {}
};
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)
{}
};
template<class K,
class V,
class Pred = std::less<K>>
struct flat_map
: boost::container::flat_map<K,V,Pred,Allocator<std::pair<K,V>>>
{};
template<class K,
class V,
class Pred = std::less<K>>
struct flat_multimap
: boost::container::flat_multimap<K,V,Pred,Allocator<std::pair<K,V>>>
{};
//////////////////////////////////////////////////////////////////////
}}
#endif