Fix tdutils after update.

GitOrigin-RevId: afc6d10dd0e2b2a7193dd2c96f07d5ca1cb11a00
This commit is contained in:
levlam 2019-07-21 21:07:07 +03:00
parent e54c0b0035
commit 635aca2924
49 changed files with 339 additions and 279 deletions

View File

@ -2652,13 +2652,15 @@ Result<FileId> FileManager::from_persistent_id_v23(Slice binary, FileType file_t
FileData data; FileData data;
data.remote_ = RemoteFileLocation(std::move(remote_location)); data.remote_ = RemoteFileLocation(std::move(remote_location));
auto file_id = auto file_id =
register_file(std::move(data), FileLocationSource::FromUser, "from_persistent_id_v2", false).move_as_ok(); register_file(std::move(data), FileLocationSource::FromUser, "from_persistent_id_v23", false).move_as_ok();
return file_id; return file_id;
} }
Result<FileId> FileManager::from_persistent_id_v2(Slice binary, FileType file_type) { Result<FileId> FileManager::from_persistent_id_v2(Slice binary, FileType file_type) {
binary.remove_suffix(1); binary.remove_suffix(1);
return from_persistent_id_v23(binary, file_type, 0); return from_persistent_id_v23(binary, file_type, 0);
} }
Result<FileId> FileManager::from_persistent_id_v3(Slice binary, FileType file_type) { Result<FileId> FileManager::from_persistent_id_v3(Slice binary, FileType file_type) {
binary.remove_suffix(1); binary.remove_suffix(1);
if (binary.empty()) { if (binary.empty()) {
@ -2676,6 +2678,7 @@ FileView FileManager::get_file_view(FileId file_id) const {
} }
return FileView(file_node); return FileView(file_node);
} }
FileView FileManager::get_sync_file_view(FileId file_id) { FileView FileManager::get_sync_file_view(FileId file_id) {
auto file_node = get_sync_file_node(file_id); auto file_node = get_sync_file_node(file_id);
if (!file_node) { if (!file_node) {

View File

@ -227,6 +227,7 @@ set(TDUTILS_SOURCE
td/utils/StorerBase.h td/utils/StorerBase.h
td/utils/StringBuilder.h td/utils/StringBuilder.h
td/utils/tests.h td/utils/tests.h
td/utils/ThreadSafeCounter.h
td/utils/Time.h td/utils/Time.h
td/utils/TimedStat.h td/utils/TimedStat.h
td/utils/Timer.h td/utils/Timer.h
@ -234,10 +235,9 @@ set(TDUTILS_SOURCE
td/utils/tl_parsers.h td/utils/tl_parsers.h
td/utils/tl_storers.h td/utils/tl_storers.h
td/utils/translit.h td/utils/translit.h
td/utils/ThreadSafeCounter.h
td/utils/type_traits.h td/utils/type_traits.h
td/utils/uint128.h
td/utils/UInt.h td/utils/UInt.h
td/utils/uint128.h
td/utils/unicode.h td/utils/unicode.h
td/utils/unique_ptr.h td/utils/unique_ptr.h
td/utils/utf8.h td/utils/utf8.h
@ -247,8 +247,8 @@ set(TDUTILS_SOURCE
set(TDUTILS_TEST_SOURCE set(TDUTILS_TEST_SOURCE
${CMAKE_CURRENT_SOURCE_DIR}/test/buffer.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/buffer.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/ConcurrentHashMap.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/crypto.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/Enumerator.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/Enumerator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/EpochBasedMemoryReclamation.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/EpochBasedMemoryReclamation.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test/filesystem.cpp
@ -300,7 +300,7 @@ if (CRC32C_FOUND)
target_link_libraries(tdutils PRIVATE crc32c) target_link_libraries(tdutils PRIVATE crc32c)
endif() endif()
if (ABSL_FOUND) if (ABSL_FOUND)
target_link_libraries(tdutils absl::base absl::container absl::hash) target_link_libraries(tdutils PUBLIC absl::base absl::container absl::hash)
endif() endif()
if (WIN32 AND WINGETOPT_FOUND) if (WIN32 AND WINGETOPT_FOUND)

View File

@ -14,6 +14,7 @@
#include <cstring> #include <cstring>
namespace td { namespace td {
class BufferedReader { class BufferedReader {
public: public:
explicit BufferedReader(FileFd &file, size_t buff_size = 8152) explicit BufferedReader(FileFd &file, size_t buff_size = 8152)
@ -58,4 +59,5 @@ inline Result<size_t> BufferedReader::read(MutableSlice slice) {
begin_pos_ += left; begin_pos_ += left;
return left + available; return left + available;
} }
} // namespace td } // namespace td

View File

@ -6,35 +6,37 @@
// //
#pragma once #pragma once
#include "td/utils/common.h"
#include "td/utils/HazardPointers.h" #include "td/utils/HazardPointers.h"
#include <mutex>
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>
#include <vector> #include <mutex>
namespace td {
// AtomicHashArray<KeyT, ValueT> // AtomicHashArray<KeyT, ValueT>
// Building block for other conurrent hash maps // Building block for other concurrent hash maps
// //
// Support one operation: // Support one operation:
// template <class F> // template <class F>
// bool with_value(KeyT key, bool should_create, F &&func); // bool with_value(KeyT key, bool should_create, F &&func);
// //
// Finds slot for key, and call func(value) // Finds slot for key, and call func(value)
// Creates slot if shoul_create is true. // Creates slot if should_create is true.
// Returns true if func was called. // Returns true if func was called.
// //
// Concurrent calls with same key may result in concurrent calls of func(value) // Concurrent calls with the same key may result in concurrent calls to func(value)
// It is resposibility of caller to handle such races. // It is responsibility of the caller to handle such races.
// //
// Key should already be random // Key should already be random
// It is resposibility of caller to provide unique random key. // It is responsibility of the caller to provide unique random key.
// One may use injective hash function, or handle collisions on some other way. // One may use injective hash function, or handle collisions in some other way.
namespace td {
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class AtomicHashArray { class AtomicHashArray {
public: public:
AtomicHashArray(size_t n) : nodes_(n) { explicit AtomicHashArray(size_t n) : nodes_(n) {
} }
struct Node { struct Node {
std::atomic<KeyT> key{KeyT{}}; std::atomic<KeyT> key{KeyT{}};
@ -54,7 +56,7 @@ class AtomicHashArray {
bool with_value(KeyT key, bool should_create, F &&f) { bool with_value(KeyT key, bool should_create, F &&f) {
DCHECK(key != empty_key()); DCHECK(key != empty_key());
size_t pos = static_cast<size_t>(key) % nodes_.size(); size_t pos = static_cast<size_t>(key) % nodes_.size();
size_t n = std::min(std::max(size_t(300), nodes_.size() / 16 + 2), nodes_.size()); size_t n = td::min(td::max(static_cast<size_t>(300), nodes_.size() / 16 + 2), nodes_.size());
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
pos++; pos++;
@ -93,10 +95,10 @@ class AtomicHashArray {
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ConcurrentHashMap { class ConcurrentHashMap {
using HashMap = AtomicHashArray<KeyT, std::atomic<ValueT>>; using HashMap = AtomicHashArray<KeyT, std::atomic<ValueT>>;
static td::HazardPointers<HashMap> hp_; static HazardPointers<HashMap> hp_;
public: public:
ConcurrentHashMap(size_t n = 32) { explicit ConcurrentHashMap(size_t n = 32) {
n = 1; n = 1;
hash_map_.store(make_unique<HashMap>(n).release()); hash_map_.store(make_unique<HashMap>(n).release());
} }
@ -105,7 +107,7 @@ class ConcurrentHashMap {
ConcurrentHashMap(ConcurrentHashMap &&) = delete; ConcurrentHashMap(ConcurrentHashMap &&) = delete;
ConcurrentHashMap &operator=(ConcurrentHashMap &&) = delete; ConcurrentHashMap &operator=(ConcurrentHashMap &&) = delete;
~ConcurrentHashMap() { ~ConcurrentHashMap() {
td::unique_ptr<HashMap>(hash_map_.load()); unique_ptr<HashMap>(hash_map_.load());
} }
static std::string get_name() { static std::string get_name() {
@ -156,6 +158,7 @@ class ConcurrentHashMap {
do_migrate(hash_map); do_migrate(hash_map);
} }
} }
ValueT find(KeyT key, ValueT value) { ValueT find(KeyT key, ValueT value) {
typename HazardPointers<HashMap>::Holder holder(hp_, get_thread_id(), 0); typename HazardPointers<HashMap>::Holder holder(hp_, get_thread_id(), 0);
while (true) { while (true) {
@ -173,6 +176,7 @@ class ConcurrentHashMap {
do_migrate(hash_map); do_migrate(hash_map);
} }
} }
template <class F> template <class F>
void for_each(F &&f) { void for_each(F &&f) {
auto hash_map = hash_map_.load(); auto hash_map = hash_map_.load();
@ -312,4 +316,5 @@ class ConcurrentHashMap {
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
td::HazardPointers<typename ConcurrentHashMap<KeyT, ValueT>::HashMap> ConcurrentHashMap<KeyT, ValueT>::hp_(64); td::HazardPointers<typename ConcurrentHashMap<KeyT, ValueT>::HashMap> ConcurrentHashMap<KeyT, ValueT>::hp_(64);
} // namespace td } // namespace td

View File

@ -151,7 +151,7 @@ class DecTree {
P.first = std::move(Tree); P.first = std::move(Tree);
return P; return P;
} }
} // namespace td }
static unique_ptr<Node> merge_node(unique_ptr<Node> left, unique_ptr<Node> right) { static unique_ptr<Node> merge_node(unique_ptr<Node> left, unique_ptr<Node> right) {
if (left == nullptr) { if (left == nullptr) {

View File

@ -5,12 +5,14 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/sleep.h" #include "td/utils/port/sleep.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
namespace td { namespace td {
template <class T> template <class T>
class EpochBasedMemoryReclamation { class EpochBasedMemoryReclamation {
public: public:
@ -18,6 +20,7 @@ class EpochBasedMemoryReclamation {
EpochBasedMemoryReclamation &operator=(const EpochBasedMemoryReclamation &other) = delete; EpochBasedMemoryReclamation &operator=(const EpochBasedMemoryReclamation &other) = delete;
EpochBasedMemoryReclamation(EpochBasedMemoryReclamation &&other) = delete; EpochBasedMemoryReclamation(EpochBasedMemoryReclamation &&other) = delete;
EpochBasedMemoryReclamation &operator=(EpochBasedMemoryReclamation &&other) = delete; EpochBasedMemoryReclamation &operator=(EpochBasedMemoryReclamation &&other) = delete;
~EpochBasedMemoryReclamation() = default;
class Locker { class Locker {
public: public:
@ -76,18 +79,17 @@ class EpochBasedMemoryReclamation {
size_t to_delete_size_unsafe() const { size_t to_delete_size_unsafe() const {
size_t res = 0; size_t res = 0;
for (auto &thread : threads_) { for (auto &thread_data : threads_) {
LOG(ERROR) << "---" << thread.epoch.load() / 2; // LOG(ERROR) << "---" << thread_data.epoch.load() / 2;
for (size_t i = 0; i < MAX_BAGS; i++) { for (size_t i = 0; i < MAX_BAGS; i++) {
res += thread.to_delete[i].size(); res += thread_data.to_delete[i].size();
LOG(ERROR) << thread.to_delete[i].size(); // LOG(ERROR) << thread_data.to_delete[i].size();
} }
} }
return res; return res;
} }
private: private:
friend class Locker;
static constexpr size_t MAX_BAGS = 3; static constexpr size_t MAX_BAGS = 3;
struct ThreadData { struct ThreadData {
std::atomic<int64> epoch{1}; std::atomic<int64> epoch{1};
@ -193,4 +195,5 @@ class EpochBasedMemoryReclamation {
data.to_delete[data.bag_i].push_back(unique_ptr<T>{ptr}); data.to_delete[data.bag_i].push_back(unique_ptr<T>{ptr});
} }
}; };
} // namespace td } // namespace td

View File

@ -134,17 +134,19 @@ Gzip::Gzip(Gzip &&other) : Gzip() {
} }
Gzip &Gzip::operator=(Gzip &&other) { Gzip &Gzip::operator=(Gzip &&other) {
CHECK(this != &other);
clear(); clear();
swap(other); swap(other);
return *this; return *this;
} }
void Gzip::swap(Gzip &other) { void Gzip::swap(Gzip &other) {
std::swap(impl_, other.impl_); using std::swap;
std::swap(input_size_, other.input_size_); swap(impl_, other.impl_);
std::swap(output_size_, other.output_size_); swap(input_size_, other.input_size_);
std::swap(close_input_flag_, other.close_input_flag_); swap(output_size_, other.output_size_);
std::swap(mode_, other.mode_); swap(close_input_flag_, other.close_input_flag_);
swap(mode_, other.mode_);
} }
Gzip::~Gzip() { Gzip::~Gzip() {

View File

@ -20,9 +20,9 @@ namespace td {
class Hasher { class Hasher {
public: public:
Hasher() = default; Hasher() = default;
Hasher(size_t init_value) : hash_(init_value) { explicit Hasher(size_t init_value) : hash_(init_value) {
} }
std::size_t finalize() { std::size_t finalize() const {
return hash_; return hash_;
} }
@ -34,7 +34,7 @@ class Hasher {
template <class A, class B> template <class A, class B>
static Hasher combine(Hasher hasher, const std::pair<A, B> &value) { static Hasher combine(Hasher hasher, const std::pair<A, B> &value) {
hasher = AbslHashValue(std::move(hasher), value.first); hasher = AbslHashValue(std::move(hasher), value.first);
hasher = AbslHashValue(std::move(hasher), value.first); hasher = AbslHashValue(std::move(hasher), value.second);
return hasher; return hasher;
} }

View File

@ -13,7 +13,9 @@
#else #else
#include <unordered_map> #include <unordered_map>
#endif #endif
namespace td { namespace td {
#if TD_HAVE_ABSL #if TD_HAVE_ABSL
template <class Key, class Value, class H = Hash<Key>> template <class Key, class Value, class H = Hash<Key>>
using HashMap = absl::flat_hash_map<Key, Value, H>; using HashMap = absl::flat_hash_map<Key, Value, H>;
@ -21,4 +23,5 @@ using HashMap = absl::flat_hash_map<Key, Value, H>;
template <class Key, class Value, class H = Hash<Key>> template <class Key, class Value, class H = Hash<Key>>
using HashMap = std::unordered_map<Key, Value, H>; using HashMap = std::unordered_map<Key, Value, H>;
#endif #endif
} // namespace td } // namespace td

View File

@ -13,7 +13,9 @@
#else #else
#include <unordered_set> #include <unordered_set>
#endif #endif
namespace td { namespace td {
#if TD_HAVE_ABSL #if TD_HAVE_ABSL
template <class Key, class H = Hash<Key>> template <class Key, class H = Hash<Key>>
using HashSet = absl::flat_hash_set<Key, H>; using HashSet = absl::flat_hash_set<Key, H>;
@ -21,4 +23,5 @@ using HashSet = absl::flat_hash_set<Key, H>;
template <class Key, class H = Hash<Key>> template <class Key, class H = Hash<Key>>
using HashSet = std::unordered_set<Key, H>; using HashSet = std::unordered_set<Key, H>;
#endif #endif
} // namespace td } // namespace td

View File

@ -19,7 +19,7 @@ class HazardPointers {
public: public:
explicit HazardPointers(size_t threads_n) : threads_(threads_n) { explicit HazardPointers(size_t threads_n) : threads_(threads_n) {
for (auto &data : threads_) { for (auto &data : threads_) {
for (auto &ptr : data.hazard) { for (auto &ptr : data.hazard_) {
// workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658 // workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=64658
#if TD_GCC && GCC_VERSION <= 40902 #if TD_GCC && GCC_VERSION <= 40902
ptr = nullptr; ptr = nullptr;
@ -66,12 +66,12 @@ class HazardPointers {
CHECK(thread_id < threads_.size()); CHECK(thread_id < threads_.size());
auto &data = threads_[thread_id]; auto &data = threads_[thread_id];
if (ptr) { if (ptr) {
data.to_delete.push_back(std::unique_ptr<T, Deleter>(ptr)); data.to_delete_.push_back(std::unique_ptr<T, Deleter>(ptr));
} }
for (auto it = data.to_delete.begin(); it != data.to_delete.end();) { for (auto it = data.to_delete_.begin(); it != data.to_delete_.end();) {
if (!is_protected(it->get())) { if (!is_protected(it->get())) {
it->reset(); it->reset();
it = data.to_delete.erase(it); it = data.to_delete_.erase(it);
} else { } else {
++it; ++it;
} }
@ -89,19 +89,19 @@ class HazardPointers {
size_t to_delete_size_unsafe() const { size_t to_delete_size_unsafe() const {
size_t res = 0; size_t res = 0;
for (auto &thread : threads_) { for (auto &thread : threads_) {
res += thread.to_delete.size(); res += thread.to_delete_.size();
} }
return res; return res;
} }
private: private:
struct ThreadData { struct ThreadData {
std::array<std::atomic<T *>, MaxPointersN> hazard; std::array<std::atomic<T *>, MaxPointersN> hazard_;
char pad[TD_CONCURRENCY_PAD - sizeof(hazard)]; char pad[TD_CONCURRENCY_PAD - sizeof(hazard_)];
// stupid gc // stupid gc
std::vector<std::unique_ptr<T, Deleter>> to_delete; std::vector<std::unique_ptr<T, Deleter>> to_delete_;
char pad2[TD_CONCURRENCY_PAD - sizeof(to_delete)]; char pad2[TD_CONCURRENCY_PAD - sizeof(to_delete_)];
}; };
std::vector<ThreadData> threads_; std::vector<ThreadData> threads_;
char pad2[TD_CONCURRENCY_PAD - sizeof(threads_)]; char pad2[TD_CONCURRENCY_PAD - sizeof(threads_)];
@ -123,7 +123,7 @@ class HazardPointers {
bool is_protected(T *ptr) { bool is_protected(T *ptr) {
for (auto &thread : threads_) { for (auto &thread : threads_) {
for (auto &hazard_ptr : thread.hazard) { for (auto &hazard_ptr : thread.hazard_) {
if (hazard_ptr.load() == ptr) { if (hazard_ptr.load() == ptr) {
return true; return true;
} }
@ -134,7 +134,7 @@ class HazardPointers {
std::atomic<T *> &get_hazard_ptr(size_t thread_id, size_t pos) { std::atomic<T *> &get_hazard_ptr(size_t thread_id, size_t pos) {
CHECK(thread_id < threads_.size()); CHECK(thread_id < threads_.size());
return threads_[thread_id].hazard[pos]; return threads_[thread_id].hazard_[pos];
} }
}; };

View File

@ -5,6 +5,11 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#include "td/utils/MpmcQueue.h" #include "td/utils/MpmcQueue.h"
namespace td { namespace td {
detail::MpmcStat stat_; namespace detail {
}
MpmcStat stat_;
} // namespace detail
} // namespace td

View File

@ -23,6 +23,7 @@
namespace td { namespace td {
namespace detail { namespace detail {
struct MpmcStat { struct MpmcStat {
void alloc_ok(size_t thread_id) { void alloc_ok(size_t thread_id) {
s(thread_id).alloc_ok_cnt++; s(thread_id).alloc_ok_cnt++;
@ -64,13 +65,15 @@ struct MpmcStat {
return arr[thread_id]; return arr[thread_id];
} }
}; };
extern MpmcStat stat_;
} // namespace detail } // namespace detail
extern detail::MpmcStat stat_;
template <class T> template <class T>
class OneValue { class OneValue {
public: public:
inline bool set_value(T &value) { bool set_value(T &value) {
value_ = std::move(value); value_ = std::move(value);
int state = Empty; int state = Empty;
if (state_.compare_exchange_strong(state, Value, std::memory_order_acq_rel)) { if (state_.compare_exchange_strong(state, Value, std::memory_order_acq_rel)) {
@ -79,7 +82,7 @@ class OneValue {
value = std::move(value_); value = std::move(value_);
return false; return false;
} }
inline bool get_value(T &value) { bool get_value(T &value) {
auto old_state = state_.exchange(Taken, std::memory_order_acq_rel); auto old_state = state_.exchange(Taken, std::memory_order_acq_rel);
if (old_state == Value) { if (old_state == Value) {
value = std::move(value_); value = std::move(value_);

View File

@ -7,8 +7,8 @@
#pragma once #pragma once
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/port/thread.h"
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/thread.h"
#include <atomic> #include <atomic>
#include <condition_variable> #include <condition_variable>

View File

@ -16,6 +16,7 @@
#endif #endif
namespace td { namespace td {
void OptionsParser::set_description(std::string description) { void OptionsParser::set_description(std::string description) {
description_ = std::move(description); description_ = std::move(description);
} }

View File

@ -12,7 +12,6 @@
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include <functional> #include <functional>
#include <string>
namespace td { namespace td {

View File

@ -9,7 +9,6 @@
#include "td/utils/common.h" #include "td/utils/common.h"
#include <type_traits> #include <type_traits>
#include <limits>
namespace td { namespace td {
@ -59,7 +58,7 @@ class MutableSlice {
char &back(); char &back();
char &operator[](size_t i); char &operator[](size_t i);
static const size_t npos = std::numeric_limits<size_t>::max(); static const size_t npos = string::npos;
}; };
class Slice { class Slice {
@ -124,7 +123,7 @@ class Slice {
char back() const; char back() const;
char operator[](size_t i) const; char operator[](size_t i) const;
static const size_t npos = std::numeric_limits<size_t>::max(); static const size_t npos = string::npos;
}; };
bool operator==(const Slice &a, const Slice &b); bool operator==(const Slice &a, const Slice &b);

View File

@ -57,7 +57,7 @@ class SpanImpl {
return false; return false;
} }
for (size_t i = 0; i < size(); i++) { for (size_t i = 0; i < size(); i++) {
if ((*this)[i] != other[i]) { if (!((*this)[i] == other[i])) {
return false; return false;
} }
} }
@ -115,11 +115,11 @@ template <class T>
using MutableSpan = detail::SpanImpl<T, T>; using MutableSpan = detail::SpanImpl<T, T>;
template <class T> template <class T>
auto span(const T *ptr, size_t size) { Span<T> span(const T *ptr, size_t size) {
return Span<T>(ptr, size); return Span<T>(ptr, size);
} }
template <class T> template <class T>
auto mutable_span(T *ptr, size_t size) { MutableSpan<T> mutable_span(T *ptr, size_t size) {
return MutableSpan<T>(ptr, size); return MutableSpan<T>(ptr, size);
} }

View File

@ -27,6 +27,7 @@
return try_status.move_as_error(); \ return try_status.move_as_error(); \
} \ } \
} }
#define TRY_STATUS_PREFIX(status, prefix) \ #define TRY_STATUS_PREFIX(status, prefix) \
{ \ { \
auto try_status = (status); \ auto try_status = (status); \
@ -34,7 +35,9 @@
return try_status.move_as_error_prefix(prefix); \ return try_status.move_as_error_prefix(prefix); \
} \ } \
} }
#define TRY_RESULT(name, result) TRY_RESULT_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result) #define TRY_RESULT(name, result) TRY_RESULT_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result)
#define TRY_RESULT_PREFIX(name, result, prefix) \ #define TRY_RESULT_PREFIX(name, result, prefix) \
TRY_RESULT_PREFIX_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result, prefix) TRY_RESULT_PREFIX_IMPL(TD_CONCAT(TD_CONCAT(r_, name), __LINE__), name, result, prefix)
@ -264,8 +267,18 @@ class Status {
return std::move(*this); return std::move(*this);
} }
Status move_as_error_prefix(std::string prefix) TD_WARN_UNUSED_RESULT { Status move_as_error_prefix(Slice prefix) TD_WARN_UNUSED_RESULT {
return td::Status::Error(code(), prefix + message().c_str()); CHECK(is_error());
Info info = get_info();
switch (info.error_type) {
case ErrorType::general:
return Error(code(), PSLICE() << prefix << message());
case ErrorType::os:
return Status(false, ErrorType::os, code(), PSLICE() << prefix << message());
default:
UNREACHABLE();
return {};
}
} }
private: private:
@ -438,10 +451,9 @@ class Result {
}; };
return std::move(status_); return std::move(status_);
} }
Status move_as_error_prefix(std::string prefix) TD_WARN_UNUSED_RESULT { Status move_as_error_prefix(Slice prefix) TD_WARN_UNUSED_RESULT {
CHECK(status_.is_error());
SCOPE_EXIT { SCOPE_EXIT {
status_ = Status::Error<-4>(); status_ = Status::Error<-5>();
}; };
return status_.move_as_error_prefix(prefix); return status_.move_as_error_prefix(prefix);
} }

View File

@ -5,14 +5,16 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
#include "td/utils/int_types.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include "td/utils/port/thread_local.h" #include "td/utils/port/thread_local.h"
#include "td/utils/int_types.h"
#include <atomic>
#include <array> #include <array>
#include <atomic>
namespace td { namespace td {
class ThreadSafeCounter { class ThreadSafeCounter {
public: public:
void add(int64 diff) { void add(int64 diff) {
@ -40,8 +42,9 @@ class ThreadSafeCounter {
Node &thread_local_node() { Node &thread_local_node() {
auto thread_id = get_thread_id(); auto thread_id = get_thread_id();
CHECK(0 <= thread_id && static_cast<size_t>(thread_id) < nodes_.size()); CHECK(static_cast<size_t>(thread_id) < nodes_.size());
return nodes_[thread_id]; return nodes_[thread_id];
} }
}; };
} // namespace td } // namespace td

View File

@ -9,8 +9,6 @@
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/port/Clocks.h" #include "td/utils/port/Clocks.h"
#include <atomic>
namespace td { namespace td {
class Time { class Time {
@ -75,8 +73,8 @@ class Timestamp {
double at() const { double at() const {
return at_; return at_;
} }
double at_unix() { double at_unix() const {
return at_ + td::Clocks::system() - Time::now(); return at_ + Clocks::system() - Time::now();
} }
double in() const { double in() const {

View File

@ -19,6 +19,7 @@ Timer::Timer() : start_time_(Time::now()) {
double Timer::elapsed() const { double Timer::elapsed() const {
return Time::now() - start_time_; return Time::now() - start_time_;
} }
StringBuilder &operator<<(StringBuilder &string_builder, const Timer &timer) { StringBuilder &operator<<(StringBuilder &string_builder, const Timer &timer) {
return string_builder << "in " << Time::now() - timer.start_time_; return string_builder << "in " << Time::now() - timer.start_time_;
} }
@ -35,6 +36,7 @@ PerfWarningTimer::PerfWarningTimer(PerfWarningTimer &&other)
PerfWarningTimer::~PerfWarningTimer() { PerfWarningTimer::~PerfWarningTimer() {
reset(); reset();
} }
void PerfWarningTimer::reset() { void PerfWarningTimer::reset() {
if (start_at_ == 0) { if (start_at_ == 0) {
return; return;

View File

@ -13,6 +13,7 @@ namespace td {
class Timer { class Timer {
public: public:
Timer(); Timer();
double elapsed() const; double elapsed() const;
private: private:

View File

@ -5,8 +5,8 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/check.h"
#if TD_MSVC #if TD_MSVC
#include <intrin.h> #include <intrin.h>
@ -19,7 +19,9 @@
#ifdef bswap64 #ifdef bswap64
#undef bswap64 #undef bswap64
#endif #endif
namespace td { namespace td {
int32 count_leading_zeroes32(uint32 x); int32 count_leading_zeroes32(uint32 x);
int32 count_leading_zeroes64(uint64 x); int32 count_leading_zeroes64(uint64 x);
int32 count_trailing_zeroes32(uint32 x); int32 count_trailing_zeroes32(uint32 x);
@ -119,9 +121,11 @@ inline int32 count_trailing_zeroes64(uint64 x) {
inline uint32 bswap32(uint32 x) { inline uint32 bswap32(uint32 x) {
return _byteswap_ulong(x); return _byteswap_ulong(x);
} }
inline uint64 bswap64(uint64 x) { inline uint64 bswap64(uint64 x) {
return _byteswap_uint64(x); return _byteswap_uint64(x);
} }
inline int32 count_bits32(uint32 x) { inline int32 count_bits32(uint32 x) {
return __popcnt(x); return __popcnt(x);
} }
@ -247,4 +251,5 @@ inline int32 count_bits64(uint64 x) {
} }
#endif #endif
} // namespace td } // namespace td

View File

@ -469,6 +469,7 @@ void hmac_sha256(Slice key, Slice message, MutableSlice dest) {
CHECK(result == dest.ubegin()); CHECK(result == dest.ubegin());
CHECK(len == dest.size()); CHECK(len == dest.size());
} }
void hmac_sha512(Slice key, Slice message, MutableSlice dest) { void hmac_sha512(Slice key, Slice message, MutableSlice dest) {
CHECK(dest.size() == 512 / 8); CHECK(dest.size() == 512 / 8);
unsigned int len = 0; unsigned int len = 0;
@ -657,8 +658,9 @@ uint32 crc32c_extend(uint32 old_crc, Slice data) {
} }
namespace { namespace {
unsigned gf32_matrix_times(uint32 *matrix, uint32 vector) {
unsigned sum = 0; uint32 gf32_matrix_times(const uint32 *matrix, uint32 vector) {
uint32 sum = 0;
while (vector) { while (vector) {
if (vector & 1) { if (vector & 1) {
sum ^= *matrix; sum ^= *matrix;
@ -669,36 +671,36 @@ unsigned gf32_matrix_times(uint32 *matrix, uint32 vector) {
return sum; return sum;
} }
void gf32_matrix_square(uint32 *square, uint32 *matrix) { void gf32_matrix_square(uint32 *square, const uint32 *matrix) {
int n = 0; for (int n = 0; n < 32; n++) {
do {
square[n] = gf32_matrix_times(matrix, matrix[n]); square[n] = gf32_matrix_times(matrix, matrix[n]);
} while (++n < 32); }
} }
} // namespace } // namespace
static uint32 power_buf_raw[1024];
uint32 crc32c_extend(uint32 old_crc, uint32 data_crc, size_t data_size) { uint32 crc32c_extend(uint32 old_crc, uint32 data_crc, size_t data_size) {
static uint32 *power_buf = [&] { static uint32 power_buf_raw[1024];
static const uint32 *power_buf = [&] {
auto *buf = power_buf_raw; auto *buf = power_buf_raw;
buf[0] = 0x82F63B78UL; buf[0] = 0x82F63B78u;
for (int n = 0; n < 31; n++) { for (int n = 0; n < 31; n++) {
buf[n + 1] = 1U << n; buf[n + 1] = 1u << n;
} }
for (int n = 1; n < 32; n++) { for (int n = 1; n < 32; n++) {
gf32_matrix_square(buf + (n << 5), buf + ((n - 1) << 5)); gf32_matrix_square(buf + (n << 5), buf + ((n - 1) << 5));
} }
return buf; return buf;
}(); }();
/* degenerate case (also disallow negative lengths) */
if (data_size == 0) { if (data_size == 0) {
return old_crc; return old_crc;
} }
unsigned int *p = power_buf + 64; const uint32 *p = power_buf + 64;
do { do {
p += 32; p += 32;
if (data_size % 2 != 0) { if (data_size & 1) {
old_crc = gf32_matrix_times(p, old_crc); old_crc = gf32_matrix_times(p, old_crc);
} }
data_size >>= 1; data_size >>= 1;
@ -774,7 +776,7 @@ uint64 crc64(Slice data) {
return crc64_partial(data, static_cast<uint64>(-1)) ^ static_cast<uint64>(-1); return crc64_partial(data, static_cast<uint64>(-1)) ^ static_cast<uint64>(-1);
} }
static unsigned short crc16_table[256] = { static const uint16 crc16_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7, 0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad,
0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a, 0xe1ce, 0xf1ef, 0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6, 0x9339, 0x8318, 0xb37b, 0xa35a,
0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de, 0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485, 0xa56a, 0xb54b,
@ -795,13 +797,13 @@ static unsigned short crc16_table[256] = {
0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x1ce0, 0x0cc1, 0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8, 0x6e17, 0x7e36, 0x4e55, 0x5e74,
0x2e93, 0x3eb2, 0x0ed1, 0x1ef0}; 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0};
td::uint16 crc16(td::Slice data) { uint16 crc16(Slice data) {
unsigned crc = 0; uint32 crc = 0;
for (std::size_t i = 0; i < data.size(); i++) { for (auto c : data) {
unsigned t = ((unsigned char)data[i] ^ (crc >> 8)) & 0xff; auto t = (static_cast<unsigned char>(c) ^ (crc >> 8)) & 0xff;
crc = crc16_table[t] ^ (crc << 8); crc = crc16_table[t] ^ (crc << 8);
} }
return (td::uint16)crc; return static_cast<uint16>(crc);
} }
} // namespace td } // namespace td

View File

@ -226,7 +226,7 @@ class DefaultLog : public LogInterface {
break; break;
} }
if (!slice.empty() && slice.back() == '\n') { if (!slice.empty() && slice.back() == '\n') {
TsCerr() << color << slice.substr(0, slice.size() - 1) << TC_EMPTY << "\n"; TsCerr() << color << slice.substr(0, slice.size() - 1) << TC_EMPTY "\n";
} else { } else {
TsCerr() << color << slice << TC_EMPTY; TsCerr() << color << slice << TC_EMPTY;
} }

View File

@ -171,7 +171,7 @@ bool is_zero_or_one(unsigned char c) {
string buffer_to_hex(Slice buffer) { string buffer_to_hex(Slice buffer) {
const char *hex = "0123456789ABCDEF"; const char *hex = "0123456789ABCDEF";
std::string res(2 * buffer.size(), '\0'); string res(2 * buffer.size(), '\0');
for (std::size_t i = 0; i < buffer.size(); i++) { for (std::size_t i = 0; i < buffer.size(); i++) {
auto c = buffer.ubegin()[i]; auto c = buffer.ubegin()[i];
res[2 * i] = hex[c & 15]; res[2 * i] = hex[c & 15];

View File

@ -16,7 +16,6 @@
#include <limits> #include <limits>
#include <type_traits> #include <type_traits>
#include <utility> #include <utility>
#include <string>
namespace td { namespace td {
@ -310,8 +309,8 @@ string url_encode(Slice str);
namespace detail { namespace detail {
template <class T, class U> template <class T, class U>
struct is_same_signedness : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> { struct is_same_signedness
}; : public std::integral_constant<bool, std::is_signed<T>::value == std::is_signed<U>::value> {};
template <class T, class Enable = void> template <class T, class Enable = void>
struct safe_undeflying_type { struct safe_undeflying_type {

View File

@ -137,12 +137,12 @@ Result<FileFd> FileFd::open(CSlice filepath, int32 flags, int32 mode) {
native_flags |= O_APPEND; native_flags |= O_APPEND;
} }
if (flags & Direct) {
#if TD_LINUX #if TD_LINUX
LOG(ERROR) << "DIRECT"; if (flags & Direct) {
native_flags |= O_DIRECT; native_flags |= O_DIRECT;
#endif
} }
#endif
int native_fd = detail::skip_eintr([&] { return ::open(filepath.c_str(), native_flags, static_cast<mode_t>(mode)); }); int native_fd = detail::skip_eintr([&] { return ::open(filepath.c_str(), native_flags, static_cast<mode_t>(mode)); });
if (native_fd < 0) { if (native_fd < 0) {
return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags}); return OS_ERROR(PSLICE() << "File \"" << filepath << "\" can't be " << PrintFlags{flags});

View File

@ -11,8 +11,8 @@
#include "td/utils/common.h" #include "td/utils/common.h"
#include "td/utils/port/detail/NativeFd.h" #include "td/utils/port/detail/NativeFd.h"
#include "td/utils/port/detail/PollableFd.h" #include "td/utils/port/detail/PollableFd.h"
#include "td/utils/port/Stat.h"
#include "td/utils/port/IoSlice.h" #include "td/utils/port/IoSlice.h"
#include "td/utils/port/Stat.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Span.h" #include "td/utils/Span.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"

View File

@ -7,28 +7,36 @@
#pragma once #pragma once
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Span.h"
#if TD_PORT_POSIX #if TD_PORT_POSIX
#include <sys/uio.h> #include <sys/uio.h>
#endif #endif
namespace td { namespace td {
#if TD_PORT_POSIX #if TD_PORT_POSIX
using IoSlice = struct iovec; using IoSlice = struct iovec;
inline IoSlice as_io_slice(Slice slice) { inline IoSlice as_io_slice(Slice slice) {
IoSlice res; IoSlice res;
res.iov_len = slice.size(); res.iov_len = slice.size();
res.iov_base = const_cast<char *>(slice.data()); res.iov_base = const_cast<char *>(slice.data());
return res; return res;
} }
inline Slice as_slice(const IoSlice io_slice) { inline Slice as_slice(const IoSlice io_slice) {
return Slice(reinterpret_cast<const char *>(io_slice.iov_base), io_slice.iov_len); return Slice(static_cast<const char *>(io_slice.iov_base), io_slice.iov_len);
} }
#else #else
using IoSlice = Slice; using IoSlice = Slice;
inline IoSlice as_io_slice(Slice slice) { inline IoSlice as_io_slice(Slice slice) {
return slice; return slice;
} }
#endif #endif
} // namespace td } // namespace td

View File

@ -10,8 +10,9 @@
// TODO: // TODO:
// windows, // windows,
// anonymous map // anonymous maps,
// huge pages? // huge pages?
#if TD_WINDOWS #if TD_WINDOWS
#else #else
#include <sys/mman.h> #include <sys/mman.h>
@ -19,10 +20,10 @@
#endif #endif
namespace td { namespace td {
namespace detail {
class MemoryMappingImpl { class MemoryMapping::Impl {
public: public:
MemoryMappingImpl(MutableSlice data, int64 offset) : data_(data), offset_(offset) { Impl(MutableSlice data, int64 offset) : data_(data), offset_(offset) {
} }
Slice as_slice() const { Slice as_slice() const {
return data_.substr(narrow_cast<size_t>(offset_)); return data_.substr(narrow_cast<size_t>(offset_));
@ -36,7 +37,7 @@ class MemoryMappingImpl {
int64 offset_; int64 offset_;
}; };
Result<int64> get_page_size() { static Result<int64> get_page_size() {
#if TD_WINDOWS #if TD_WINDOWS
return Status::Error("Unimplemented"); return Status::Error("Unimplemented");
#else #else
@ -50,11 +51,11 @@ Result<int64> get_page_size() {
return page_size.clone(); return page_size.clone();
#endif #endif
} }
} // namespace detail
Result<MemoryMapping> MemoryMapping::create_anonymous(const MemoryMapping::Options &options) { Result<MemoryMapping> MemoryMapping::create_anonymous(const MemoryMapping::Options &options) {
return Status::Error("Unsupported yet"); return Status::Error("Unsupported yet");
} }
Result<MemoryMapping> MemoryMapping::create_from_file(const FileFd &file_fd, const MemoryMapping::Options &options) { Result<MemoryMapping> MemoryMapping::create_from_file(const FileFd &file_fd, const MemoryMapping::Options &options) {
#if TD_WINDOWS #if TD_WINDOWS
return Status::Error("Unsupported yet"); return Status::Error("Unsupported yet");
@ -76,7 +77,7 @@ Result<MemoryMapping> MemoryMapping::create_from_file(const FileFd &file_fd, con
end = begin + stat.size_; end = begin + stat.size_;
} }
TRY_RESULT(page_size, detail::get_page_size()); TRY_RESULT(page_size, get_page_size());
auto fixed_begin = begin / page_size * page_size; auto fixed_begin = begin / page_size * page_size;
auto data_offset = begin - fixed_begin; auto data_offset = begin - fixed_begin;
@ -87,8 +88,7 @@ Result<MemoryMapping> MemoryMapping::create_from_file(const FileFd &file_fd, con
return OS_ERROR("mmap call failed"); return OS_ERROR("mmap call failed");
} }
return MemoryMapping(std::make_unique<detail::MemoryMappingImpl>( return MemoryMapping(make_unique<Impl>(MutableSlice(static_cast<char *>(data), data_size), data_offset));
MutableSlice(reinterpret_cast<char *>(data), data_size), data_offset));
#endif #endif
} }
@ -96,14 +96,15 @@ MemoryMapping::MemoryMapping(MemoryMapping &&other) = default;
MemoryMapping &MemoryMapping::operator=(MemoryMapping &&other) = default; MemoryMapping &MemoryMapping::operator=(MemoryMapping &&other) = default;
MemoryMapping::~MemoryMapping() = default; MemoryMapping::~MemoryMapping() = default;
MemoryMapping::MemoryMapping(std::unique_ptr<detail::MemoryMappingImpl> impl) : impl_(std::move(impl)) { MemoryMapping::MemoryMapping(unique_ptr<Impl> impl) : impl_(std::move(impl)) {
} }
Slice MemoryMapping::as_slice() const { Slice MemoryMapping::as_slice() const {
return impl_->as_slice(); return impl_->as_slice();
} }
MutableSlice MemoryMapping::as_mutable_slice() { MutableSlice MemoryMapping::as_mutable_slice() {
return impl_->as_mutable_slice(); return impl_->as_mutable_slice();
} }
} // namespace td } // namespace td

View File

@ -12,9 +12,6 @@
#include "td/utils/Status.h" #include "td/utils/Status.h"
namespace td { namespace td {
namespace detail {
class MemoryMappingImpl;
}
class MemoryMapping { class MemoryMapping {
public: public:
@ -47,7 +44,9 @@ class MemoryMapping {
~MemoryMapping(); ~MemoryMapping();
private: private:
std::unique_ptr<detail::MemoryMappingImpl> impl_; class Impl;
explicit MemoryMapping(std::unique_ptr<detail::MemoryMappingImpl> impl); unique_ptr<Impl> impl_;
explicit MemoryMapping(unique_ptr<Impl> impl);
}; };
} // namespace td } // namespace td

View File

@ -10,8 +10,8 @@
#include "td/utils/port/detail/NativeFd.h" #include "td/utils/port/detail/NativeFd.h"
#include "td/utils/port/detail/PollableFd.h" #include "td/utils/port/detail/PollableFd.h"
#include "td/utils/port/IPAddress.h"
#include "td/utils/port/IoSlice.h" #include "td/utils/port/IoSlice.h"
#include "td/utils/port/IPAddress.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Span.h" #include "td/utils/Span.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"

View File

@ -125,7 +125,6 @@ class BufferedStdinImpl : public Iocp::Callback {
inc_refcnt(); inc_refcnt();
} }
} }
LOG(ERROR) << "Close";
if (!iocp_ref_.post(0, this, nullptr)) { if (!iocp_ref_.post(0, this, nullptr)) {
dec_refcnt(); dec_refcnt();
} }
@ -138,7 +137,6 @@ class BufferedStdinImpl : public Iocp::Callback {
bool dec_refcnt() { bool dec_refcnt() {
if (--refcnt_ == 0) { if (--refcnt_ == 0) {
delete this; delete this;
LOG(ERROR) << "Delete this";
return true; return true;
} }
return false; return false;

View File

@ -652,7 +652,7 @@ class UdpSocketFdImpl {
//}; //};
struct std::array<detail::UdpSocketSendHelper, 16> helpers; struct std::array<detail::UdpSocketSendHelper, 16> helpers;
struct std::array<struct mmsghdr, 16> headers; struct std::array<struct mmsghdr, 16> headers;
size_t to_send = td::min(messages.size(), headers.size()); size_t to_send = min(messages.size(), headers.size());
for (size_t i = 0; i < to_send; i++) { for (size_t i = 0; i < to_send; i++) {
helpers[i].to_native(messages[i], headers[i].msg_hdr); helpers[i].to_native(messages[i], headers[i].msg_hdr);
headers[i].msg_len = 0; headers[i].msg_len = 0;
@ -703,7 +703,7 @@ class UdpSocketFdImpl {
//}; //};
struct std::array<detail::UdpSocketReceiveHelper, 16> helpers; struct std::array<detail::UdpSocketReceiveHelper, 16> helpers;
struct std::array<struct mmsghdr, 16> headers; struct std::array<struct mmsghdr, 16> headers;
size_t to_receive = td::min(messages.size(), headers.size()); size_t to_receive = min(messages.size(), headers.size());
for (size_t i = 0; i < to_receive; i++) { for (size_t i = 0; i < to_receive; i++) {
helpers[i].to_native(messages[i], headers[i].msg_hdr); helpers[i].to_native(messages[i], headers[i].msg_hdr);
headers[i].msg_len = 0; headers[i].msg_len = 0;
@ -786,29 +786,20 @@ const NativeFd &UdpSocketFd::get_native_fd() const {
} }
#if TD_PORT_POSIX #if TD_PORT_POSIX
td::Result<td::uint32> UdpSocketFd::maximize_snd_buffer(td::uint32 max) { static Result<uint32> maximize_buffer(int socket_fd, int optname, uint32 max) {
socklen_t intsize = sizeof(td::uint32);
td::uint32 last_good = 0;
td::uint32 min, avg;
td::uint32 old_size;
auto socket_fd = get_native_fd().fd();
if (!max) {
max = default_udp_max_snd_buffer_size;
}
/* Start with the default size. */ /* Start with the default size. */
if (getsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, &old_size, &intsize)) { uint32 old_size;
return td::Status::PosixError(errno, "getsockopt() failed"); socklen_t intsize = sizeof(old_size);
if (getsockopt(socket_fd, SOL_SOCKET, optname, &old_size, &intsize)) {
return OS_ERROR("getsockopt() failed");
} }
/* Binary-search for the real maximum. */ /* Binary-search for the real maximum. */
min = last_good = old_size; uint32 last_good = old_size;
uint32 min = old_size;
while (min <= max) { while (min <= max) {
avg = (min + max) / 2; uint32 avg = min + (max - min) / 2;
if (setsockopt(socket_fd, SOL_SOCKET, SO_SNDBUF, &avg, intsize) == 0) { if (setsockopt(socket_fd, SOL_SOCKET, optname, &avg, intsize) == 0) {
last_good = avg; last_good = avg;
min = avg + 1; min = avg + 1;
} else { } else {
@ -818,42 +809,18 @@ td::Result<td::uint32> UdpSocketFd::maximize_snd_buffer(td::uint32 max) {
return last_good; return last_good;
} }
td::Result<td::uint32> UdpSocketFd::maximize_rcv_buffer(td::uint32 max) { Result<uint32> UdpSocketFd::maximize_snd_buffer(uint32 max) {
socklen_t intsize = sizeof(td::uint32); return maximize_buffer(get_native_fd().fd(), SO_SNDBUF, max == 0 ? default_udp_max_snd_buffer_size : max);
td::uint32 last_good = 0;
td::uint32 min, avg;
td::uint32 old_size;
auto socket_fd = get_native_fd().fd();
if (!max) {
max = default_udp_max_rcv_buffer_size;
} }
/* Start with the default size. */ Result<uint32> UdpSocketFd::maximize_rcv_buffer(uint32 max) {
if (getsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &old_size, &intsize)) { return maximize_buffer(get_native_fd().fd(), SO_RCVBUF, max == 0 ? default_udp_max_rcv_buffer_size : max);
return td::Status::PosixError(errno, "getsockopt() failed");
}
/* Binary-search for the real maximum. */
min = last_good = old_size;
while (min <= max) {
avg = (min + max) / 2;
if (setsockopt(socket_fd, SOL_SOCKET, SO_RCVBUF, &avg, intsize) == 0) {
last_good = avg;
min = avg + 1;
} else {
max = avg - 1;
}
}
return last_good;
} }
#else #else
td::Result<td::uint32> UdpSocketFd::maximize_snd_buffer(td::uint32 max) { Result<uint32> UdpSocketFd::maximize_snd_buffer(uint32 max) {
return 0; return 0;
} }
td::Result<td::uint32> UdpSocketFd::maximize_rcv_buffer(td::uint32 max) { Result<uint32> UdpSocketFd::maximize_rcv_buffer(uint32 max) {
return 0; return 0;
} }
#endif #endif

View File

@ -45,8 +45,8 @@ class UdpSocketFd {
UdpSocketFd(const UdpSocketFd &) = delete; UdpSocketFd(const UdpSocketFd &) = delete;
UdpSocketFd &operator=(const UdpSocketFd &) = delete; UdpSocketFd &operator=(const UdpSocketFd &) = delete;
td::Result<td::uint32> maximize_snd_buffer(td::uint32 max_buffer_size = 0); Result<uint32> maximize_snd_buffer(uint32 max_buffer_size = 0);
td::Result<td::uint32> maximize_rcv_buffer(td::uint32 max_buffer_size = 0); Result<uint32> maximize_rcv_buffer(uint32 max_buffer_size = 0);
static Result<UdpSocketFd> open(const IPAddress &address) TD_WARN_UNUSED_RESULT; static Result<UdpSocketFd> open(const IPAddress &address) TD_WARN_UNUSED_RESULT;
@ -84,8 +84,8 @@ class UdpSocketFd {
#endif #endif
private: private:
static constexpr td::uint32 default_udp_max_snd_buffer_size = (1 << 24); static constexpr uint32 default_udp_max_snd_buffer_size = (1 << 24);
static constexpr td::uint32 default_udp_max_rcv_buffer_size = (1 << 24); static constexpr uint32 default_udp_max_rcv_buffer_size = (1 << 24);
std::unique_ptr<detail::UdpSocketFdImpl, detail::UdpSocketFdImplDeleter> impl_; std::unique_ptr<detail::UdpSocketFdImpl, detail::UdpSocketFdImplDeleter> impl_;
explicit UdpSocketFd(unique_ptr<detail::UdpSocketFdImpl> impl); explicit UdpSocketFd(unique_ptr<detail::UdpSocketFdImpl> impl);
}; };

View File

@ -80,15 +80,13 @@ IocpRef Iocp::get_ref() const {
return IocpRef(iocp_handle_); return IocpRef(iocp_handle_);
} }
namespace { static void iocp_post(NativeFd &iocp_handle, size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped) {
void iocp_post(NativeFd &iocp_handle, size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped) {
if (PostQueuedCompletionStatus(iocp_handle.fd(), DWORD(size), reinterpret_cast<ULONG_PTR>(callback), if (PostQueuedCompletionStatus(iocp_handle.fd(), DWORD(size), reinterpret_cast<ULONG_PTR>(callback),
reinterpret_cast<OVERLAPPED *>(overlapped)) == 0) { reinterpret_cast<OVERLAPPED *>(overlapped)) == 0) {
auto error = OS_ERROR("IOCP post failed"); auto error = OS_ERROR("IOCP post failed");
LOG(FATAL) << error; LOG(FATAL) << error;
} }
} }
} // namespace
void Iocp::post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped) { void Iocp::post(size_t size, Callback *callback, WSAOVERLAPPED *overlapped) {
iocp_post(*iocp_handle_, size, callback, overlapped); iocp_post(*iocp_handle_, size, callback, overlapped);

View File

@ -59,9 +59,11 @@ class IocpRef {
IocpRef(std::weak_ptr<NativeFd> iocp_handle); IocpRef(std::weak_ptr<NativeFd> iocp_handle);
bool post(size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped); bool post(size_t size, Iocp::Callback *callback, WSAOVERLAPPED *overlapped);
private: private:
std::weak_ptr<NativeFd> iocp_handle_; std::weak_ptr<NativeFd> iocp_handle_;
}; };
} // namespace detail } // namespace detail
} // namespace td } // namespace td

View File

@ -298,27 +298,28 @@ void signal_safe_write_pointer(void *p, bool add_header) {
signal_safe_write(Slice(ptr, end), add_header); signal_safe_write(Slice(ptr, end), add_header);
} }
static void unblock_stdin() { static void block_stdin() {
#if TD_PORT_POSIX #if TD_PORT_POSIX
td::Stdin().get_native_fd().set_is_blocking(true).ignore(); Stdin().get_native_fd().set_is_blocking(true).ignore();
#endif #endif
} }
void default_failure_signal_hanler(int sig) {
td::signal_safe_write_signal_number(sig, true);
td::Stacktrace::PrintOptions options; static void default_failure_signal_handler(int sig) {
signal_safe_write_signal_number(sig);
Stacktrace::PrintOptions options;
options.use_gdb = true; options.use_gdb = true;
td::Stacktrace::print_to_stderr(options); Stacktrace::print_to_stderr(options);
unblock_stdin(); block_stdin();
_Exit(EXIT_FAILURE); _Exit(EXIT_FAILURE);
} }
Status set_default_failure_signal_handler() { Status set_default_failure_signal_handler() {
atexit(unblock_stdin); atexit(block_stdin);
TRY_STATUS(setup_signals_alt_stack()); TRY_STATUS(setup_signals_alt_stack());
TRY_STATUS(set_signal_handler(td::SignalType::Abort, default_failure_signal_hanler)); TRY_STATUS(set_signal_handler(SignalType::Abort, default_failure_signal_handler));
TRY_STATUS(td::set_signal_handler(td::SignalType::Error, default_failure_signal_hanler)); TRY_STATUS(set_signal_handler(SignalType::Error, default_failure_signal_handler));
return Status::OK(); return Status::OK();
} }

View File

@ -5,33 +5,41 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#include "td/utils/port/stacktrace.h" #include "td/utils/port/stacktrace.h"
#include "td/utils/port/signals.h" #include "td/utils/port/signals.h"
#if !TD_WINDOWS && !TD_ANDROID && !TD_FREEBSD #if __GLIBC__
#include <execinfo.h> #include <execinfo.h>
#endif
#if TD_LINUX || TD_FREEBSD
#include <sys/types.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <unistd.h> #include <unistd.h>
#if TD_LINUX #if TD_LINUX
#include <sys/prctl.h> #include <sys/prctl.h>
#endif #endif
#endif #endif
namespace td { namespace td {
namespace { namespace {
void print_backtrace(void) { void print_backtrace(void) {
#if !TD_WINDOWS && !TD_ANDROID && !TD_FREEBSD #if __GLIBC__
void *buffer[128]; void *buffer[128];
int nptrs = backtrace(buffer, 128); int nptrs = backtrace(buffer, 128);
td::signal_safe_write("------- Stack Backtrace -------\n", false); signal_safe_write("------- Stack Backtrace -------\n", false);
backtrace_symbols_fd(buffer, nptrs, 2); backtrace_symbols_fd(buffer, nptrs, 2);
td::signal_safe_write("-------------------------------\n", false); signal_safe_write("-------------------------------\n", false);
#endif #endif
} }
void print_backtrace_gdb(void) { void print_backtrace_gdb(void) {
#if !TD_WINDOWS && !TD_DARWIN && !TD_ANDROID #if TD_LINUX || TD_FREEBSD
char pid_buf[30], *pid_buf_begin = pid_buf + sizeof(pid_buf); char pid_buf[30];
char *pid_buf_begin = pid_buf + sizeof(pid_buf);
pid_t pid = getpid(); pid_t pid = getpid();
*--pid_buf_begin = '\0'; *--pid_buf_begin = '\0';
do { do {
@ -46,23 +54,23 @@ void print_backtrace_gdb(void) {
#if TD_LINUX #if TD_LINUX
if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) { if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
td::signal_safe_write("Can't set dumpable\n"); signal_safe_write("Can't set dumpable\n");
return; return;
} }
#if defined(PR_SET_PTRACER) #if defined(PR_SET_PTRACER)
// We can't use td::EventFd because we are in a signal handler // We can't use EventFd because we are in a signal handler
int fds[2]; int fds[2];
bool need_set_ptracer = true; bool need_set_ptracer = true;
if (pipe(fds) < 0) { if (pipe(fds) < 0) {
need_set_ptracer = false; need_set_ptracer = false;
td::signal_safe_write("Can't create a pipe\n"); signal_safe_write("Can't create a pipe\n");
} }
#endif #endif
#endif #endif
int child_pid = fork(); int child_pid = fork();
if (child_pid < 0) { if (child_pid < 0) {
td::signal_safe_write("Can't fork() to run gdb\n"); signal_safe_write("Can't fork() to run gdb\n");
return; return;
} }
if (!child_pid) { if (!child_pid) {
@ -80,20 +88,21 @@ void print_backtrace_gdb(void) {
#if TD_LINUX && defined(PR_SET_PTRACER) #if TD_LINUX && defined(PR_SET_PTRACER)
if (need_set_ptracer) { if (need_set_ptracer) {
if (prctl(PR_SET_PTRACER, child_pid, 0, 0, 0) < 0) { if (prctl(PR_SET_PTRACER, child_pid, 0, 0, 0) < 0) {
td::signal_safe_write("Can't set ptracer\n"); signal_safe_write("Can't set ptracer\n");
} }
if (write(fds[1], "a", 1) != 1) { if (write(fds[1], "a", 1) != 1) {
td::signal_safe_write("Can't write to pipe\n"); signal_safe_write("Can't write to pipe\n");
} }
} }
#endif #endif
waitpid(child_pid, nullptr, 0); waitpid(child_pid, nullptr, 0);
} }
} else { } else {
td::signal_safe_write("Can't get name of executable file to pass to gdb\n"); signal_safe_write("Can't get name of executable file to pass to gdb\n");
} }
#endif #endif
} }
} // namespace } // namespace
void Stacktrace::print_to_stderr(const PrintOptions &options) { void Stacktrace::print_to_stderr(const PrintOptions &options) {
@ -102,4 +111,5 @@ void Stacktrace::print_to_stderr(const PrintOptions &options) {
} }
print_backtrace(); print_backtrace();
} }
} // namespace td } // namespace td

View File

@ -5,13 +5,13 @@
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#pragma once #pragma once
namespace td { namespace td {
class Stacktrace { class Stacktrace {
public: public:
struct PrintOptions { struct PrintOptions {
bool use_gdb = false; bool use_gdb = false;
PrintOptions() {
}
}; };
static void print_to_stderr(const PrintOptions &options = PrintOptions()); static void print_to_stderr(const PrintOptions &options = PrintOptions());
}; };

View File

@ -6,7 +6,6 @@
// //
#include "td/utils/tests.h" #include "td/utils/tests.h"
#include "td/utils/base64.h"
#include "td/utils/crypto.h" #include "td/utils/crypto.h"
#include "td/utils/filesystem.h" #include "td/utils/filesystem.h"
#include "td/utils/Parser.h" #include "td/utils/Parser.h"
@ -228,4 +227,5 @@ Status TestsRunner::verify(Slice data) {
} }
return regression_tester_->verify_test(PSLICE() << name() << "_default", data); return regression_tester_->verify_test(PSLICE() << name() << "_default", data);
} }
} // namespace td } // namespace td

View File

@ -12,7 +12,6 @@
#include "td/utils/logging.h" #include "td/utils/logging.h"
#include "td/utils/port/thread.h" #include "td/utils/port/thread.h"
#include "td/utils/Random.h" #include "td/utils/Random.h"
#include "td/utils/optional.h"
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/Status.h" #include "td/utils/Status.h"

View File

@ -6,8 +6,12 @@
// //
#pragma once #pragma once
#include "td/utils/common.h"
#include "td/utils/bits.h" #include "td/utils/bits.h"
#include "td/utils/common.h"
#include <limits>
#include <type_traits>
namespace td { namespace td {
class uint128_emulated { class uint128_emulated {
@ -15,9 +19,11 @@ class uint128_emulated {
using uint128 = uint128_emulated; using uint128 = uint128_emulated;
uint128_emulated(uint64 hi, uint64 lo) : hi_(hi), lo_(lo) { uint128_emulated(uint64 hi, uint64 lo) : hi_(hi), lo_(lo) {
} }
uint128_emulated(uint64 lo) : uint128_emulated(0, lo) { template <class T, typename = std::enable_if_t<std::is_unsigned<T>::value>>
uint128_emulated(T lo) : uint128_emulated(0, lo) {
} }
uint128_emulated() = default; uint128_emulated() = default;
uint64 hi() const { uint64 hi() const {
return hi_; return hi_;
} }
@ -40,29 +46,29 @@ class uint128_emulated {
} }
uint128 shl(int cnt) const { uint128 shl(int cnt) const {
if (cnt >= 128) {
return uint128();
}
if (cnt == 0) { if (cnt == 0) {
return *this; return *this;
} }
if (cnt < 64) { if (cnt < 64) {
return uint128((hi() << cnt) | (lo() >> (64 - cnt)), lo() << cnt); return uint128((hi() << cnt) | (lo() >> (64 - cnt)), lo() << cnt);
} }
if (cnt < 128) {
return uint128(lo() << (cnt - 64), 0); return uint128(lo() << (cnt - 64), 0);
} }
uint128 shr(int cnt) const {
if (cnt >= 128) {
return uint128(); return uint128();
} }
uint128 shr(int cnt) const {
if (cnt == 0) { if (cnt == 0) {
return *this; return *this;
} }
if (cnt < 64) { if (cnt < 64) {
return uint128(hi() >> cnt, (lo() >> cnt) | (hi() << (64 - cnt))); return uint128(hi() >> cnt, (lo() >> cnt) | (hi() << (64 - cnt)));
} }
if (cnt < 128) {
return uint128(0, hi() >> (cnt - 64)); return uint128(0, hi() >> (cnt - 64));
} }
return uint128();
}
uint128 mult(uint128 other) const { uint128 mult(uint128 other) const {
uint64 a_lo = lo() & 0xffffffff; uint64 a_lo = lo() & 0xffffffff;
@ -156,7 +162,7 @@ class uint128_emulated {
uint64 lo_{0}; uint64 lo_{0};
bool is_negative() const { bool is_negative() const {
return static_cast<int64>(hi_) < 0; return (hi_ >> 63) == 1;
} }
int32 count_leading_zeroes() const { int32 count_leading_zeroes() const {
@ -179,6 +185,7 @@ class uint128_emulated {
return res; return res;
} }
}; };
#if TD_HAVE_INT128 #if TD_HAVE_INT128
class uint128_intrinsic { class uint128_intrinsic {
public: public:
@ -262,9 +269,11 @@ class uint128_intrinsic {
} }
}; };
#endif #endif
#if TD_HAVE_INT128 #if TD_HAVE_INT128
using uint128 = uint128_intrinsic; using uint128 = uint128_intrinsic;
#else #else
using uint128 = uint128_emulated; using uint128 = uint128_emulated;
#endif #endif
} // namespace td } // namespace td

View File

@ -4,13 +4,18 @@
// Distributed under the Boost Software License, Version 1.0. (See accompanying // Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
#include <cstdio>
#include "td/utils/tests.h"
#include "td/utils/benchmark.h" #include "td/utils/benchmark.h"
#include "td/utils/SpinLock.h"
#include "td/utils/HazardPointers.h"
#include "td/utils/ConcurrentHashTable.h" #include "td/utils/ConcurrentHashTable.h"
#include "td/utils/HazardPointers.h"
#include "td/utils/port/thread.h"
#include "td/utils/SpinLock.h"
#include "td/utils/tests.h"
#include <algorithm> #include <algorithm>
#include <atomic>
#include <cstdio>
#if !TD_THREAD_UNSUPPORTED
#if TD_HAVE_ABSL #if TD_HAVE_ABSL
#include <absl/container/flat_hash_map.h> #include <absl/container/flat_hash_map.h>
@ -18,7 +23,7 @@
#include <unordered_map> #include <unordered_map>
#endif #endif
#if TD_WITH_JUNCTION #if TD_WITH_LIBCUCKOO
#include <third-party/libcuckoo/libcuckoo/cuckoohash_map.hh> #include <third-party/libcuckoo/libcuckoo/cuckoohash_map.hh>
#endif #endif
@ -27,13 +32,14 @@
#include <junction/ConcurrentMap_Linear.h> #include <junction/ConcurrentMap_Linear.h>
#include <junction/ConcurrentMap_Leapfrog.h> #include <junction/ConcurrentMap_Leapfrog.h>
#endif #endif
namespace td { namespace td {
// Non resizable HashMap. Just an example // Non resizable HashMap. Just an example
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ArrayHashMap { class ArrayHashMap {
public: public:
ArrayHashMap(size_t n) : array_(n) { explicit ArrayHashMap(size_t n) : array_(n) {
} }
struct Node { struct Node {
std::atomic<KeyT> key{KeyT{}}; std::atomic<KeyT> key{KeyT{}};
@ -61,7 +67,7 @@ class ArrayHashMap {
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ConcurrentHashMapMutex { class ConcurrentHashMapMutex {
public: public:
ConcurrentHashMapMutex(size_t) { explicit ConcurrentHashMapMutex(size_t) {
} }
static std::string get_name() { static std::string get_name() {
return "ConcurrentHashMapMutex"; return "ConcurrentHashMapMutex";
@ -87,10 +93,11 @@ class ConcurrentHashMapMutex {
std::unordered_map<KeyT, ValueT> hash_map_; std::unordered_map<KeyT, ValueT> hash_map_;
#endif #endif
}; };
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ConcurrentHashMapSpinlock { class ConcurrentHashMapSpinlock {
public: public:
ConcurrentHashMapSpinlock(size_t) { explicit ConcurrentHashMapSpinlock(size_t) {
} }
static std::string get_name() { static std::string get_name() {
return "ConcurrentHashMapSpinlock"; return "ConcurrentHashMapSpinlock";
@ -109,18 +116,19 @@ class ConcurrentHashMapSpinlock {
} }
private: private:
td::SpinLock spinlock_; SpinLock spinlock_;
#if TD_HAVE_ABSL #if TD_HAVE_ABSL
absl::flat_hash_map<KeyT, ValueT> hash_map_; absl::flat_hash_map<KeyT, ValueT> hash_map_;
#else #else
std::unordered_map<KeyT, ValueT> hash_map_; std::unordered_map<KeyT, ValueT> hash_map_;
#endif #endif
}; };
#if TD_WITH_LIBCUCKOO #if TD_WITH_LIBCUCKOO
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ConcurrentHashMapLibcuckoo { class ConcurrentHashMapLibcuckoo {
public: public:
ConcurrentHashMapLibcuckoo(size_t) { explicit ConcurrentHashMapLibcuckoo(size_t) {
} }
static std::string get_name() { static std::string get_name() {
return "ConcurrentHashMapLibcuckoo"; return "ConcurrentHashMapLibcuckoo";
@ -137,11 +145,12 @@ class ConcurrentHashMapLibcuckoo {
cuckoohash_map<KeyT, ValueT> hash_map_; cuckoohash_map<KeyT, ValueT> hash_map_;
}; };
#endif #endif
#if TD_WITH_JUNCTION #if TD_WITH_JUNCTION
template <class KeyT, class ValueT> template <class KeyT, class ValueT>
class ConcurrentHashMapJunction { class ConcurrentHashMapJunction {
public: public:
ConcurrentHashMapJunction(size_t size) : hash_map_() { explicit ConcurrentHashMapJunction(size_t size) : hash_map_() {
} }
static std::string get_name() { static std::string get_name() {
return "ConcurrentHashMapJunction"; return "ConcurrentHashMapJunction";
@ -152,6 +161,11 @@ class ConcurrentHashMapJunction {
ValueT find(KeyT key, ValueT default_value) { ValueT find(KeyT key, ValueT default_value) {
return hash_map_.get(key); return hash_map_.get(key);
} }
ConcurrentHashMapJunction(const ConcurrentHashMapJunction &) = delete;
ConcurrentHashMapJunction &operator=(const ConcurrentHashMapJunction &) = delete;
ConcurrentHashMapJunction(ConcurrentHashMapJunction &&other) = delete;
ConcurrentHashMapJunction &operator=(ConcurrentHashMapJunction &&) = delete;
~ConcurrentHashMapJunction() { ~ConcurrentHashMapJunction() {
junction::DefaultQSBR.flush(); junction::DefaultQSBR.flush();
} }
@ -160,6 +174,7 @@ class ConcurrentHashMapJunction {
junction::ConcurrentMap_Leapfrog<KeyT, ValueT> hash_map_; junction::ConcurrentMap_Leapfrog<KeyT, ValueT> hash_map_;
}; };
#endif #endif
} // namespace td } // namespace td
template <class HashMap> template <class HashMap>
@ -169,7 +184,7 @@ class HashMapBenchmark : public td::Benchmark {
int value; int value;
}; };
std::vector<Query> queries; std::vector<Query> queries;
std::unique_ptr<HashMap> hash_map; td::unique_ptr<HashMap> hash_map;
size_t threads_n = 16; size_t threads_n = 16;
int mod_; int mod_;
@ -177,7 +192,7 @@ class HashMapBenchmark : public td::Benchmark {
int n_; int n_;
public: public:
HashMapBenchmark(size_t threads_n) : threads_n(threads_n) { explicit HashMapBenchmark(size_t threads_n) : threads_n(threads_n) {
} }
std::string get_description() const override { std::string get_description() const override {
return hash_map->get_name(); return hash_map->get_name();
@ -185,7 +200,7 @@ class HashMapBenchmark : public td::Benchmark {
void start_up_n(int n) override { void start_up_n(int n) override {
n *= (int)threads_n; n *= (int)threads_n;
n_ = n; n_ = n;
hash_map = std::make_unique<HashMap>(n * 2); hash_map = td::make_unique<HashMap>(n * 2);
} }
void run(int n) override { void run(int n) override {
@ -217,8 +232,6 @@ class HashMapBenchmark : public td::Benchmark {
queries.clear(); queries.clear();
hash_map.reset(); hash_map.reset();
} }
private:
}; };
template <class HashMap> template <class HashMap>
@ -240,3 +253,4 @@ TEST(ConcurrentHashMap, Benchmark) {
#endif #endif
} }
#endif

View File

@ -178,10 +178,11 @@ TEST(Crypto, crc32c) {
ASSERT_EQ(answers[i], b); ASSERT_EQ(answers[i], b);
} }
} }
TEST(Crypto, crc32c_benchmark) { TEST(Crypto, crc32c_benchmark) {
class Crc32cExtendBenchmark : public td::Benchmark { class Crc32cExtendBenchmark : public td::Benchmark {
public: public:
Crc32cExtendBenchmark(size_t chunk_size) : chunk_size_(chunk_size) { explicit Crc32cExtendBenchmark(size_t chunk_size) : chunk_size_(chunk_size) {
} }
std::string get_description() const override { std::string get_description() const override {
return PSTRING() << "Crc32c with chunk_size=" << chunk_size_; return PSTRING() << "Crc32c with chunk_size=" << chunk_size_;

View File

@ -6,7 +6,6 @@
// //
#include "td/utils/as.h" #include "td/utils/as.h"
#include "td/utils/base64.h" #include "td/utils/base64.h"
#include "td/utils/bits.h"
#include "td/utils/BigNum.h" #include "td/utils/BigNum.h"
#include "td/utils/bits.h" #include "td/utils/bits.h"
#include "td/utils/CancellationToken.h" #include "td/utils/CancellationToken.h"
@ -30,8 +29,8 @@
#include "td/utils/Slice.h" #include "td/utils/Slice.h"
#include "td/utils/StringBuilder.h" #include "td/utils/StringBuilder.h"
#include "td/utils/tests.h" #include "td/utils/tests.h"
#include "td/utils/translit.h"
#include "td/utils/Time.h" #include "td/utils/Time.h"
#include "td/utils/translit.h"
#include "td/utils/uint128.h" #include "td/utils/uint128.h"
#include "td/utils/unicode.h" #include "td/utils/unicode.h"
#include "td/utils/utf8.h" #include "td/utils/utf8.h"
@ -40,8 +39,8 @@
#include <clocale> #include <clocale>
#include <limits> #include <limits>
#include <locale> #include <locale>
#include <utility>
#include <unordered_map> #include <unordered_map>
#include <utility>
#if TD_HAVE_ABSL #if TD_HAVE_ABSL
#include <absl/container/flat_hash_map.h> #include <absl/container/flat_hash_map.h>
@ -673,6 +672,7 @@ TEST(Misc, Bits) {
ASSERT_EQ(4, count_bits64((1ull << 63) | 7)); ASSERT_EQ(4, count_bits64((1ull << 63) | 7));
} }
#if !TD_THREAD_UNSUPPORTED
TEST(Misc, Time) { TEST(Misc, Time) {
Stage run; Stage run;
Stage check; Stage check;
@ -703,6 +703,7 @@ TEST(Misc, Time) {
thread.join(); thread.join();
} }
} }
#endif
TEST(Misc, uint128) { TEST(Misc, uint128) {
std::vector<uint64> parts = {0, std::vector<uint64> parts = {0,
@ -753,19 +754,15 @@ TEST(Misc, uint128) {
} }
} }
for (auto a : nums) {
#if TD_HAVE_INT128 #if TD_HAVE_INT128
for (auto a : nums) {
auto ia = to_intrinsic(a); auto ia = to_intrinsic(a);
ensure_eq(a, ia); ensure_eq(a, ia);
CHECK(a.is_zero() == ia.is_zero()); CHECK(a.is_zero() == ia.is_zero());
#endif
for (int i = 0; i <= 130; i++) { for (int i = 0; i <= 130; i++) {
#if TD_HAVE_INT128
ensure_eq(a.shl(i), ia.shl(i)); ensure_eq(a.shl(i), ia.shl(i));
ensure_eq(a.shr(i), ia.shr(i)); ensure_eq(a.shr(i), ia.shr(i));
#endif
} }
#if TD_HAVE_INT128
for (auto b : parts) { for (auto b : parts) {
ensure_eq(a.mult(b), ia.mult(b)); ensure_eq(a.mult(b), ia.mult(b));
} }
@ -792,10 +789,8 @@ TEST(Misc, uint128) {
ensure_eq(a.mod(b), ia.mod(ib)); ensure_eq(a.mod(b), ia.mod(ib));
} }
} }
#endif
} }
#if TD_HAVE_INT128
for (auto signed_part : signed_parts) { for (auto signed_part : signed_parts) {
auto a = uint128_emulated::from_signed(signed_part); auto a = uint128_emulated::from_signed(signed_part);
auto ia = uint128_intrinsic::from_signed(signed_part); auto ia = uint128_intrinsic::from_signed(signed_part);
@ -828,7 +823,7 @@ Status test_hash(const std::vector<ValueT> &values) {
class BadValue { class BadValue {
public: public:
BadValue(size_t value) : value_(value) { explicit BadValue(size_t value) : value_(value) {
} }
template <class H> template <class H>
@ -845,7 +840,7 @@ class BadValue {
class ValueA { class ValueA {
public: public:
ValueA(size_t value) : value_(value) { explicit ValueA(size_t value) : value_(value) {
} }
template <class H> template <class H>
friend H AbslHashValue(H hasher, ValueA value) { friend H AbslHashValue(H hasher, ValueA value) {
@ -861,7 +856,7 @@ class ValueA {
class ValueB { class ValueB {
public: public:
ValueB(size_t value) : value_(value) { explicit ValueB(size_t value) : value_(value) {
} }
template <class H> template <class H>

View File

@ -36,28 +36,33 @@ TEST(Port, files) {
int cnt = 0; int cnt = 0;
const int ITER_COUNT = 1000; const int ITER_COUNT = 1000;
for (int i = 0; i < ITER_COUNT; i++) { for (int i = 0; i < ITER_COUNT; i++) {
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { walk_path(main_dir,
[&](CSlice name, WalkPath::Type type) {
if (type == WalkPath::Type::NotDir) { if (type == WalkPath::Type::NotDir) {
ASSERT_TRUE(name == fd_path || name == fd2_path); ASSERT_TRUE(name == fd_path || name == fd2_path);
} }
cnt++; cnt++;
}).ensure(); })
.ensure();
} }
ASSERT_EQ((5 * 2 + 2) * ITER_COUNT, cnt); ASSERT_EQ((5 * 2 + 2) * ITER_COUNT, cnt);
bool was_abort = false; bool was_abort = false;
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { walk_path(main_dir,
[&](CSlice name, WalkPath::Type type) {
CHECK(!was_abort); CHECK(!was_abort);
if (type == WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) { if (type == WalkPath::Type::EnterDir && ends_with(name, PSLICE() << TD_DIR_SLASH << "B")) {
was_abort = true; was_abort = true;
return WalkPath::Action::Abort; return WalkPath::Action::Abort;
} }
return WalkPath::Action::Continue; return WalkPath::Action::Continue;
}).ensure(); })
.ensure();
CHECK(was_abort); CHECK(was_abort);
cnt = 0; cnt = 0;
bool is_first_dir = true; bool is_first_dir = true;
walk_path(main_dir, [&](CSlice name, WalkPath::Type type) { walk_path(main_dir,
[&](CSlice name, WalkPath::Type type) {
cnt++; cnt++;
if (type == WalkPath::Type::EnterDir) { if (type == WalkPath::Type::EnterDir) {
if (is_first_dir) { if (is_first_dir) {
@ -67,7 +72,8 @@ TEST(Port, files) {
} }
} }
return WalkPath::Action::Continue; return WalkPath::Action::Continue;
}).ensure(); })
.ensure();
ASSERT_EQ(6, cnt); ASSERT_EQ(6, cnt);
ASSERT_EQ(0u, fd.get_size().move_as_ok()); ASSERT_EQ(0u, fd.get_size().move_as_ok());
@ -113,19 +119,21 @@ TEST(Port, Writev) {
ASSERT_EQ(expected_content, content); ASSERT_EQ(expected_content, content);
} }
#if TD_PORT_POSIX #if TD_PORT_POSIX && !TD_THREAD_UNSUPPORTED
#include <signal.h> #include <signal.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <unistd.h> #include <unistd.h>
#include <algorithm>
#include <mutex> #include <mutex>
#include <set> #include <set>
#include <algorithm>
std::mutex m; static std::mutex m;
std::vector<std::string> ptrs; static std::vector<std::string> ptrs;
std::vector<int *> addrs; static std::vector<int *> addrs;
TD_THREAD_LOCAL int thread_id; static TD_THREAD_LOCAL int thread_id;
void on_user_signal(int sig) {
static void on_user_signal(int sig) {
int addr; int addr;
addrs[thread_id] = &addr; addrs[thread_id] = &addr;
char ptr[10]; char ptr[10];