Skip to content

Commit

Permalink
Support optional
Browse files Browse the repository at this point in the history
  • Loading branch information
chenBright committed Oct 30, 2024
1 parent ac2738c commit a339839
Show file tree
Hide file tree
Showing 17 changed files with 1,058 additions and 232 deletions.
24 changes: 24 additions & 0 deletions src/bthread/task_meta.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,26 @@ struct LocalStorage {

const static LocalStorage LOCAL_STORAGE_INIT = BTHREAD_LOCAL_STORAGE_INITIALIZER;

// https://stackoverflow.com/a/61860187
// https://stackoverflow.com/a/57308102
// https://github.com/WAVM/WAVM/issues/80
// https://www.nongnu.org/libunwind/man/unw_step(3).html#section_4
// https://github.com/gperftools/gperftools/wiki/gperftools'-stacktrace-capturing-methods-and-their-issues#libunwind
// https://github.com/alk/unwind_safeness_helper/blob/master/unwind_safeness_helper.c
// https://github.com/gperftools/gperftools/issues/775#issuecomment-207836201
// https://github.com/libunwind/libunwind/pull/490
// https://github.com/libunwind/libunwind/issues/580
// https://maskray.me/blog/2022-04-10-unwinding-through-signal-handler
// enum TaskStatus {
// TASK_STATUS_CREATED,
// TASK_STATUS_READY,
// TASK_STATUS_RUNNING,
// TASK_STATUS_SLEEP,
// TASK_STATUS_BLOCKED,
// TASK_STATUS_TRACE,
// TASK_STATUS_END,
// };

struct TaskMeta {
// [Not Reset]
butil::atomic<ButexWaiter*> current_waiter;
Expand All @@ -64,6 +84,10 @@ struct TaskMeta {

// Scheduling of the thread can be delayed.
bool about_to_quit;

// butil::atomic<TaskStatus> status;
pthread_t worker_tid;
bool trace;

// [Not Reset] guarantee visibility of version_butex.
pthread_spinlock_t version_lock;
Expand Down
58 changes: 27 additions & 31 deletions src/butil/containers/flat_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
#include "butil/strings/string_piece.h" // StringPiece
#include "butil/memory/scope_guard.h"
#include "butil/memory/manual_constructor.h"
#include "butil/containers/optional.h"

namespace butil {

Expand Down Expand Up @@ -153,11 +154,10 @@ class FlatMap {
_Sparse, SparseFlatMapIterator<FlatMap, value_type>,
FlatMapIterator<FlatMap, value_type> >::type iterator;
typedef typename conditional<
_Sparse, SparseFlatMapIterator<FlatMap, const value_type>,
_Sparse, SparseFlatMapIterator<FlatMap, const value_type>,
FlatMapIterator<FlatMap, const value_type> >::type const_iterator;
typedef _Hash hasher;
typedef _Equal key_equal;
typedef typename conditional<_Multi, true_type, false_type>::type multi_type;
static constexpr size_t DEFAULT_NBUCKET = BRPC_FLATMAP_DEFAULT_NBUCKET;

struct PositionHint {
Expand All @@ -166,7 +166,7 @@ class FlatMap {
bool at_entry;
key_type key;
};

explicit FlatMap(const hasher& hashfn = hasher(),
const key_equal& eql = key_equal(),
const allocator_type& alloc = allocator_type());
Expand All @@ -177,13 +177,13 @@ class FlatMap {
void swap(FlatMap & rhs);

// FlatMap will be automatically initialized, so no need to call this function.
// `nbucket' is the initial number of buckets. `load_factor' is the
// `nbucket' is the initial number of buckets. `load_factor' is the
// maximum value of size()*100/nbucket, if the value is reached, nbucket
// will be doubled and all items stored will be rehashed which is costly.
// Choosing proper values for these 2 parameters reduces costs.
int init(size_t nbucket, u_int load_factor = 80);
// Insert a pair of |key| and |value|. If size()*100/bucket_count() is

// Insert a pair of |key| and |value|. If size()*100/bucket_count() is
// more than load_factor(), a resize() will be done.
// Returns address of the inserted value, NULL on error.
mapped_type* insert(const key_type& key, const mapped_type& value);
Expand All @@ -210,7 +210,7 @@ class FlatMap {

// Remove all items and return all allocated spaces to system.
void clear_and_reset_pool();

// Search for the value associated with |key|.
// If `_Multi=false', Search for any of multiple values associated with |key|.
// Returns: address of the value.
Expand All @@ -228,8 +228,8 @@ class FlatMap {
// Resize this map. This is optional because resizing will be triggered by
// insert() or operator[] if there're too many items.
// Returns successful or not.
bool resize(size_t new_nbucket);
bool resize(size_t nbucket);

// Iterators
iterator begin();
iterator end();
Expand Down Expand Up @@ -278,42 +278,40 @@ class FlatMap {
BucketInfo bucket_info() const;

struct Bucket {
Bucket() : next((Bucket*)-1UL) {}
explicit Bucket(const _K& k) : next(NULL) {
element_.Init(k);
element_space_.Init(k);
}
Bucket(const Bucket& other) : next(NULL) {
element_.Init(other.element());
element_space_.Init(other.element());
}

bool is_valid() const { return next != (const Bucket*)-1UL; }
void set_invalid() { next = (Bucket*)-1UL; }
// NOTE: Only be called when is_valid() is true.
Element& element() {
return *element_;
}
const Element& element() const {
return *element_;
}
Element& element() { return *element_space_; }
const Element& element() const { return *element_space_; }
void destroy_element() { element_space_.Destroy(); }

void swap(Bucket& rhs) {
if (!is_valid() && !rhs.is_valid()) {
return;
} else if (is_valid() && !rhs.is_valid()) {
rhs.element_.Init(std::move(element()));
element().~Element();
rhs.element_space_.Init(std::move(element()));
destroy_element();
} else if (!is_valid() && rhs.is_valid()) {
element_.Init(std::move(rhs.element()));
rhs.element().~Element();
element_space_.Init(std::move(rhs.element()));
rhs.destroy_element();
} else {
element().swap(rhs.element());
}
std::swap(next, rhs.next);
}

Bucket *next;
Bucket* next;

private:
ManualConstructor<Element> element_;
ManualConstructor<Element> element_space_;
};

private:
Expand All @@ -325,13 +323,13 @@ template <typename _Map, typename _Element> friend class SparseFlatMapIterator;
: buckets(NULL), thumbnail(NULL), nbucket(0) {}
NewBucketsInfo(Bucket* b, uint64_t* t, size_t n)
: buckets(b), thumbnail(t), nbucket(n) {}

Bucket* buckets;
uint64_t* thumbnail;
size_t nbucket;
};

NewBucketsInfo new_buckets_and_thumbnail(
size_t size, size_t new_nbucket, bool ignore_same_nbucket);
optional<NewBucketsInfo> new_buckets_and_thumbnail(size_t size, size_t new_nbucket);

// For `_Multi=true'.
// Insert a new default-constructed associated with |key| always.
Expand Down Expand Up @@ -359,9 +357,9 @@ template <typename _Map, typename _Element> friend class SparseFlatMapIterator;
}
}

// True if using default buckets which is for small map optimization.
// True if using default buckets.
bool is_default_buckets() const {
return _buckets == (Bucket*)(&_default_buckets_spaces);
return _buckets == (Bucket*)(&_default_buckets);
}

static void init_buckets_and_thumbnail(Bucket* buckets,
Expand All @@ -377,11 +375,9 @@ template <typename _Map, typename _Element> friend class SparseFlatMapIterator;
}

static const size_t default_nthumbnail = BIT_ARRAY_LEN(DEFAULT_NBUCKET);
// Small map optimization.
typedef typename std::aligned_storage<sizeof(Bucket), alignof(Bucket)>::type
buckets_spaces_type;
// Note: need an extra bucket to let iterator know where buckets end.
buckets_spaces_type _default_buckets_spaces[DEFAULT_NBUCKET + 1];
// Small map optimization.
Bucket _default_buckets[DEFAULT_NBUCKET + 1];
uint64_t _default_thumbnail[default_nthumbnail];
size_t _size;
size_t _nbucket;
Expand Down
Loading

0 comments on commit a339839

Please sign in to comment.