提交 86d8ee24 编写于 作者: G guokuankuan

[bug fix] Fix readme typo and fix build bug

上级 6ffe5c50
......@@ -19,14 +19,9 @@ drawbacks.
- `heavy_write` means 90% write operations
- `heavy_read` means 90% read operations
### Documentation
[TerarkDB all-in-one Docs](https://bytedance.feishu.cn/docs/doccnZmYFqHBm06BbvYgjsHHcKc#)
![](docs/static/images/performance/compare_rocksdb.png)
<<<<<<< HEAD
## Full Document
## Document
[All-in-one Documentation](https://bytedance.feishu.cn/docs/doccnZmYFqHBm06BbvYgjsHHcKc#)
......@@ -92,8 +87,7 @@ We didn't archieve all static libraries together yet, so you have to pack all li
```
-Wl,-Bstatic \
-lterarkdb -lbz2 -ljemalloc -llz4 -lmetrics2 -lsnappy -lz -lterark-zip-r -lzstd \
-lboost_context -lboost_fiber -lboost_filesystem -lboost_system \
-lterarkdb -lbz2 -ljemalloc -llz4 -lsnappy -lz -lzstd \
-Wl,-Bdynamic -pthread -lgomp -lrt -ldl -laio
```
......
#ifndef __terark_config_h__
#define __terark_config_h__
#if defined(_MSC_VER)
# pragma once
#ifndef _CRT_SECURE_NO_WARNINGS
# define _CRT_SECURE_NO_WARNINGS
#endif
#ifndef _CRT_NONSTDC_NO_WARNINGS
#define _CRT_NONSTDC_NO_WARNINGS
#endif
#ifndef _SCL_SECURE_NO_WARNINGS
#define _SCL_SECURE_NO_WARNINGS
#endif
# if defined(TERARK_CREATE_DLL)
# pragma warning(disable: 4251)
# define TERARK_DLL_EXPORT __declspec(dllexport) // creator of dll
# if defined(_DEBUG) || !defined(NDEBUG)
#// pragma message("creating terark-d.lib")
# else
#// pragma message("creating terark-r.lib")
# endif
# elif defined(TERARK_USE_DLL)
# pragma warning(disable: 4251)
# define TERARK_DLL_EXPORT __declspec(dllimport) // user of dll
# if defined(_DEBUG) || !defined(NDEBUG)
//# pragma comment(lib, "terark-d.lib")
# else
//# pragma comment(lib, "terark-r.lib")
# endif
# else
# define TERARK_DLL_EXPORT // static lib creator or user
# endif
#else /* _MSC_VER */
# define TERARK_DLL_EXPORT
#endif /* _MSC_VER */
#if defined(__GNUC__) && __GNUC__*1000 + __GNUC_MINOR__ >= 7001
# define no_break_fallthrough __attribute__ ((fallthrough))
#endif
#if defined(__GNUC__) || defined(__INTEL_COMPILER) || defined(__clang__)
# define terark_likely(x) __builtin_expect(x, 1)
# define terark_unlikely(x) __builtin_expect(x, 0)
# define terark_no_return __attribute__((noreturn))
# define terark_warn_unused_result __attribute__((warn_unused_result))
# define terark_flatten __attribute__((flatten))
# define terark_used_static_obj __attribute__((used))
# define terark_no_inline __attribute__((noinline))
# define terark_forceinline inline __attribute__((always_inline))
#else
#if defined(_MSC_VER) && _MSC_VER >= 1310
# define terark_no_return __declspec(noreturn)
# define terark_no_inline __declspec(noinline)
# define terark_forceinline __forceinline
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1400
# define terark_no_alias __declspec(noalias)
#endif
#if defined(_MSC_VER) && _MSC_VER >= 1910 // vs2017
# if _MSVC_LANG >= 201703L
# define no_break_fallthrough [[fallthrough]]
# endif
#endif
# define terark_likely(x) x
# define terark_unlikely(x) x
# define terark_warn_unused_result
# define terark_flatten
#endif
#if !defined(terark_no_return)
# define terark_no_return
#endif
#if !defined(terark_no_inline)
# define terark_no_inline
#endif
#if !defined(terark_forceinline)
# define terark_forceinline inline
#endif
#if !defined(terark_no_alias)
# define terark_no_alias
#endif
#if !defined(terark_used_static_obj)
# define terark_used_static_obj volatile
#endif
/* The ISO C99 standard specifies that in C++ implementations these
* should only be defined if explicitly requested __STDC_CONSTANT_MACROS
*/
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#if defined(__GNUC__) && ( \
defined(__LP64__) && (__LP64__ == 1) || \
defined(__amd64__) || defined(__amd64) || \
defined(__x86_64__) || defined(__x86_64) || \
defined(__ia64__) || defined(_IA64) || defined(__IA64__) ) || \
defined(_MSC_VER) && ( defined(_WIN64) || defined(_M_X64) || defined(_M_IA64) ) || \
defined(__INTEL_COMPILER) && ( \
defined(__ia64) || defined(__itanium__) || \
defined(__x86_64) || defined(__x86_64__) ) || \
defined(__WORD_SIZE) && __WORD_SIZE == 64
#define TERARK_WORD_BITS 64
#define TERARK_IF_WORD_BITS_64(Then, Else) Then
#else
#define TERARK_WORD_BITS 32
#define TERARK_IF_WORD_BITS_64(Then, Else) Else
#endif
#if defined(_MSC_VER)
#define TERARK_IF_MSVC(Then, Else) Then
#else
#define TERARK_IF_MSVC(Then, Else) Else
#endif
#if !defined(no_break_fallthrough)
#define no_break_fallthrough /* fall through */
#endif
#if defined(__gnu_linux__) || defined(__gnu_hurd__) || defined(__FreeBSD__)
#define TERARK_HAS_WEAK_SYMBOL 1
#define TERARK_WEAK_SYMBOL __attribute__((weak))
#else
#define TERARK_WEAK_SYMBOL
#endif
#define TERARK_UNUSED_VAR(x) (void)(x)
#define TERARK_NAME_TYPE(name, ...) \
struct name : __VA_ARGS__ { \
typedef __VA_ARGS__ super_class; \
using super_class::super_class; \
}
extern bool g_Terark_hasValgrind;
#endif // __terark_config_h__
#include "utilities/util/factory.h"
//#include <terark/hash_strmap.hpp>
// #include <terark/gold_hash_map.hpp>
namespace bytedance_terark {
///@note on principle, the factory itself is stateless, but its product
/// can has states, sometimes we need factory of factory, in this case,
/// just let the factory being factoryable:
/// class SomeFactory : public Factoyable<SomeFactory> {
/// ...
/// };
bool getEnvBool(const char* envName, bool Default) {
if (const char* env = getenv(envName)) {
if (isdigit(env[0])) {
return atoi(env) != 0;
}
#if defined(_MSC_VER)
#define strcasecmp stricmp
#endif
if (strcasecmp(env, "true") == 0) return true;
if (strcasecmp(env, "false") == 0) return false;
fprintf(stderr,
"WARN: terark::getEnvBool(\"%s\") = \"%s\" is invalid, treat as "
"false\n",
envName, env);
}
return Default;
}
long getEnvLong(const char* envName, long Default) {
if (const char* env = getenv(envName)) {
int base = 0; // env can be oct, dec, hex
return strtol(env, NULL, base);
}
return Default;
}
double getEnvDouble(const char* envName, double Default) {
if (const char* env = getenv(envName)) {
return strtof(env, NULL);
}
return Default;
}
} // namespace bytedance_terark
// created by leipeng 2019-12-13
#pragma once
// #ifndef __UTILITIES_UTIL_FACTORY_HPP__
// #define __UTILITIES_UTIL_FACTORY_HPP__
#include <rocksdb/slice.h>
#ifdef BOOSTLIB
#include <boost/current_function.hpp>
#include <boost/noncopyable.hpp>
#else
#define BOOST_CURRENT_FUNCTION "(unknown)"
#endif
#include <mutex>
#include <typeindex>
#include <typeinfo>
#include <unordered_map>
#include "util/hash.h"
#include "utilities/util/function.hpp"
#include "utilities/util/terark_boost.hpp"
#define BYTEDANCE_TERARK_DLL_EXPORT
namespace bytedance_terark {
///@note on principle, the factory itself is stateless, but its product
/// can has states, sometimes we need factory of factory, in this case,
/// just let the factory being factoryable:
/// class SomeFactory : public Factoyable<SomeFactory> {
/// ...
/// };
template <class ProductPtr, class... CreatorArgs>
class Factoryable {
public:
virtual ~Factoryable();
static ProductPtr create(rocksdb::Slice name, CreatorArgs...);
rocksdb::Slice reg_name() const;
#ifdef BOOSTLIB
struct AutoReg : boost::noncopyable {
#else
struct AutoReg : terark_boost::noncopyable {
#endif
typedef function<ProductPtr(CreatorArgs...)> CreatorFunc;
AutoReg(rocksdb::Slice name, CreatorFunc creator, const std::type_info&);
~AutoReg();
std::string m_name;
std::type_index m_type_idx;
struct Impl;
};
};
///@param VarID var identifier
///@param Name string of factory name
///@param Creator
///@param Class ... can be qulified template such as:
/// SomeNameSpace::SomeProductPtr<T1, T2, T3>
#define TERARK_FACTORY_REGISTER_IMPL(VarID, Name, Creator, Class, ...) \
TERARK_PP_IDENTITY(Class, ##__VA_ARGS__)::AutoReg TERARK_PP_CAT( \
g_reg_factory_, VarID, __LINE__)( \
Name, Creator, typeid(TERARK_PP_IDENTITY(Class, ##__VA_ARGS__)))
///@param Class can not be template such as SomeProductPtr<T1, T2, T3>,
/// can not be qulified class name such as SomeNameSpace::SomeClass
///@note if Class has some non-var char, such as "-,." ...
/// must use TERARK_FACTORY_REGISTER_IMPL to set an VarID
#define TERARK_FACTORY_REGISTER_EX(Class, Name, Creator) \
TERARK_FACTORY_REGISTER_IMPL(Class, Name, Creator, Class)
#define TERARK_FACTORY_REGISTER(Class, Creator) \
TERARK_FACTORY_REGISTER_EX(Class, TERARK_PP_STR(Class), Creator)
} // namespace bytedance_terark
namespace bytedance_terark {
BYTEDANCE_TERARK_DLL_EXPORT bool getEnvBool(const char* envName,
bool Default = false);
BYTEDANCE_TERARK_DLL_EXPORT long getEnvLong(const char* envName,
long Default = false);
BYTEDANCE_TERARK_DLL_EXPORT double getEnvDouble(const char* envName,
double Default);
} // namespace bytedance_terark
// #endif // __UTILITIES_UTIL_FACTORY_HPP__
namespace bytedance_terark {
template <class ProductPtr, class... CreatorArgs>
struct Factoryable<ProductPtr, CreatorArgs...>::AutoReg::Impl {
#if 1
struct FakeMutex {
void lock() {}
void unlock() {}
};
using MaybeMutex = FakeMutex;
#else
using MaybeMutex = std::mutex;
#endif
using NameToFuncMap = std::unordered_map<std::string, CreatorFunc>;
using TypeToNameMap = std::unordered_map<std::type_index, std::string>;
NameToFuncMap func_map;
TypeToNameMap type_map;
MaybeMutex mtx;
static Impl& s_singleton() {
static Impl imp;
return imp;
}
};
//#define TERARK_FACTORY_WARN_ON_DUP_NAME
template <class ProductPtr, class... CreatorArgs>
Factoryable<ProductPtr, CreatorArgs...>::AutoReg::AutoReg(
rocksdb::Slice name, CreatorFunc creator, const std::type_info& ti)
: m_name(name.ToString()), m_type_idx(ti) {
auto& imp = Impl::s_singleton();
auto& func_map = imp.func_map;
imp.mtx.lock();
if (!func_map.emplace(name.ToString(), creator).second) {
fprintf(stderr, "FATAL: %s: duplicate name = %.*s\n", __FUNCTION__,
int(name.size()), name.data());
abort();
}
if (!imp.type_map.emplace(ti, name.ToString()).second) {
#if defined(TERARK_FACTORY_WARN_ON_DUP_NAME)
rocksdb::Slice oldname = imp.type_map.val(ib.first);
fprintf(stderr,
"WARN: %s: dup name: {old=\"%.*s\", new=\"%.*s\"} "
"for type: %s, new name ignored\n",
__FUNCTION__, oldname.size(), oldname.data(), name.size(),
name.data(), ti.name());
#endif
}
imp.mtx.unlock();
}
template <class ProductPtr, class... CreatorArgs>
Factoryable<ProductPtr, CreatorArgs...>::AutoReg::~AutoReg() {
auto& imp = Impl::s_singleton();
imp.mtx.lock();
size_t cnt1 = imp.func_map.erase(m_name);
size_t cnt2 = imp.type_map.erase(m_type_idx);
if (0 == cnt1) {
fprintf(stderr, "FATAL: %s: name = %.*s to creator not found\n",
__FUNCTION__, int(m_name.size()), m_name.data());
abort();
}
if (0 == cnt2) {
#if defined(TERARK_FACTORY_WARN_ON_DUP_NAME)
fprintf(stderr, "WARN: %s: type = %s to name not found, ignored\n",
__FUNCTION__, m_type_idx.name());
#endif
}
imp.mtx.unlock();
}
template <class ProductPtr, class... CreatorArgs>
ProductPtr Factoryable<ProductPtr, CreatorArgs...>::create(
rocksdb::Slice name, CreatorArgs... args) {
auto& imp = AutoReg::Impl::s_singleton();
auto& func_map = imp.func_map;
imp.mtx.lock();
auto i = func_map.find(name.ToString());
if (func_map.end() != i) {
auto& creator = i->second;
imp.mtx.unlock();
return (creator)(args...);
} else {
imp.mtx.unlock();
return nullptr;
}
}
template <class ProductPtr, class... CreatorArgs>
rocksdb::Slice Factoryable<ProductPtr, CreatorArgs...>::reg_name() const {
auto& imp = AutoReg::Impl::s_singleton();
rocksdb::Slice name;
imp.mtx.lock();
auto i = imp.type_map.find(std::type_index(typeid(*this)));
if (imp.type_map.end() != i) {
name = i->second;
}
imp.mtx.unlock();
return name;
}
template <class ProductPtr, class... CreatorArgs>
Factoryable<ProductPtr, CreatorArgs...>::~Factoryable() {}
} // namespace bytedance_terark
/// ---- user land ----
///@param ProductPtr allowing template product, such as
/// TERARK_FACTORY_INSTANTIATE(SomeProduct<T1, T2, T3>, CreatorArg1...)
///@note this macro must be called in namespace terark
#define BYTEDANCE_TERARK_FACTORY_INSTANTIATE(ProductPtr, ...) \
template class Factoryable<ProductPtr, ##__VA_ARGS__>
///@note this macro must be called in global namespace
#define BYTEDANCE_TERARK_FACTORY_INSTANTIATE_GNS(ProductPtr, ...) \
namespace bytedance_terark { \
BYTEDANCE_TERARK_FACTORY_INSTANTIATE(ProductPtr, ##__VA_ARGS__); \
}
/* vim: set tabstop=4 : */
#pragma once
#include <functional>
#include "utilities/util/config.hpp"
#include "utilities/util/preproc.hpp"
#include "utilities/util/terark_boost.hpp"
namespace bytedance_terark {
using std::bind;
using std::cref;
using std::function;
using std::ref;
using std::reference_wrapper;
using std::remove_reference;
template <class FuncProto>
class tfunc : public function<FuncProto> {
typedef function<FuncProto> super;
public:
using super::super;
template <class Functor>
tfunc(const Functor* f) : super(ref(*f)) {}
};
template <class Functor, class... ArgList>
auto bind(Functor* f, ArgList&&... args)
-> decltype(bind(ref(*f), std::forward<ArgList>(args)...)) {
return bind(ref(*f), std::forward<ArgList>(args)...);
}
template <class Func>
class OnScopeExit {
const Func& on_exit;
public:
OnScopeExit(const Func& f) : on_exit(f) {}
~OnScopeExit() { on_exit(); }
};
#define TERARK_SCOPE_EXIT(...) \
auto TERARK_PP_CAT2(func_on_exit_, __LINE__) = [&]() { __VA_ARGS__; }; \
terark::OnScopeExit<decltype(TERARK_PP_CAT2(func_on_exit_, __LINE__))> \
TERARK_PP_CAT2(call_on_exit_, \
__LINE__)(TERARK_PP_CAT2(func_on_exit_, __LINE__))
template <class R, class... Args>
using c_callback_fun_t = R (*)(void*, Args...);
template <class Lambda>
struct c_callback_t {
template <class R, class... Args>
static R invoke(void* vlamb, Args... args) {
return (*(Lambda*)vlamb)(std::forward<Args>(args)...);
}
template <class R, class... Args>
operator c_callback_fun_t<R, Args...>() const {
return &c_callback_t::invoke<R, Args...>;
}
};
template <class Lambda>
c_callback_t<Lambda> c_callback(Lambda&) {
return c_callback_t<Lambda>();
}
template <class MemFuncType, MemFuncType MemFunc>
struct mf_callback_t {
template <class R, class Obj, class... Args>
static R invoke(void* self, Args... args) {
return (((Obj*)self)->*MemFunc)(std::forward<Args>(args)...);
}
template <class R, class... Args>
operator c_callback_fun_t<R, Args...>() const {
return &mf_callback_t::invoke<R, Args...>;
}
};
// do not need to pack <This, MemFunc> as a struct
#define TERARK_MEM_FUNC(MemFunc) mf_callback_t<decltype(MemFunc), MemFunc>()
///@param lambda lambda obj
///@note this yield two args
#define TERARK_C_CALLBACK(lambda) terark::c_callback(lambda), &lambda
//--------------------------------------------------------------------
// User/Application defined MemPool
class TERARK_DLL_EXPORT UserMemPool : terark_boost::noncopyable {
UserMemPool();
public:
virtual ~UserMemPool();
virtual void* alloc(size_t);
virtual void* realloc(void*, size_t);
virtual void sfree(void*, size_t);
static UserMemPool* SysMemPool();
};
#define TERARK_COMPARATOR_OP(Name, expr) \
struct Name { \
template <class T> \
bool operator()(const T& x, const T& y) const { \
return expr; \
} \
}
TERARK_COMPARATOR_OP(CmpLT, x < y);
TERARK_COMPARATOR_OP(CmpGT, y < x);
TERARK_COMPARATOR_OP(CmpLE, !(y < x));
TERARK_COMPARATOR_OP(CmpGE, !(x < y));
TERARK_COMPARATOR_OP(CmpEQ, x == y);
TERARK_COMPARATOR_OP(CmpNE, !(x == y));
struct cmp_placeholder {};
constexpr cmp_placeholder cmp; // gcc warns for unused static var
template <class Pred>
struct NotPredT {
template <class T>
bool operator()(const T& x) const {
return !pred(x);
}
Pred pred;
};
///{@
///@arg x is the free arg
///@arg y is the bound arg
#define TERARK_BINDER_CMP_OP(BinderName, expr) \
template <class T> \
struct BinderName { \
const T y; \
template <class U> \
BinderName(U&& y1) : y(std::forward<U>(y1)) {} \
bool operator()(const T& x) const { return expr; } \
}; \
template <class T> \
struct BinderName<T*> { \
const T* y; \
BinderName(const T* y1) : y(y1) {} \
bool operator()(const T* x) const { return expr; } \
}; \
template <class T> \
struct BinderName<reference_wrapper<const T> > { \
const T& y; \
BinderName(const T& y1) : y(y1) {} \
bool operator()(const T& x) const { return expr; } \
}
TERARK_BINDER_CMP_OP(BinderLT, x < y);
TERARK_BINDER_CMP_OP(BinderGT, y < x);
TERARK_BINDER_CMP_OP(BinderLE, !(y < x));
TERARK_BINDER_CMP_OP(BinderGE, !(x < y));
TERARK_BINDER_CMP_OP(BinderEQ, x == y);
TERARK_BINDER_CMP_OP(BinderNE, !(x == y));
///@}
template <class KeyExtractor>
struct ExtractorLessT {
KeyExtractor ex;
template <class T>
bool operator()(const T& x, const T& y) const {
return ex(x) < ex(y);
}
};
template <class KeyExtractor>
ExtractorLessT<KeyExtractor> ExtractorLess(KeyExtractor ex) {
return ExtractorLessT<KeyExtractor>{ex};
}
template <class KeyExtractor>
struct ExtractorGreaterT {
KeyExtractor ex;
template <class T>
bool operator()(const T& x, const T& y) const {
return ex(y) < ex(x);
}
};
template <class KeyExtractor>
ExtractorGreaterT<KeyExtractor> ExtractorGreater(KeyExtractor ex) {
return ExtractorGreaterT<KeyExtractor>{ex};
}
template <class KeyExtractor>
struct ExtractorEqualT {
KeyExtractor ex;
template <class T>
bool operator()(const T& x, const T& y) const {
return ex(x) == ex(y);
}
};
template <class KeyExtractor>
ExtractorEqualT<KeyExtractor> ExtractorEqual(KeyExtractor ex) {
return ExtractorEqualT<KeyExtractor>{ex};
}
template <class KeyExtractor, class KeyComparator>
struct ExtractorComparatorT {
template <class T>
bool operator()(const T& x, const T& y) const {
return keyCmp(keyEx(x), keyEx(y));
}
KeyExtractor keyEx;
KeyComparator keyCmp;
};
template <class KeyExtractor, class Comparator>
ExtractorComparatorT<KeyExtractor, Comparator> ExtractorComparator(
KeyExtractor ex, Comparator cmp) {
return ExtractorComparatorT<KeyExtractor, Comparator>{ex, cmp};
}
template <class Extractor1, class Extractor2>
struct CombineExtractor {
Extractor1 ex1;
Extractor2 ex2;
template <class T>
auto operator()(const T& x) const -> decltype(ex2(ex1(x))) {
return ex2(ex1(x));
}
};
template <class Extractor1>
struct CombinableExtractorT {
Extractor1 ex1;
NotPredT<CombinableExtractorT> operator!() const {
return NotPredT<CombinableExtractorT>{*this};
}
///@{
/// operator+ as combine operator
template <class Extractor2>
CombineExtractor<Extractor1, Extractor2> operator+(Extractor2&& ex2) const {
return CombineExtractor<Extractor1, Extractor2>{
ex1, std::forward<Extractor2>(ex2)};
}
///@}
///@{
/// operator| combine a comparator: less, greator, equal...
template <class Comparator>
ExtractorComparatorT<Extractor1, Comparator> operator|(
Comparator&& cmp) const {
return ExtractorComparator(ex1, std::forward<Comparator>(cmp));
}
///@}
#define TERARK_CMP_OP(Name, op) \
ExtractorComparatorT<Extractor1, Name> operator op(cmp_placeholder) const { \
return ExtractorComparator(ex1, Name()); \
}
TERARK_CMP_OP(CmpLT, <)
TERARK_CMP_OP(CmpGT, >)
TERARK_CMP_OP(CmpLE, <=)
TERARK_CMP_OP(CmpGE, >=)
TERARK_CMP_OP(CmpEQ, ==)
TERARK_CMP_OP(CmpNE, !=)
#define TERARK_COMBINE_BIND_OP(Name, op) \
template <class T> \
CombineExtractor<Extractor1, Name<typename remove_reference<T>::type> > \
operator op(T&& y) const { \
return CombineExtractor<Extractor1, \
Name<typename remove_reference<T>::type> >{ \
ex1, {std::forward<T>(y)}}; \
} \
\
template <class T> \
CombineExtractor<Extractor1, Name<reference_wrapper<const T> > > \
operator op(reference_wrapper<const T> y) const { \
return CombineExtractor<Extractor1, Name<reference_wrapper<const T> > >{ \
ex1, {y.get()}}; \
}
///@{
/// operators: <, >, <=, >=, ==, !=
/// use bound operator as Extractor, Extractor is a transformer in this case
TERARK_COMBINE_BIND_OP(BinderLT, <)
TERARK_COMBINE_BIND_OP(BinderGT, >)
TERARK_COMBINE_BIND_OP(BinderLE, <=)
TERARK_COMBINE_BIND_OP(BinderGE, >=)
TERARK_COMBINE_BIND_OP(BinderEQ, ==)
TERARK_COMBINE_BIND_OP(BinderNE, !=)
///@}
/// forward the extractor
template <class T>
auto operator()(const T& x) const -> decltype(ex1(x)) {
return ex1(x);
}
};
template <class Extractor1>
CombinableExtractorT<Extractor1> CombinableExtractor(Extractor1&& ex1) {
return CombinableExtractorT<Extractor1>{std::forward<Extractor1>(ex1)};
}
///@param __VA_ARGS__ can be ' .template some_member_func<1,2,3>()'
/// or '->template some_member_func<1,2,3>()'
///@note '.' or '->' before field is required
///@note TERARK_GET() is identity operator
#define TERARK_GET(...) \
bytedance_terark::CombinableExtractor( \
[](const auto& x) -> decltype(auto) { return (x __VA_ARGS__); })
#define TERARK_FIELD_O_0() x
#define TERARK_FIELD_P_0() x
#define TERARK_FIELD_O_1(field) x.field
#define TERARK_FIELD_P_1(field) x->field
///@param __VA_ARGS__ can NOT be 'template some_member_func<1,2,3>()'
///@note decltype(auto) is required, () on return is required
///@note TERARK_FIELD() is identity operator
///@note '.' or '->' can not before field name
#define TERARK_FIELD(...) \
[](const auto& x) -> decltype(auto) { \
return (TERARK_PP_VA_NAME(TERARK_FIELD_O_, __VA_ARGS__)(__VA_ARGS__)); \
}
#define TERARK_FIELD_P(...) \
[](const auto& x) -> decltype(auto) { \
return (TERARK_PP_VA_NAME(TERARK_FIELD_P_, __VA_ARGS__)(__VA_ARGS__)); \
}
///@{
///@param d '.' or '->'
///@param f field
///@param o order/operator, '<' or '>'
#define TERARK_CMP1(d, f, o) \
if (x d f o y d f) return true; \
if (y d f o x d f) return false;
#define TERARK_CMP_O_2(f, o) return x.f o y.f;
#define TERARK_CMP_O_4(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_2(__VA_ARGS__)
#define TERARK_CMP_O_6(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_4(__VA_ARGS__)
#define TERARK_CMP_O_8(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_6(__VA_ARGS__)
#define TERARK_CMP_O_a(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_8(__VA_ARGS__)
#define TERARK_CMP_O_c(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_a(__VA_ARGS__)
#define TERARK_CMP_O_e(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_c(__VA_ARGS__)
#define TERARK_CMP_O_g(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_e(__VA_ARGS__)
#define TERARK_CMP_O_i(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_g(__VA_ARGS__)
#define TERARK_CMP_O_k(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_i(__VA_ARGS__)
#define TERARK_CMP_O_m(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_k(__VA_ARGS__)
#define TERARK_CMP_O_o(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_m(__VA_ARGS__)
#define TERARK_CMP_O_q(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_o(__VA_ARGS__)
#define TERARK_CMP_O_s(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_q(__VA_ARGS__)
#define TERARK_CMP_O_u(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_s(__VA_ARGS__)
#define TERARK_CMP_O_w(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_u(__VA_ARGS__)
#define TERARK_CMP_O_y(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_w(__VA_ARGS__)
#define TERARK_CMP_O_A(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_y(__VA_ARGS__)
#define TERARK_CMP_O_C(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_A(__VA_ARGS__)
#define TERARK_CMP_O_E(f, o, ...) \
TERARK_CMP1(., f, o) TERARK_CMP_O_C(__VA_ARGS__)
#define TERARK_CMP_P_2(f, o) return x->f o y->f;
#define TERARK_CMP_P_4(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_2(__VA_ARGS__)
#define TERARK_CMP_P_6(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_4(__VA_ARGS__)
#define TERARK_CMP_P_8(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_6(__VA_ARGS__)
#define TERARK_CMP_P_a(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_8(__VA_ARGS__)
#define TERARK_CMP_P_c(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_a(__VA_ARGS__)
#define TERARK_CMP_P_e(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_c(__VA_ARGS__)
#define TERARK_CMP_P_g(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_e(__VA_ARGS__)
#define TERARK_CMP_P_i(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_g(__VA_ARGS__)
#define TERARK_CMP_P_k(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_i(__VA_ARGS__)
#define TERARK_CMP_P_m(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_k(__VA_ARGS__)
#define TERARK_CMP_P_o(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_m(__VA_ARGS__)
#define TERARK_CMP_P_q(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_o(__VA_ARGS__)
#define TERARK_CMP_P_s(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_q(__VA_ARGS__)
#define TERARK_CMP_P_u(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_s(__VA_ARGS__)
#define TERARK_CMP_P_w(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_u(__VA_ARGS__)
#define TERARK_CMP_P_y(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_w(__VA_ARGS__)
#define TERARK_CMP_P_A(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_y(__VA_ARGS__)
#define TERARK_CMP_P_C(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_A(__VA_ARGS__)
#define TERARK_CMP_P_E(f, o, ...) \
TERARK_CMP1(->, f, o) TERARK_CMP_P_C(__VA_ARGS__)
///@}
///@param __VA_ARGS__ at least 1 field
///@note max support 20 fields, sample usage: TERARK_CMP(f1,>,f2,<,f3,<)
#define TERARK_CMP(...) \
[](const auto& x, const auto& y) -> bool { \
TERARK_PP_VA_NAME(TERARK_CMP_O_, __VA_ARGS__)(__VA_ARGS__) \
}
#define TERARK_CMP_P(...) \
[](const auto& x, const auto& y) -> bool { \
TERARK_PP_VA_NAME(TERARK_CMP_P_, __VA_ARGS__)(__VA_ARGS__) \
}
#define TERARK_EQUAL_MAP(c, f) \
if (!(x f == y f)) return false;
#define TERARK_EQUAL_IMP(...) \
[](const auto& x, const auto& y) { \
TERARK_PP_MAP(TERARK_EQUAL_MAP, ~, __VA_ARGS__); \
return true; \
}
///@param __VA_ARGS__ can not be empty
#define TERARK_EQUAL(...) \
TERARK_EQUAL_IMP(TERARK_PP_MAP(TERARK_PP_PREPEND, ., __VA_ARGS__))
///@param __VA_ARGS__ can not be empty
#define TERARK_EQUAL_P(...) \
TERARK_EQUAL_IMP(TERARK_PP_MAP(TERARK_PP_PREPEND, ->, __VA_ARGS__))
} // namespace bytedance_terark
// using bytedance_terark::cmp;
此差异已折叠。
#pragma once
namespace terark_boost {
struct base_token {};
class noncopyable : base_token {
protected:
noncopyable() = default;
~noncopyable() = default;
private:
noncopyable(const noncopyable&);
const noncopyable& operator=(const noncopyable&);
};
} // namespace terark_boost
\ No newline at end of file
#ifndef __bytedance_penglei_valvec_hpp__
#define __bytedance_penglei_valvec_hpp__
#include <stdlib.h>
#include "utilities/util/function.hpp"
namespace bytedance_terark {
/// STL like algorithm with array/RanIt and size_t param
template <class RanIt, class Key, class KeyExtractor>
size_t lower_bound_ex_n(RanIt a, size_t low, size_t upp, const Key& key,
KeyExtractor keyEx) {
assert(low <= upp);
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (keyEx(a[mid]) < key)
i = mid + 1;
else
j = mid;
}
return i;
}
template <class RanIt, class Key, class KeyExtractor, class Comp>
size_t lower_bound_ex_n(RanIt a, size_t low, size_t upp, const Key& key,
KeyExtractor keyEx, Comp comp) {
assert(low <= upp);
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (comp(keyEx(a[mid]), key))
i = mid + 1;
else
j = mid;
}
return i;
}
template <class RanIt, class Key>
size_t lower_bound_n(RanIt a, size_t low, size_t upp, const Key& key) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (a[mid] < key)
i = mid + 1;
else
j = mid;
}
return i;
}
template <class RanIt, class Key, class Comp>
size_t lower_bound_n(RanIt a, size_t low, size_t upp, const Key& key,
Comp comp) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (comp(a[mid], key))
i = mid + 1;
else
j = mid;
}
return i;
}
template <class RanIt, class Key>
size_t upper_bound_n(RanIt a, size_t low, size_t upp, const Key& key) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (key < a[mid])
j = mid;
else
i = mid + 1;
}
return i;
}
template <class RanIt, class Key, class Comp>
size_t upper_bound_n(RanIt a, size_t low, size_t upp, const Key& key,
Comp comp) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (comp(key, a[mid]))
j = mid;
else
i = mid + 1;
}
return i;
}
template <class RanIt, class Key>
std::pair<size_t, size_t> equal_range_n(RanIt a, size_t low, size_t upp,
const Key& key) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (a[mid] < key)
i = mid + 1;
else if (key < a[mid])
j = mid;
else
return std::pair<size_t, size_t>(
lower_bound_n<RanIt, Key>(a, i, mid, key),
upper_bound_n<RanIt, Key>(a, mid + 1, upp, key));
}
return std::pair<size_t, size_t>(i, i);
}
template <class RanIt, class Key, class Comp>
std::pair<size_t, size_t> equal_range_n(RanIt a, size_t low, size_t upp,
const Key& key, Comp comp) {
size_t i = low, j = upp;
while (i < j) {
size_t mid = (i + j) / 2;
if (comp(a[mid], key))
i = mid + 1;
else if (comp(key, a[mid]))
j = mid;
else
return std::pair<size_t, size_t>(
lower_bound_n<RanIt, Key, Comp>(a, i, mid, key, comp),
upper_bound_n<RanIt, Key, Comp>(a, mid + 1, j, key, comp));
}
return std::pair<size_t, size_t>(i, i);
}
template <class RanIt, class Key>
bool binary_search_n(RanIt a, size_t low, size_t upp, const Key& key) {
size_t f = lower_bound_n<RanIt, Key>(a, low, upp, key);
return f < upp && !(key < a[f]);
}
template <class RanIt, class Key, class Comp>
bool binary_search_n(RanIt a, size_t low, size_t upp, const Key& key,
Comp comp) {
size_t f = lower_bound_n<RanIt, Key, Comp>(a, low, upp, key, comp);
return f < upp && !comp(key, a[f]);
}
template <class RanIt>
void sort_n(RanIt a, size_t low, size_t upp) {
std::sort<RanIt>(a + low, a + upp);
}
template <class RanIt, class Comp>
void sort_n(RanIt a, size_t low, size_t upp, Comp comp) {
std::sort<RanIt, Comp>(a + low, a + upp, comp);
}
template <class RanIt, class Key>
size_t lower_bound_0(RanIt a, size_t n, const Key& key) {
return lower_bound_n<RanIt, Key>(a, 0, n, key);
}
template <class RanIt, class Key, class Comp>
size_t lower_bound_0(RanIt a, size_t n, const Key& key, Comp comp) {
return lower_bound_n<RanIt, Key, Comp>(a, 0, n, key, comp);
}
template <class Container, class Key>
size_t lower_bound_a(const Container& a, const Key& key) {
typedef typename Container::const_iterator RanIt;
return lower_bound_n<RanIt, Key>(a.begin(), 0, a.size(), key);
}
template <class Container, class Key, class Comp>
size_t lower_bound_a(const Container& a, const Key& key, Comp comp) {
typedef typename Container::const_iterator RanIt;
return lower_bound_n<RanIt, Key, Comp>(a.begin(), 0, a.size(), key, comp);
}
template <class RanIt, class Key>
size_t upper_bound_0(RanIt a, size_t n, const Key& key) {
return upper_bound_n<RanIt, Key>(a, 0, n, key);
}
template <class RanIt, class Key, class Comp>
size_t upper_bound_0(RanIt a, size_t n, const Key& key, Comp comp) {
return upper_bound_n<RanIt, Key, Comp>(a, 0, n, key, comp);
}
template <class Container, class Key>
size_t upper_bound_a(const Container& a, const Key& key) {
typedef typename Container::const_iterator RanIt;
return upper_bound_n<RanIt, Key>(a.begin(), 0, a.size(), key);
}
template <class Container, class Key, class Comp>
size_t upper_bound_a(const Container& a, const Key& key, Comp comp) {
typedef typename Container::const_iterator RanIt;
return upper_bound_n<RanIt, Key, Comp>(a.begin(), 0, a.size(), key, comp);
}
template <class RanIt, class Key>
std::pair<size_t, size_t> equal_range_0(RanIt a, size_t n, const Key& key) {
return equal_range_n<RanIt, Key>(a, 0, n, key);
}
template <class RanIt, class Key, class Comp>
std::pair<size_t, size_t> equal_range_0(RanIt a, size_t n, const Key& key,
Comp comp) {
return equal_range_n<RanIt, Key, Comp>(a, 0, n, key, comp);
}
template <class Container, class Key>
std::pair<size_t, size_t> equal_range_a(const Container& a, const Key& key) {
typedef typename Container::const_iterator RanIt;
return equal_range_n<RanIt, Key>(a.begin(), 0, a.size(), key);
}
template <class Container, class Key, class Comp>
std::pair<size_t, size_t> equal_range_a(const Container& a, const Key& key,
Comp comp) {
typedef typename Container::const_iterator RanIt;
return equal_range_n<RanIt, Key, Comp>(a.begin(), 0, a.size(), key, comp);
}
template <class RanIt, class Key>
bool binary_search_0(RanIt a, size_t n, const Key& key) {
return binary_search_n<RanIt, Key>(a, 0, n, key);
}
template <class RanIt, class Key, class Comp>
bool binary_search_0(RanIt a, size_t n, const Key& key, Comp comp) {
return binary_search_n<RanIt, Key, Comp>(a, 0, n, key, comp);
}
template <class Range, class Key>
bool binary_search_a(const Range& a, const Key& key) {
return binary_search_n(a.begin(), 0, a.size(), key);
}
template <class Range, class Key, class Comp>
bool binary_search_a(const Range& a, const Key& key, Comp comp) {
return binary_search_n(a.begin(), 0, a.size(), key, comp);
}
template <class RanIt>
void sort_0(RanIt a, size_t n) {
sort_n<RanIt>(a, 0, n);
}
template <class RanIt, class Comp>
void sort_0(RanIt a, size_t n, Comp comp) {
sort_n<RanIt, Comp>(a, 0, n, comp);
}
template <class Container>
void sort_a(Container& a) {
std::sort(std::begin(a), std::end(a));
}
template <class Container, class Comp>
void sort_a(Container& a, Comp comp) {
std::sort(std::begin(a), std::end(a), comp);
}
template <class RanIt>
void reverse_n(RanIt a, size_t low, size_t upp) {
std::reverse<RanIt>(a + low, a + upp);
}
template <class RanIt>
void reverse_0(RanIt a, size_t n) {
std::reverse<RanIt>(a + 0, a + n);
}
template <class Container>
void reverse_a(Container& a) {
std::reverse(a.begin(), a.end());
}
template <class Container>
void reverse_a(Container& a, size_t low, size_t upp) {
assert(low <= upp);
assert(upp <= a.size());
std::reverse(a.begin() + low, a.begin() + upp);
}
template <class RanIt>
size_t unique_n(RanIt a, size_t low, size_t upp) {
return std::unique<RanIt>(a + low, a + upp) - a;
}
template <class RanIt>
size_t unique_0(RanIt a, size_t n) {
return std::unique<RanIt>(a + 0, a + n) - a;
}
template <class Container>
size_t unique_a(Container& a) {
return std::unique(a.begin(), a.end()) - a.begin();
}
template <class Container, class Equal>
size_t unique_a(Container& a, Equal eq) {
return std::unique(a.begin(), a.end(), eq) - a.begin();
}
template <class Container>
size_t unique_a(Container& a, size_t low, size_t upp) {
assert(low <= upp);
assert(upp <= a.size());
return std::unique(a.begin() + low, a.begin() + upp) - low - a.begin();
}
template <class Container, class Equal>
size_t unique_a(Container& a, Equal eq, size_t low, size_t upp) {
assert(low <= upp);
assert(upp <= a.size());
return std::unique(a.begin() + low, a.begin() + upp, eq) - low - a.begin();
}
template <class RanIt, class KeyExtractor>
void sort_ex_n(RanIt a, size_t low, size_t upp, KeyExtractor keyEx) {
assert(low <= upp);
std::sort(a + low, a + upp, ExtractorLess(keyEx));
}
template <class RanIt, class KeyExtractor, class Comp>
void sort_ex_n(RanIt a, size_t low, size_t upp, KeyExtractor keyEx, Comp cmp) {
assert(low <= upp);
std::sort(a + low, a + upp, ExtractorComparator(keyEx, cmp));
}
template <class Container, class KeyExtractor>
void sort_ex_a(Container& a, KeyExtractor keyEx) {
std::sort(std::begin(a), std::end(a), ExtractorLess(keyEx));
}
template <class Container, class KeyExtractor, class Comp>
void sort_ex_a(Container& a, KeyExtractor keyEx, Comp cmp) {
std::sort(std::begin(a), std::end(a), ExtractorComparator(keyEx, cmp));
}
} // namespace bytedance_terark
#endif
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册