Browse Source

将异常和返回值做成union以减小state的大小。

支持返回引用。
tags/v2.9.7
tearshark 4 years ago
parent
commit
837a2827ba

+ 1
- 1
benchmark/benchmark_channel_passing_next.cpp View File

@@ -20,7 +20,7 @@ static future_t<> passing_next(int_channel_ptr rd, int_channel_ptr wr)
for (;;)
{
intptr_t value = co_await *rd;
co_await (*wr << (value + 1));
co_await wr->write(value + 1);
}
}


+ 15
- 2
librf/src/awaitable.h View File

@@ -39,7 +39,7 @@ RESUMEF_NS
};

template<class _Ty>
struct awaitable_t : public awaitable_impl_t<_Ty>
struct [[nodiscard]] awaitable_t : public awaitable_impl_t<_Ty>
{
using typename awaitable_impl_t<_Ty>::value_type;
using awaitable_impl_t<_Ty>::awaitable_impl_t;
@@ -52,8 +52,21 @@ RESUMEF_NS
}
};

template<class _Ty>
struct [[nodiscard]] awaitable_t<_Ty&> : public awaitable_impl_t<_Ty&>
{
using typename awaitable_impl_t<_Ty&>::value_type;
using awaitable_impl_t<_Ty&>::awaitable_impl_t;

void set_value(_Ty& value) const
{
this->_state->set_value(value);
this->_state = nullptr;
}
};

template<>
struct awaitable_t<void> : public awaitable_impl_t<void>
struct [[nodiscard]] awaitable_t<void> : public awaitable_impl_t<void>
{
using awaitable_impl_t<void>::awaitable_impl_t;


+ 1
- 1
librf/src/def.h View File

@@ -1,6 +1,6 @@
#pragma once
#define LIB_RESUMEF_VERSION 20303 // 2.3.3
#define LIB_RESUMEF_VERSION 20304 // 2.3.4
#if defined(RESUMEF_MODULE_EXPORT)
#define RESUMEF_NS export namespace resumef

+ 57
- 0
librf/src/event.cpp View File

@@ -353,4 +353,61 @@ RESUMEF_NS
return awaitable.get_future();
}
void async_manual_reset_event::set() noexcept
{
// Needs to be 'release' so that subsequent 'co_await' has
// visibility of our prior writes.
// Needs to be 'acquire' so that we have visibility of prior
// writes by awaiting coroutines.
void* oldValue = m_state.exchange(this, std::memory_order_acq_rel);
if (oldValue != this)
{
// Wasn't already in 'set' state.
// Treat old value as head of a linked-list of waiters
// which we have now acquired and need to resume.
auto* waiters = static_cast<awaiter*>(oldValue);
while (waiters != nullptr)
{
// Read m_next before resuming the coroutine as resuming
// the coroutine will likely destroy the awaiter object.
auto* next = waiters->m_next;
waiters->m_awaitingCoroutine.resume();
waiters = next;
}
}
}
bool async_manual_reset_event::awaiter::await_suspend(
coroutine_handle<> awaitingCoroutine) noexcept
{
// Special m_state value that indicates the event is in the 'set' state.
const void* const setState = &m_event;
// Remember the handle of the awaiting coroutine.
m_awaitingCoroutine = awaitingCoroutine;
// Try to atomically push this awaiter onto the front of the list.
void* oldValue = m_event.m_state.load(std::memory_order_acquire);
do
{
// Resume immediately if already in 'set' state.
if (oldValue == setState) return false;
// Update linked list to point at current head.
m_next = static_cast<awaiter*>(oldValue);
// Finally, try to swap the old list head, inserting this awaiter
// as the new list head.
} while (!m_event.m_state.compare_exchange_weak(
oldValue,
this,
std::memory_order_release,
std::memory_order_acquire));
// Successfully enqueued. Remain suspended.
return true;
}
}

+ 59
- 0
librf/src/event.h View File

@@ -208,4 +208,63 @@ RESUMEF_NS
static future_t<bool> wait_all_until_(const clock_type::time_point& tp, std::vector<event_impl_ptr>&& evts);
};
class async_manual_reset_event
{
public:
async_manual_reset_event(bool initiallySet = false) noexcept
: m_state(initiallySet ? this : nullptr)
{}
// No copying/moving
async_manual_reset_event(const async_manual_reset_event&) = delete;
async_manual_reset_event(async_manual_reset_event&&) = delete;
async_manual_reset_event& operator=(const async_manual_reset_event&) = delete;
async_manual_reset_event& operator=(async_manual_reset_event&&) = delete;
bool is_set() const noexcept
{
return m_state.load(std::memory_order_acquire) == this;
}
struct awaiter;
awaiter operator co_await() const noexcept;
void set() noexcept;
void reset() noexcept
{
void* oldValue = this;
m_state.compare_exchange_strong(oldValue, nullptr, std::memory_order_acquire);
}
private:
friend struct awaiter;
// - 'this' => set state
// - otherwise => not set, head of linked list of awaiter*.
mutable std::atomic<void*> m_state;
};
struct async_manual_reset_event::awaiter
{
awaiter(const async_manual_reset_event& event) noexcept
: m_event(event)
{}
bool await_ready() const noexcept
{
return m_event.is_set();
}
bool await_suspend(coroutine_handle<> awaitingCoroutine) noexcept;
void await_resume() noexcept {}
private:
friend class async_manual_reset_event;
const async_manual_reset_event& m_event;
coroutine_handle<> m_awaitingCoroutine;
awaiter* m_next;
};
inline async_manual_reset_event::awaiter async_manual_reset_event::operator co_await() const noexcept
{
return awaiter{ *this };
}
}

+ 1
- 1
librf/src/future.h View File

@@ -4,7 +4,7 @@
RESUMEF_NS
{
template<class _Ty>
struct future_t
struct [[nodiscard]] future_t
{
using value_type = _Ty;
using state_type = state_t<value_type>;

+ 10
- 0
librf/src/promise.h View File

@@ -56,6 +56,16 @@ RESUMEF_NS
std::experimental::suspend_always yield_value(U&& val);
};

template<class _Ty>
struct promise_t<_Ty&> final : public promise_impl_t<_Ty&>
{
using typename promise_impl_t<_Ty&>::value_type;
using promise_impl_t<_Ty&>::get_return_object;

void return_value(_Ty& val); //co_return val
std::experimental::suspend_always yield_value(_Ty& val);
};

template<>
struct promise_t<void> final : public promise_impl_t<void>
{

+ 13
- 0
librf/src/promise.inl View File

@@ -182,6 +182,19 @@ RESUMEF_NS
return {};
}

template<class _Ty>
inline void promise_t<_Ty&>::return_value(_Ty& val)
{
this->get_state()->set_value(val);
}

template<class _Ty>
inline std::experimental::suspend_always promise_t<_Ty&>::yield_value(_Ty& val)
{
this->get_state()->promise_yield_value(this, val);
return {};
}

inline void promise_t<void>::return_void()
{
this->get_state()->set_value();

+ 17
- 17
librf/src/state.cpp View File

@@ -126,21 +126,6 @@ RESUMEF_NS
return has_handler_skip_lock();
}
void state_future_t::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
this->_exception = std::move(e);
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}
bool state_future_t::switch_scheduler_await_suspend(scheduler_t* sch, coroutine_handle<> handler)
{
assert(sch != nullptr);
@@ -177,14 +162,29 @@ RESUMEF_NS
if (this->_exception)
std::rethrow_exception(std::move(this->_exception));
if (!this->_has_value.load(std::memory_order_acquire))
if (this->_has_value.load(std::memory_order_acquire) == result_type::None)
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready}));
}
void state_t<void>::set_value()
{
scoped_lock<lock_type> __guard(this->_mtx);
this->_has_value.store(true, std::memory_order_release);
this->_has_value.store(result_type::Value, std::memory_order_release);
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}
void state_t<void>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
this->_exception = std::move(e);
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)

+ 90
- 17
librf/src/state.h View File

@@ -79,6 +79,13 @@ RESUMEF_NS
Initial,
Final
};
enum struct result_type : uint8_t
{
None,
Value,
Exception,
};
//typedef std::recursive_mutex lock_type;
typedef spinlock lock_type;
protected:
@@ -88,9 +95,8 @@ RESUMEF_NS
#if RESUMEF_DEBUG_COUNTER
intptr_t _id;
#endif
std::exception_ptr _exception;
uint32_t _alloc_size = 0;
std::atomic<bool> _has_value{ false };
std::atomic<result_type> _has_value{ result_type::None };
bool _is_awaitor;
initor_type _is_initor = initor_type::None;
public:
@@ -115,7 +121,7 @@ RESUMEF_NS
inline bool is_ready() const
{
return _exception != nullptr || _has_value.load(std::memory_order_acquire) || !_is_awaitor;
return _has_value.load(std::memory_order_acquire) != result_type::None || !_is_awaitor;
}
inline bool has_handler_skip_lock() const
{
@@ -136,18 +142,10 @@ RESUMEF_NS
return _alloc_size;
}
void set_exception(std::exception_ptr e);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
inline bool future_await_ready()
{
//scoped_lock<lock_type> __guard(this->_mtx);
return _has_value.load(std::memory_order_acquire);
return _has_value.load(std::memory_order_acquire) != result_type::None;
}
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void future_await_suspend(coroutine_handle<_PromiseT> handler);
@@ -191,23 +189,89 @@ RESUMEF_NS
public:
~state_t()
{
if (_has_value.load(std::memory_order_acquire))
cast_value_ptr()->~value_type();
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Value:
_value.~value_type();
break;
case result_type::Exception:
_exception.~exception_ptr();
break;
default:
break;
}
}
auto future_await_resume() -> value_type;
template<class _PromiseT, typename U, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise, U&& val);
void set_exception(std::exception_ptr e);
template<typename U>
void set_value(U&& val);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private:
value_type * cast_value_ptr()
union
{
return static_cast<value_type*>(static_cast<void*>(_value));
std::exception_ptr _exception;
value_type _value;
};
template<typename U>
void set_value_internal(U&& val);
void set_exception_internal(std::exception_ptr e);
};
template <typename _Ty>
struct state_t<_Ty&> final : public state_future_t
{
friend state_future_t;
using state_future_t::lock_type;
using value_type = _Ty;
using reference_type = _Ty&;
explicit state_t(size_t alloc_size) :state_future_t()
{
_alloc_size = static_cast<uint32_t>(alloc_size);
}
explicit state_t(bool awaitor) :state_future_t(awaitor)
{
_alloc_size = sizeof(*this);
}
public:
~state_t()
{
if (_has_value.load(std::memory_order_acquire) == result_type::Exception)
_exception.~exception_ptr();
}
auto future_await_resume()->reference_type;
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise, reference_type val);
alignas(value_type) unsigned char _value[sizeof(value_type)] = {0};
void set_exception(std::exception_ptr e);
void set_value(reference_type val);
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private:
union
{
std::exception_ptr _exception;
value_type* _value;
};
void set_value_internal(reference_type val);
void set_exception_internal(std::exception_ptr e);
};
template<>
@@ -229,7 +293,16 @@ RESUMEF_NS
template<class _PromiseT, typename = std::enable_if_t<is_promise_v<_PromiseT>>>
void promise_yield_value(_PromiseT* promise);
void set_exception(std::exception_ptr e);
void set_value();
template<class _Exp>
inline void throw_exception(_Exp e)
{
set_exception(std::make_exception_ptr(std::move(e)));
}
private:
std::exception_ptr _exception;
};
}

+ 172
- 19
librf/src/state.inl View File

@@ -49,6 +49,8 @@ RESUMEF_NS
sch->add_generator(this);
}

//------------------------------------------------------------------------------------------------

template<class _PromiseT, typename _Enable >
void state_t<void>::promise_yield_value(_PromiseT* promise)
{
@@ -62,7 +64,7 @@ RESUMEF_NS
this->_coro = handler;
}

this->_has_value.store(true, std::memory_order_release);
this->_has_value.store(result_type::Value, std::memory_order_release);

if (!handler.done())
{
@@ -72,6 +74,8 @@ RESUMEF_NS
}
}

//------------------------------------------------------------------------------------------------

template<typename _Ty>
template<class _PromiseT, typename U, typename _Enable >
void state_t<_Ty>::promise_yield_value(_PromiseT* promise, U&& val)
@@ -86,15 +90,7 @@ RESUMEF_NS
this->_coro = handler;
}

if (this->_has_value.load(std::memory_order_acquire))
{
*this->cast_value_ptr() = std::forward<U>(val);
}
else
{
new (this->cast_value_ptr()) value_type(std::forward<U>(val));
this->_has_value.store(true, std::memory_order_release);
}
set_value_internal(std::forward<U>(val));

if (!handler.done())
{
@@ -108,12 +104,55 @@ RESUMEF_NS
auto state_t<_Ty>::future_await_resume() -> value_type
{
scoped_lock<lock_type> __guard(this->_mtx);
if (this->_exception)

switch (this->_has_value.load(std::memory_order_acquire))
{
case result_type::None:
std::rethrow_exception(std::make_exception_ptr(future_exception{ error_code::not_ready }));
break;
case result_type::Exception:
std::rethrow_exception(std::move(this->_exception));
if (!this->_has_value.load(std::memory_order_acquire))
std::rethrow_exception(std::make_exception_ptr(future_exception{error_code::not_ready}));
break;
default:
break;
}

return std::move(this->_value);
}

template<typename _Ty>
template<typename U>
void state_t<_Ty>::set_value_internal(U&& val)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Value:
_value = std::forward<U>(val);
break;
case result_type::Exception:
_exception.~exception_ptr();
default:
new (&this->_value) value_type(std::forward<U>(val));
this->_has_value.store(result_type::Value, std::memory_order_release);
break;
}
}

return std::move(*this->cast_value_ptr());
template<typename _Ty>
void state_t<_Ty>::set_exception_internal(std::exception_ptr e)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Exception:
_exception = std::move(e);
break;
case result_type::Value:
_value.~value_type();
default:
new (&this->_exception) std::exception_ptr(std::move(e));
this->_has_value.store(result_type::Exception, std::memory_order_release);
break;
}
}

template<typename _Ty>
@@ -121,16 +160,130 @@ RESUMEF_NS
void state_t<_Ty>::set_value(U&& val)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_value_internal(std::forward<U>(val));

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}

template<typename _Ty>
void state_t<_Ty>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_exception_internal(std::move(e));

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}

//------------------------------------------------------------------------------------------------

template<typename _Ty>
template<class _PromiseT, typename _Enable >
void state_t<_Ty&>::promise_yield_value(_PromiseT* promise, reference_type val)
{
coroutine_handle<_PromiseT> handler = coroutine_handle<_PromiseT>::from_promise(*promise);

scoped_lock<lock_type> __guard(this->_mtx);

if (!handler.done())
{
if (this->_coro == nullptr)
this->_coro = handler;
}

set_value_internal(val);

if (!handler.done())
{
scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
sch->add_generator(this);
}
}

template<typename _Ty>
auto state_t<_Ty&>::future_await_resume() -> reference_type
{
scoped_lock<lock_type> __guard(this->_mtx);

switch (this->_has_value.load(std::memory_order_acquire))
{
case result_type::None:
std::rethrow_exception(std::make_exception_ptr(future_exception{ error_code::not_ready }));
break;
case result_type::Exception:
std::rethrow_exception(std::move(this->_exception));
break;
default:
break;
}

return static_cast<reference_type>(*this->_value);
}

if (this->_has_value.load(std::memory_order_acquire))
template<typename _Ty>
void state_t<_Ty&>::set_value_internal(reference_type val)
{
switch (_has_value.load(std::memory_order_acquire))
{
*this->cast_value_ptr() = std::forward<U>(val);
case result_type::Exception:
_exception.~exception_ptr();
default:
this->_value = &val;
this->_has_value.store(result_type::Value, std::memory_order_release);
break;
}
else
}

template<typename _Ty>
void state_t<_Ty&>::set_exception_internal(std::exception_ptr e)
{
switch (_has_value.load(std::memory_order_acquire))
{
case result_type::Exception:
_exception = std::move(e);
break;
default:
new (&this->_exception) std::exception_ptr(std::move(e));
this->_has_value.store(result_type::Exception, std::memory_order_release);
break;
}
}

template<typename _Ty>
void state_t<_Ty&>::set_value(reference_type val)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_value_internal(val);

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)
{
new (this->cast_value_ptr()) value_type(std::forward<U>(val));
this->_has_value.store(true, std::memory_order_release);
if (this->has_handler_skip_lock())
sch->add_generator(this);
else
sch->del_final(this);
}
}

template<typename _Ty>
void state_t<_Ty&>::set_exception(std::exception_ptr e)
{
scoped_lock<lock_type> __guard(this->_mtx);
set_exception_internal(std::move(e));

scheduler_t* sch = this->get_scheduler();
if (sch != nullptr)

+ 30
- 3
tutorial/test_async_cb.cpp View File

@@ -23,7 +23,7 @@ static void callback_get_long(int64_t val, _Ctype&& cb)
//这种情况下,没有生成 frame-context,因此,并没有promise_type被内嵌在frame-context里
static future_t<int64_t> async_get_long(int64_t val)
{
resumef::awaitable_t<int64_t> awaitable;
awaitable_t<int64_t> awaitable;
callback_get_long(val, [awaitable](int64_t val)
{
awaitable.set_value(val);
@@ -60,13 +60,40 @@ static future_t<int64_t> loop_get_long(int64_t val)
co_return val;
}
static future_t<std::string&> async_get_string(std::string & ref_string)
{
awaitable_t<std::string&> awaitable;
callback_get_long(std::stoi(ref_string), [awaitable, &ref_string](int64_t val)
{
ref_string = std::to_string(val);
awaitable.set_value(ref_string);
});
return awaitable.get_future();
}
static future_t<std::string&> resumable_get_string(std::string& val)
{
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
val = co_await async_get_string(val);
std::cout << val << std::endl;
co_return static_cast<std::string&>(val);
}
void resumable_main_cb()
{
//由于使用者可能不能明确的区分是resume function返回的awaitor还是awaitable function返回的awaitor
//导致均有可能加入到协程里去调度。
//所以,协程调度器应该需要能处理这种情况。
go async_get_long(3);
resumef::this_scheduler()->run_until_notask();
this_scheduler()->run_until_notask();
std::string ref_string{"2"};
go resumable_get_string(ref_string);
this_scheduler()->run_until_notask();
GO
{
@@ -75,5 +102,5 @@ void resumable_main_cb()
};
go loop_get_long(3);
resumef::this_scheduler()->run_until_notask();
this_scheduler()->run_until_notask();
}

+ 6
- 6
tutorial/test_async_memory_layout.cpp View File

@@ -58,9 +58,9 @@ future_t<int64_t> resumeable_get_long(int64_t x, int64_t y)
promise_type* promise = &handler.promise();
state_type* state = handler.promise().get_state();

std::cout << " future size=" << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << _Align_size<state_type>() << std::endl;
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl;
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl;

std::cout << " frame ptr=" << frame_ptr << "," << (void*)&frame_ptr << std::endl;
@@ -97,9 +97,9 @@ future_t<> resumable_get_long_2(int64_t a, int64_t b, int64_t c)
promise_type * promise = &handler.promise();
state_type * state = handler.promise().get_state();

std::cout << " future size=" << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << _Align_size<state_type>() << std::endl;
std::cout << " future size=" << sizeof(future_type) << " / " << _Align_size<future_type>() << std::endl;
std::cout << " promise size=" << sizeof(promise_type) << " / " << _Align_size<promise_type>() << std::endl;
std::cout << " state size=" << sizeof(state_type) << " / "<< _Align_size<state_type>() << std::endl;
std::cout << " frame size=" << _coro_frame_size() << ", alloc size=" << state->get_alloc_size() << std::endl;

std::cout << " frame ptr=" << frame_ptr << ","<< (void*)&frame_ptr << std::endl;

+ 1
- 1
tutorial/test_async_sleep.cpp View File

@@ -13,7 +13,7 @@ future_t<> test_sleep_use_timer()
{
using namespace std::chrono;
resumef::sleep_for(100ms); //incorrect!!!
(void)resumef::sleep_for(100ms); //incorrect!!!
co_await resumef::sleep_for(100ms);
std::cout << "sleep_for 100ms." << std::endl;

+ 2
- 2
tutorial/test_async_switch_scheduler.cpp View File

@@ -19,7 +19,7 @@ void run_in_thread(channel_t<bool>& c_done)
local_scheduler my_scheduler; //产生本线程唯一的调度器
sch_in_thread = this_scheduler(); //本线程唯一的调度器赋值给sch_in_thread,以便于后续测试直接访问此线程的调度器

c_done << true; //数据都准备好了,通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了
(void)c_done.write(true); //数据都准备好了,通过channel通知其他协程可以启动后续依赖sch_in_thread变量的协程了

//循环直到sch_in_thread为nullptr
for (;;)
@@ -71,7 +71,7 @@ static future_t<> resumable_get_long(int64_t val, channel_t<bool> & c_done)
val = co_await async_get_long(val);
std::cout << "thread = " << std::this_thread::get_id() << ", value = " << val << std::endl;

c_done << true;
(void)c_done.write(true);
}

void resumable_main_switch_scheduler()

+ 3
- 1
vs_proj/librf.cpp View File

@@ -31,7 +31,7 @@ int main(int argc, const char* argv[])
{
(void)argc;
(void)argv;
//resumable_main_resumable();
//resumable_main_layout();
//return 0;
//if (argc > 1)
@@ -61,7 +61,9 @@ int main(int argc, const char* argv[])
resumable_main_switch_scheduler();
std::cout << "ALL OK!" << std::endl;
#if !defined(__clang__) || defined(_WIN64)
benchmark_main_channel_passing_next(); //这是一个死循环测试
#endif
return 0;
}

+ 13
- 12
vs_proj/librf.vcxproj View File

@@ -34,19 +34,19 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<UseDebugLibraries>true</UseDebugLibraries>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<PlatformToolset>ClangCL</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>NotSet</CharacterSet>
</PropertyGroup>
@@ -74,9 +74,7 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<CodeAnalysisRuleSet>NativeRecommendedRules.ruleset</CodeAnalysisRuleSet>
<EnableClangTidyCodeAnalysis>true</EnableClangTidyCodeAnalysis>
@@ -110,7 +108,6 @@
<CLanguageStandard>c11</CLanguageStandard>
<CppLanguageStandard>c++1y</CppLanguageStandard>
<DisableSpecificWarnings>4834</DisableSpecificWarnings>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -131,7 +128,9 @@
<LanguageStandard>stdcpplatest</LanguageStandard>
<StringPooling>true</StringPooling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<OmitFramePointers />
<OmitFramePointers>true</OmitFramePointers>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -150,7 +149,6 @@
<PreprocessorDefinitions>NDEBUG;_CONSOLE;ASIO_STANDALONE;RESUMEF_ENABLE_MULT_SCHEDULER=1;_SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING=1;ASIO_DISABLE_CONCEPTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\librf;..\..\asio\asio\include;..\..\asio-1.10.6\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalOptions>/await</AdditionalOptions>
<ExceptionHandling>Sync</ExceptionHandling>
<FavorSizeOrSpeed>Size</FavorSizeOrSpeed>
<StringPooling>true</StringPooling>
<LanguageStandard>stdcpplatest</LanguageStandard>
@@ -163,7 +161,6 @@
<EnableFiberSafeOptimizations>true</EnableFiberSafeOptimizations>
<BufferSecurityCheck>false</BufferSecurityCheck>
<EnableParallelCodeGeneration>true</EnableParallelCodeGeneration>
<TreatWarningAsError>true</TreatWarningAsError>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
@@ -176,9 +173,13 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp" />
<ClCompile Include="..\benchmark\benchmark_asio_echo.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\benchmark\benchmark_async_mem.cpp" />
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp" />
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\librf\src\event.cpp" />
<ClCompile Include="..\librf\src\mutex.cpp" />
<ClCompile Include="..\librf\src\rf_task.cpp" />

Loading…
Cancel
Save