Skip to content

Commit

Permalink
尝试使用更小的原子操作控制,试试能否增加缓存预测率
Browse files Browse the repository at this point in the history
  • Loading branch information
owent committed Jun 1, 2017
1 parent af38a42 commit 8bf734b
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 44 deletions.
21 changes: 11 additions & 10 deletions include/libcopp/coroutine/coroutine_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ namespace copp {

struct flag_t {
enum type {
EN_CFT_UNKNOWN = 0,
EN_CFT_UNKNOWN = 0,
EN_CFT_FINISHED = 0x01,
};
};
Expand Down Expand Up @@ -104,10 +104,11 @@ namespace copp {
static int create(coroutine_context *p, callback_t &runner, const stack_context &callee_stack, size_t coroutine_size,
size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT;

template<typename TRunner>
static int create(coroutine_context *p, TRunner* runner, const stack_context &callee_stack, size_t coroutine_size,
size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
return create(p, std::bind(&TRunner::operator(), runner, std::placeholders::_1), callee_stack, coroutine_size, private_buffer_size);
template <typename TRunner>
static int create(coroutine_context *p, TRunner *runner, const stack_context &callee_stack, size_t coroutine_size,
size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
return create(p, std::bind(&TRunner::operator(), runner, std::placeholders::_1), callee_stack, coroutine_size,
private_buffer_size);
}

/**
Expand Down Expand Up @@ -203,13 +204,13 @@ namespace copp {
public:
static inline size_t align_private_data_size(size_t sz) {
// static size_t random_index = 0;
// const size_t random_mask = 63;
const size_t align_mask = 2 * sizeof(size_t) - 1;
// UTIL_CONFIG_CONSTEXPR size_t random_mask = 63;
UTIL_CONFIG_CONSTEXPR size_t align_mask = 2 * sizeof(size_t) - 1;

// align
sz += align_mask;
sz &= ~align_mask;

// random
// ++random_index;
// random_index &= random_mask;
Expand All @@ -218,7 +219,7 @@ namespace copp {
}

static inline size_t align_address_size(size_t sz) {
const size_t mask = 2 * sizeof(size_t) - 1;
UTIL_CONFIG_CONSTEXPR size_t mask = 2 * sizeof(size_t) - 1;
sz += mask;
sz &= ~mask;
return sz;
Expand Down
18 changes: 10 additions & 8 deletions include/libcotask/core/standard_int_id_allocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@
#ifndef _COTASK_CORE_STANDARD_INT_ID_ALLOCATOR_H_
#define _COTASK_CORE_STANDARD_INT_ID_ALLOCATOR_H_

#include <stdint.h>
#include <ctime>
#include <stdint.h>


#include <libcopp/utils/atomic_int_type.h>
#include <libcotask/impl/id_allocator_impl.h>
Expand All @@ -21,12 +22,11 @@ namespace cotask {

/**
* @biref allocate a id of specify type
* @note we guarantee id will not repeated for a short time.
* @note we guarantee id will not repeated for a short time.
* the time depennd the length of TKey.
*/
template<typename TKey = uint64_t>
class standard_int_id_allocator
{
template <typename TKey = uint64_t>
class standard_int_id_allocator {
public:
typedef cotask::impl::id_allocator<TKey> base_type;
typedef typename base_type::value_type value_type;
Expand All @@ -41,7 +41,7 @@ namespace cotask {

// always do not allocate 0 as a valid ID
value_type ret = npos;
while(npos == ret) {
while (npos == ret) {
value_type res = seq_alloc.load();
value_type time_part = res >> seq_bits;

Expand All @@ -54,11 +54,13 @@ namespace cotask {
}

// if failed, maybe another thread do it
if (seq_alloc.compare_exchange_strong(res, now_time << seq_bits)) {
if (seq_alloc.compare_exchange_strong(res, now_time << seq_bits, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
ret = now_time << seq_bits;
}
} else {
if (seq_alloc.compare_exchange_weak(res, next_ret)) {
if (seq_alloc.compare_exchange_weak(res, next_ret, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
ret = next_ret;
}
}
Expand Down
4 changes: 3 additions & 1 deletion include/libcotask/impl/task_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,9 @@ namespace cotask {
* get task status
* @return task status
*/
EN_TASK_STATUS get_status() const UTIL_CONFIG_NOEXCEPT { return static_cast<EN_TASK_STATUS>(status_.load()); }
EN_TASK_STATUS get_status() const UTIL_CONFIG_NOEXCEPT {
return static_cast<EN_TASK_STATUS>(status_.load(util::lock::memory_order_acquire));
}

virtual bool is_canceled() const UTIL_CONFIG_NOEXCEPT;
virtual bool is_completed() const UTIL_CONFIG_NOEXCEPT;
Expand Down
64 changes: 40 additions & 24 deletions src/libcopp/coroutine/coroutine_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -60,25 +60,26 @@ namespace copp {
}
}

coroutine_context::coroutine_context() UTIL_CONFIG_NOEXCEPT : runner_ret_code_(0), flags_(0),
runner_(UTIL_CONFIG_NULLPTR),
priv_data_(UTIL_CONFIG_NULLPTR),
private_buffer_size_(0),
status_(status_t::EN_CRS_INVALID),
caller_(UTIL_CONFIG_NULLPTR),
callee_(UTIL_CONFIG_NULLPTR),
callee_stack_()
coroutine_context::coroutine_context() UTIL_CONFIG_NOEXCEPT : runner_ret_code_(0),
flags_(0),
runner_(UTIL_CONFIG_NULLPTR),
priv_data_(UTIL_CONFIG_NULLPTR),
private_buffer_size_(0),
status_(status_t::EN_CRS_INVALID),
caller_(UTIL_CONFIG_NULLPTR),
callee_(UTIL_CONFIG_NULLPTR),
callee_stack_()
#ifdef COPP_MACRO_USE_SEGMENTED_STACKS
,
caller_stack_()
,
caller_stack_()
#endif
{
}

coroutine_context::~coroutine_context() {}

int coroutine_context::create(coroutine_context *p, callback_t &runner, const stack_context &callee_stack, size_t coroutine_size,
size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
size_t private_buffer_size) UTIL_CONFIG_NOEXCEPT {
if (UTIL_CONFIG_NULLPTR == p) {
return COPP_EC_ARGS_ERROR;
}
Expand Down Expand Up @@ -120,7 +121,7 @@ namespace copp {
// stack down, left enough private data
p->priv_data_ = reinterpret_cast<unsigned char *>(p->callee_stack_.sp) - p->private_buffer_size_;
p->callee_ = fcontext::copp_make_fcontext(reinterpret_cast<unsigned char *>(p->callee_stack_.sp) - stack_offset,
p->callee_stack_.size - stack_offset, &coroutine_context::coroutine_context_callback);
p->callee_stack_.size - stack_offset, &coroutine_context::coroutine_context_callback);
if (NULL == p->callee_) {
return COPP_EC_FCONTEXT_MAKE_FAILED;
}
Expand All @@ -139,7 +140,8 @@ namespace copp {
return COPP_EC_NOT_INITED;
}

if (status_.compare_exchange_strong(from_status, status_t::EN_CRS_RUNNING)) {
if (status_.compare_exchange_strong(from_status, status_t::EN_CRS_RUNNING, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
break;
} else {
// finished or stoped
Expand Down Expand Up @@ -170,10 +172,12 @@ namespace copp {
{
// assume it's running, or set into EN_CRS_EXITED if in EN_CRS_FINISHED
from_status = status_t::EN_CRS_RUNNING;
if (false == status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY)) {
if (false ==
status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
if (status_t::EN_CRS_FINISHED == from_status) {
// if in finished status, change it to exited
status_.store(status_t::EN_CRS_EXITED);
status_.store(status_t::EN_CRS_EXITED, util::lock::memory_order_release);
}
}
}
Expand All @@ -189,7 +193,9 @@ namespace copp {
}

int from_status = status_t::EN_CRS_RUNNING;
if (false == status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY)) {
if (false ==
status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
switch (from_status) {
case status_t::EN_CRS_INVALID:
return COPP_EC_NOT_INITED;
Expand Down Expand Up @@ -229,7 +235,9 @@ namespace copp {
}

int from_status = status_t::EN_CRS_INVALID;
if (false == status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY)) {
if (false ==
status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
return COPP_EC_ALREADY_INITED;
}

Expand All @@ -244,7 +252,9 @@ namespace copp {
}

int from_status = status_t::EN_CRS_INVALID;
if (false == status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY)) {
if (false ==
status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
util::lock::memory_order_acquire)) {
return COPP_EC_ALREADY_INITED;
}

Expand All @@ -253,7 +263,10 @@ namespace copp {
}
#endif

bool coroutine_context::is_finished() const UTIL_CONFIG_NOEXCEPT { return !!(flags_ & flag_t::EN_CFT_FINISHED); }
bool coroutine_context::is_finished() const UTIL_CONFIG_NOEXCEPT {
// return !!(flags_ & flag_t::EN_CFT_FINISHED);
return status_.load(util::lock::memory_order_acquire);
}

void coroutine_context::jump_to(fcontext::fcontext_t &to_fctx, stack_context &from_sctx, stack_context &to_sctx,
jump_src_data_t &jump_transfer) UTIL_CONFIG_NOEXCEPT {
Expand Down Expand Up @@ -312,7 +325,8 @@ namespace copp {
// [BUG #4](https://github.com/owt5008137/libcopp/issues/4)
// from_status = jump_src->from_co->status_.load();
// if (status_t::EN_CRS_RUNNING == from_status) {
// jump_src->from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY);
// jump_src->from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
// util::lock::memory_order_acquire);
// } else if (status_t::EN_CRS_FINISHED == from_status) {
// // if in finished status, change it to exited
// jump_src->from_co->status_.store(status_t::EN_CRS_EXITED);
Expand All @@ -331,7 +345,8 @@ namespace copp {
// from_status = jump_transfer.from_co->status_.load();
// swap_success = false;
// while (!swap_success && status_t::EN_CRS_READY == from_status) {
// swap_success = jump_transfer.from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_RUNNING);
// swap_success = jump_transfer.from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_RUNNING,
// util::lock::memory_order_acq_rel, util::lock::memory_order_acquire);
// }
// }
}
Expand Down Expand Up @@ -362,7 +377,8 @@ namespace copp {
jump_src.from_co->callee_ = src_ctx.fctx;
// [BUG #4](https://github.com/owt5008137/libcopp/issues/4)
// int from_status = status_t::EN_CRS_RUNNING; // from coroutine change status from running to ready
// jump_src.from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY);
// jump_src.from_co->status_.compare_exchange_strong(from_status, status_t::EN_CRS_READY, util::lock::memory_order_acq_rel,
// util::lock::memory_order_acquire);
}

// this_coroutine
Expand All @@ -372,9 +388,9 @@ namespace copp {
ins_ptr->run_and_recv_retcode(jump_src.priv_data);

ins_ptr->flags_ |= flag_t::EN_CFT_FINISHED;
ins_ptr->status_.store(status_t::EN_CRS_FINISHED);
ins_ptr->status_.store(status_t::EN_CRS_FINISHED, util::lock::memory_order_release);
// add memory fence to flush flags_(used in is_finished())
UTIL_LOCK_ATOMIC_THREAD_FENCE(util::lock::memory_order_release);
// UTIL_LOCK_ATOMIC_THREAD_FENCE(util::lock::memory_order_release);

// jump back to caller
ins_ptr->yield();
Expand Down
3 changes: 2 additions & 1 deletion src/libcotask/impl/task_impl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ namespace cotask {

bool task_impl::_cas_status(EN_TASK_STATUS &expected, EN_TASK_STATUS desired) {
uint32_t expected_int = expected;
bool ret = status_.compare_exchange_weak(expected_int, desired);
bool ret =
status_.compare_exchange_weak(expected_int, desired, util::lock::memory_order_acq_rel, util::lock::memory_order_acquire);
expected = static_cast<EN_TASK_STATUS>(expected_int);
return ret;
}
Expand Down

0 comments on commit 8bf734b

Please sign in to comment.