Skip to content

Commit

Permalink
Drop the boost dependency from Traits.h and FBVector.h
Browse files Browse the repository at this point in the history
Summary:
[Folly] Drop the `boost` dependency from `Traits.h` and `FBVector.h`.

Should not need it anymore with the currently supported compilers.

Reviewed By: ericniebler

Differential Revision: D4375572

fbshipit-source-id: df890c07f49b0499d2d2d08aa21c226b2893281e
  • Loading branch information
yfeldblum authored and facebook-github-bot committed Jan 3, 2017
1 parent 1807488 commit 03a4c5b
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 143 deletions.
7 changes: 4 additions & 3 deletions folly/FBVector.h
Expand Up @@ -210,7 +210,7 @@ class fbvector {
private:

typedef std::integral_constant<bool,
boost::has_trivial_copy_constructor<T>::value &&
IsTriviallyCopyable<T>::value &&
sizeof(T) <= 16 // don't force large structures to be passed by value
> should_pass_by_value;
typedef typename std::conditional<
Expand Down Expand Up @@ -322,7 +322,8 @@ class fbvector {

void M_destroy(T* p) noexcept {
if (usingStdAllocator::value) {
if (!boost::has_trivial_destructor<T>::value) p->~T();
if (!std::is_trivially_destructible<T>::value)
p->~T();
} else {
std::allocator_traits<Allocator>::destroy(impl_, p);
}
Expand Down Expand Up @@ -360,7 +361,7 @@ class fbvector {

// optimized
static void S_destroy_range(T* first, T* last) noexcept {
if (!boost::has_trivial_destructor<T>::value) {
if (!std::is_trivially_destructible<T>::value) {
// EXPERIMENTAL DATA on fbvector<vector<int>> (where each vector<int> has
// size 0).
// The unrolled version seems to work faster for small to medium sized
Expand Down
22 changes: 12 additions & 10 deletions folly/MPMCQueue.h
Expand Up @@ -86,7 +86,7 @@ template <typename> class MPMCQueueBase;
/// use noexcept, you will have to wrap it in something that provides
/// the guarantee. We provide an alternate safe implementation for types
/// that don't use noexcept but that are marked folly::IsRelocatable
/// and boost::has_nothrow_constructor, which is common for folly types.
/// and std::is_nothrow_constructible, which is common for folly types.
/// In particular, if you can declare FOLLY_ASSUME_FBVECTOR_COMPATIBLE
/// then your type can be put in MPMCQueue.
///
Expand Down Expand Up @@ -1310,15 +1310,17 @@ struct SingleElementQueue {

/// enqueue using move construction, either real (if
/// is_nothrow_move_constructible) or simulated using relocation and
/// default construction (if IsRelocatable and has_nothrow_constructor)
template <typename = typename std::enable_if<
(folly::IsRelocatable<T>::value &&
boost::has_nothrow_constructor<T>::value) ||
std::is_nothrow_constructible<T, T&&>::value>::type>
void enqueue(const uint32_t turn,
Atom<uint32_t>& spinCutoff,
const bool updateSpinCutoff,
T&& goner) noexcept {
/// default construction (if IsRelocatable and is_nothrow_constructible)
template <
typename = typename std::enable_if<
(folly::IsRelocatable<T>::value &&
std::is_nothrow_constructible<T>::value) ||
std::is_nothrow_constructible<T, T&&>::value>::type>
void enqueue(
const uint32_t turn,
Atom<uint32_t>& spinCutoff,
const bool updateSpinCutoff,
T&& goner) noexcept {
enqueueImpl(
turn,
spinCutoff,
Expand Down
1 change: 0 additions & 1 deletion folly/Makefile.am
Expand Up @@ -8,7 +8,6 @@ ACLOCAL_AMFLAGS = -I m4

CLEANFILES =


noinst_PROGRAMS = generate_fingerprint_tables
generate_fingerprint_tables_SOURCES = build/GenerateFingerprintTables.cpp
generate_fingerprint_tables_LDADD = libfollybase.la
Expand Down
8 changes: 0 additions & 8 deletions folly/String.h
Expand Up @@ -646,12 +646,4 @@ using UTF8StringPiece = UTF8Range<const char*>;

} // namespace folly

// Hook into boost's type traits
namespace boost {
template <class T>
struct has_nothrow_constructor<folly::basic_fbstring<T> > : true_type {
enum { value = true };
};
} // namespace boost

#include <folly/String-inl.h>
101 changes: 31 additions & 70 deletions folly/Traits.h
Expand Up @@ -36,8 +36,6 @@
#include <bits/c++config.h>
#endif

#include <boost/type_traits.hpp>

#define FOLLY_CREATE_HAS_MEMBER_TYPE_TRAITS(classname, type_name) \
template <typename TTheClass_> \
struct classname##__folly_traits_impl__ { \
Expand Down Expand Up @@ -341,29 +339,12 @@ using StrictConjunction =
struct IsRelocatable< __VA_ARGS__ > : std::true_type {};

/**
* Use this macro ONLY inside namespace boost. When using it with a
* regular type, use it like this:
*
* // Make sure you're at namespace ::boost scope
* template<> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyType)
*
* When using it with a template type, use it like this:
*
* // Make sure you're at namespace ::boost scope
* template<class T1, class T2>
* FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyType<T1, T2>)
*/
#define FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(...) \
struct has_nothrow_constructor< __VA_ARGS__ > : ::boost::true_type {};

/**
* The FOLLY_ASSUME_FBVECTOR_COMPATIBLE* macros below encode two
* assumptions: first, that the type is relocatable per IsRelocatable
* above, and that it has a nothrow constructor. Most types can be
* assumed to satisfy both conditions, but it is the responsibility of
* the user to state that assumption. User-defined classes will not
* work with fbvector (see FBVector.h) unless they state this
* combination of properties.
* The FOLLY_ASSUME_FBVECTOR_COMPATIBLE* macros below encode the
* assumption that the type is relocatable per IsRelocatable
* above. Many types can be assumed to satisfy this condition, but
* it is the responsibility of the user to state that assumption.
* User-defined classes will not be optimized for use with
* fbvector (see FBVector.h) unless they state that assumption.
*
* Use FOLLY_ASSUME_FBVECTOR_COMPATIBLE with regular types like this:
*
Expand All @@ -382,40 +363,35 @@ using StrictConjunction =
*/

// Use this macro ONLY at global level (no namespace)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE(...) \
namespace folly { template<> FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__) } \
namespace boost { \
template<> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__) }
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE(...) \
namespace folly { \
template <> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__) \
}
// Use this macro ONLY at global level (no namespace)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...) \
namespace folly { \
template <class T1> FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1>) } \
namespace boost { \
template <class T1> FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1>) }
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(...) \
namespace folly { \
template <class T1> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1>) \
}
// Use this macro ONLY at global level (no namespace)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(...) \
namespace folly { \
template <class T1, class T2> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2>) } \
namespace boost { \
template <class T1, class T2> \
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2>) }
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(...) \
namespace folly { \
template <class T1, class T2> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2>) \
}
// Use this macro ONLY at global level (no namespace)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(...) \
namespace folly { \
template <class T1, class T2, class T3> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3>) } \
namespace boost { \
template <class T1, class T2, class T3> \
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2, T3>) }
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_3(...) \
namespace folly { \
template <class T1, class T2, class T3> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3>) \
}
// Use this macro ONLY at global level (no namespace)
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(...) \
namespace folly { \
template <class T1, class T2, class T3, class T4> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3, T4>) } \
namespace boost { \
template <class T1, class T2, class T3, class T4> \
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(__VA_ARGS__<T1, T2, T3, T4>) }
#define FOLLY_ASSUME_FBVECTOR_COMPATIBLE_4(...) \
namespace folly { \
template <class T1, class T2, class T3, class T4> \
FOLLY_ASSUME_RELOCATABLE(__VA_ARGS__<T1, T2, T3, T4>) \
}

/**
* Instantiate FOLLY_ASSUME_FBVECTOR_COMPATIBLE for a few types. It is
Expand Down Expand Up @@ -454,18 +430,6 @@ template <class T>

FOLLY_NAMESPACE_STD_END

namespace boost {

template <class T> class shared_ptr;

template <class T, class U>
struct has_nothrow_constructor< std::pair<T, U> >
: std::integral_constant<bool,
has_nothrow_constructor<T>::value &&
has_nothrow_constructor<U>::value> {};

} // namespace boost

namespace folly {

// STL commonly-used types
Expand Down Expand Up @@ -681,9 +645,6 @@ FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::deque)
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_2(std::unique_ptr)
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::shared_ptr)
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(std::function)

// Boost
FOLLY_ASSUME_FBVECTOR_COMPATIBLE_1(boost::shared_ptr)
#endif

/* Some combinations of compilers and C++ libraries make __int128 and
Expand Down
27 changes: 0 additions & 27 deletions folly/docs/FBVector.md
Expand Up @@ -189,33 +189,6 @@ after `Widget`'s definition and write this:
If you don't do this, `fbvector<Widget>` will fail to compile
with a `static_assert`.

#### Additional Constraints

Similar improvements are possible in presence of a "simple" type
- more specifically, one that has a trivial assignment (i.e.
assignment is the same as bitblitting the bits over) or a nothrow
default constructor. These traits are used gainfully by
`fbvector` in a variety of places. Fortunately, these traits are
already present in the C++ standard (well, currently in Boost).
To summarize, in order to work with `fbvector`, a type `Widget`
must pass:

static_assert(
IsRelocatable<Widget>::value &&
(boost::has_trivial_assign<T>::value ||
boost::has_nothrow_constructor<T>::value),
"");

These traits go hand in hand; for example, it would be very
difficult to design a class that satisfies one branch of the
conjunction above but not the other. `fbvector` uses these simple
constraints to minimize the number of copies made on many common
operations such as `push_back`, `insert`, or `resize`.

To make it easy for you to state assumptions about a given type
or family of parameterized types, check Traits.h and in
particular handy family of macros FOLLY_ASSUME_FBVECTOR_COMPATIBLE*.

### Miscellaneous
***

Expand Down
36 changes: 12 additions & 24 deletions folly/docs/Traits.md
@@ -1,7 +1,7 @@
'folly/Traits.h'
-----------------

Implements traits complementary to those provided in <boost/type_traits.h>
Implements traits complementary to those provided in <type_traits>

* Implements `IsRelocatable` trait.
* Implements `IsOneOf` trait
Expand All @@ -10,12 +10,11 @@ Implements traits complementary to those provided in <boost/type_traits.h>
### Motivation
***

`<boost/type_traits.hpp>` is the Boost type-traits library defining a
variety of traits such as `is_integral` or `is_floating_point`. This helps
to gain more information about a given type.
Many traits introduced by Boost have been standardized in C++11.
`<type_traits>` is the Standard type-traits library defining a variety of traits
such as `is_integral` or `is_floating_point`. This helps to gain more
information about a given type.

`folly/Traits.h` implements traits complementing those present in boost.
`folly/Traits.h` implements traits complementing those present in the Standard.


### IsRelocatable
Expand Down Expand Up @@ -88,11 +87,11 @@ a value of type T by using memcpy.
namespace folly {
// defining specialization of IsRelocatable for MySimpleType
template <>
struct IsRelocatable<MySimpleType> : boost::true_type {};
struct IsRelocatable<MySimpleType> : std::true_type {};
// defining specialization of IsRelocatable for MyParameterizedType
template <class T1, class T2>
struct IsRelocatable<MyParameterizedType<T1, T2>>
: ::boost::true_type {};
: ::std::true_type {};
}
```

Expand All @@ -111,17 +110,6 @@ a value of type T by using memcpy.
}
```

* Stating that a type has no throw constructor using a macro

```Cpp
namespace boost {
// For a Regular Type
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MySimpleType);
// For a Parameterized Type
FOLLY_ASSUME_HAS_NOTHROW_CONSTRUCTOR(MyParameterizedType<T1, T2>);
}
```

`fbvector` only works with relocatable objects. If assumptions are not stated
explicitly, `fbvector<MySimpleType>` or `fbvector<MyParameterizedType>`
will fail to compile due to assertion below:
Expand Down Expand Up @@ -157,17 +145,17 @@ Similarly,

Few common types, namely `std::basic_string`, `std::vector`, `std::list`,
`std::map`, `std::deque`, `std::set`, `std::unique_ptr`, `std::shared_ptr`,
`std::function`, `boost::shared_ptr` which are compatible with `fbvector` are
already instantiated and declared compatible with `fbvector`. `fbvector` can be
directly used with any of these C++ types.
`std::function`, which are compatible with `fbvector` are already instantiated
and declared compatible with `fbvector`. `fbvector` can be directly used with
any of these C++ types.

`std::pair` can be safely assumed to be compatible with `fbvector` if both of
its components are.

### IsOneOf
***

`boost::is_same<T1, T2>::value` can be used to test if types of T1 and T2 are
same. `folly::IsOneOf<T, T1, Ts...>::value` can be used to test if type of T1
`std::is_same<T1, T2>::value` can be used to test if types of T1 and T2 are
same. `folly::IsOneOf<T, T1, Ts...>::value` can be used to test if type of T1
matches the type of one of the other template parameter, T1, T2, ...Tn.
Recursion is used to implement this type trait.

0 comments on commit 03a4c5b

Please sign in to comment.