Browse Source

实现mutex第二版

tags/v2.9.7
tearshark 4 years ago
parent
commit
946656e34e

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

@@ -1,6 +1,6 @@
#pragma once
#define LIB_RESUMEF_VERSION 20700 // 2.7.0
#define LIB_RESUMEF_VERSION 20800 // 2.8.0
#if defined(RESUMEF_MODULE_EXPORT)
#define RESUMEF_NS export namespace resumef

+ 1
- 0
librf/src/exception.inl View File

@@ -10,6 +10,7 @@ RESUMEF_NS
unlock_more, // unlock 次数多余lock次数
read_before_write, // 0容量的channel,先读后写
timer_canceled, // 定时器被意外取消
not_await_lock, // 没有在协程中使用co_await等待lock结果

max__
};

+ 3
- 87
librf/src/mutex.h View File

@@ -1,89 +1,5 @@
#pragma once
RESUMEF_NS
{
namespace detail
{
struct mutex_impl;
typedef ::resumef::detail::_awaker<mutex_impl> mutex_awaker;
typedef std::shared_ptr<mutex_awaker> mutex_awaker_ptr;
struct mutex_impl : public std::enable_shared_from_this<mutex_impl>
{
private:
//typedef spinlock lock_type;
typedef std::recursive_mutex lock_type;
std::list<mutex_awaker_ptr> _awakes;
mutex_awaker_ptr _owner;
lock_type _lock;
public:
mutex_impl();
//如果已经触发了awaker,则返回true
bool lock_(const mutex_awaker_ptr& awaker);
bool try_lock_(const mutex_awaker_ptr& awaker);
void unlock();
template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>>
decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr)
{
(void)dummy_;
return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(awaker)));
}
private:
mutex_impl(const mutex_impl&) = delete;
mutex_impl(mutex_impl&&) = delete;
mutex_impl& operator = (const mutex_impl&) = delete;
mutex_impl& operator = (mutex_impl&&) = delete;
};
}
struct mutex_t
{
typedef std::shared_ptr<detail::mutex_impl> lock_impl_ptr;
typedef std::weak_ptr<detail::mutex_impl> lock_impl_wptr;
typedef std::chrono::system_clock clock_type;
private:
lock_impl_ptr _locker;
public:
mutex_t();
void unlock() const
{
_locker->unlock();
}
future_t<bool> lock() const;
bool try_lock() const;
/*
template<class _Rep, class _Period>
awaitable_t<bool>
try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const
{
return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt));
}
template<class _Clock, class _Duration>
awaitable_t<bool>
try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const
{
return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(tp));
}
*/
mutex_t(const mutex_t&) = default;
mutex_t(mutex_t&&) = default;
mutex_t& operator = (const mutex_t&) = default;
mutex_t& operator = (mutex_t&&) = default;
private:
inline future_t<bool> try_lock_for_(const clock_type::duration& dt) const
{
return try_lock_until_(clock_type::now() + dt);
}
future_t<bool> try_lock_until_(const clock_type::time_point& tp) const;
};
}
#include "mutex_v1.h"
#include "mutex_v2.h"
#include "mutex_v2.inl"

librf/src/mutex.cpp → librf/src/mutex_v1.cpp View File

@@ -1,124 +1,128 @@
#include "../librf.h"
RESUMEF_NS
{
namespace detail
{
mutex_impl::mutex_impl()
{
}
void mutex_impl::unlock()
{
scoped_lock<lock_type> lock_(this->_lock);
if (_owner != nullptr)
{
for (auto iter = _awakes.begin(); iter != _awakes.end(); )
{
auto awaker = *iter;
iter = _awakes.erase(iter);
if (awaker->awake(this, 1))
{
_owner = awaker;
break;
}
}
if (_awakes.size() == 0)
{
_owner = nullptr;
}
}
}
bool mutex_impl::lock_(const mutex_awaker_ptr & awaker)
{
assert(awaker);
scoped_lock<lock_type> lock_(this->_lock);
if (_owner == nullptr)
{
_owner = awaker;
awaker->awake(this, 1);
return true;
}
else
{
_awakes.push_back(awaker);
return false;
}
}
bool mutex_impl::try_lock_(const mutex_awaker_ptr & awaker)
{
assert(awaker);
scoped_lock<lock_type> lock_(this->_lock);
if (_owner == nullptr)
{
_owner = awaker;
return true;
}
else
{
return false;
}
}
}
mutex_t::mutex_t()
: _locker(std::make_shared<detail::mutex_impl>())
{
}
future_t<bool> mutex_t::lock() const
{
awaitable_t<bool> awaitable;
auto awaker = std::make_shared<detail::mutex_awaker>(
[st = awaitable._state](detail::mutex_impl * e) -> bool
{
st->set_value(e ? true : false);
return true;
});
_locker->lock_(awaker);
return awaitable.get_future();
}
bool mutex_t::try_lock() const
{
auto dummy_awaker = std::make_shared<detail::mutex_awaker>(
[](detail::mutex_impl * ) -> bool
{
return true;
});
return _locker->try_lock_(dummy_awaker);
}
future_t<bool> mutex_t::try_lock_until_(const clock_type::time_point & tp) const
{
awaitable_t<bool> awaitable;
auto awaker = std::make_shared<detail::mutex_awaker>(
[st = awaitable._state](detail::mutex_impl * e) -> bool
{
st->set_value(e ? true : false);
return true;
});
_locker->lock_(awaker);
(void)this_scheduler()->timer()->add(tp,
[awaker](bool )
{
awaker->awake(nullptr, 1);
});
return awaitable.get_future();
}
}
#include "../librf.h"

RESUMEF_NS
{
namespace detail
{
mutex_impl::mutex_impl()
{
}

void mutex_impl::unlock()
{
scoped_lock<lock_type> lock_(this->_lock);

if (_owner != nullptr)
{
for (auto iter = _awakes.begin(); iter != _awakes.end(); )
{
auto awaker = *iter;
iter = _awakes.erase(iter);

if (awaker->awake(this, 1))
{
_owner = awaker;
break;
}

}
if (_awakes.size() == 0)
{
_owner = nullptr;
}
}
}

bool mutex_impl::lock_(const mutex_awaker_ptr& awaker)
{
assert(awaker);

scoped_lock<lock_type> lock_(this->_lock);

if (_owner == nullptr)
{
_owner = awaker;
awaker->awake(this, 1);
return true;
}
else
{
_awakes.push_back(awaker);
return false;
}
}

bool mutex_impl::try_lock_(const mutex_awaker_ptr& awaker)
{
assert(awaker);

scoped_lock<lock_type> lock_(this->_lock);

if (_owner == nullptr)
{
_owner = awaker;
return true;
}
else
{
return false;
}
}

}

namespace mutex_v1
{

mutex_t::mutex_t()
: _locker(std::make_shared<detail::mutex_impl>())
{
}

future_t<bool> mutex_t::lock() const
{
awaitable_t<bool> awaitable;

auto awaker = std::make_shared<detail::mutex_awaker>(
[st = awaitable._state](detail::mutex_impl* e) -> bool
{
st->set_value(e ? true : false);
return true;
});
_locker->lock_(awaker);

return awaitable.get_future();
}

bool mutex_t::try_lock() const
{
auto dummy_awaker = std::make_shared<detail::mutex_awaker>(
[](detail::mutex_impl*) -> bool
{
return true;
});
return _locker->try_lock_(dummy_awaker);
}

future_t<bool> mutex_t::try_lock_until_(const clock_type::time_point& tp) const
{
awaitable_t<bool> awaitable;

auto awaker = std::make_shared<detail::mutex_awaker>(
[st = awaitable._state](detail::mutex_impl* e) -> bool
{
st->set_value(e ? true : false);
return true;
});
_locker->lock_(awaker);

(void)this_scheduler()->timer()->add(tp,
[awaker](bool)
{
awaker->awake(nullptr, 1);
});

return awaitable.get_future();
}
}
}

+ 92
- 0
librf/src/mutex_v1.h View File

@@ -0,0 +1,92 @@
#pragma once

RESUMEF_NS
{
namespace detail
{
struct mutex_impl;
typedef ::resumef::detail::_awaker<mutex_impl> mutex_awaker;
typedef std::shared_ptr<mutex_awaker> mutex_awaker_ptr;

struct mutex_impl : public std::enable_shared_from_this<mutex_impl>
{
private:
//typedef spinlock lock_type;
typedef std::recursive_mutex lock_type;

std::list<mutex_awaker_ptr> _awakes;
mutex_awaker_ptr _owner;
lock_type _lock;
public:
mutex_impl();

//如果已经触发了awaker,则返回true
bool lock_(const mutex_awaker_ptr& awaker);
bool try_lock_(const mutex_awaker_ptr& awaker);
void unlock();

template<class callee_t, class dummy_t = std::enable_if<!std::is_same<std::remove_cv_t<callee_t>, mutex_awaker_ptr>::value>>
decltype(auto) lock(callee_t&& awaker, dummy_t* dummy_ = nullptr)
{
(void)dummy_;
return lock_(std::make_shared<mutex_awaker>(std::forward<callee_t>(awaker)));
}

private:
mutex_impl(const mutex_impl&) = delete;
mutex_impl(mutex_impl&&) = delete;
mutex_impl& operator = (const mutex_impl&) = delete;
mutex_impl& operator = (mutex_impl&&) = delete;
};
}

namespace mutex_v1
{
struct mutex_t
{
typedef std::shared_ptr<detail::mutex_impl> lock_impl_ptr;
typedef std::weak_ptr<detail::mutex_impl> lock_impl_wptr;
typedef std::chrono::system_clock clock_type;
private:
lock_impl_ptr _locker;
public:
mutex_t();

void unlock() const
{
_locker->unlock();
}


future_t<bool> lock() const;
bool try_lock() const;

/*
template<class _Rep, class _Period>
awaitable_t<bool>
try_lock_for(const std::chrono::duration<_Rep, _Period> & dt) const
{
return try_lock_for_(std::chrono::duration_cast<clock_type::duration>(dt));
}
template<class _Clock, class _Duration>
awaitable_t<bool>
try_lock_until(const std::chrono::time_point<_Clock, _Duration> & tp) const
{
return try_lock_until_(std::chrono::time_point_cast<clock_type::duration>(tp));
}
*/


mutex_t(const mutex_t&) = default;
mutex_t(mutex_t&&) = default;
mutex_t& operator = (const mutex_t&) = default;
mutex_t& operator = (mutex_t&&) = default;
private:
inline future_t<bool> try_lock_for_(const clock_type::duration& dt) const
{
return try_lock_until_(clock_type::now() + dt);
}
future_t<bool> try_lock_until_(const clock_type::time_point& tp) const;
};
}
}

+ 127
- 0
librf/src/mutex_v2.cpp View File

@@ -0,0 +1,127 @@
#include "../librf.h"

RESUMEF_NS
{
namespace detail
{
void state_mutex_t::resume()
{
coroutine_handle<> handler = _coro;
if (handler)
{
_coro = nullptr;
_scheduler->del_final(this);
handler.resume();
}
}

bool state_mutex_t::has_handler() const noexcept
{
return (bool)_coro;
}
state_base_t* state_mutex_t::get_parent() const noexcept
{
return _root;
}

bool state_mutex_t::on_notify()
{
assert(this->_scheduler != nullptr);
if (this->_coro)
{
this->_scheduler->add_generator(this);
return true;
}

return false;
}

void mutex_v2_impl::lock_until_succeed(void* sch)
{
assert(sch != nullptr);

for (;;)
{
if (try_lock(sch))
break;
std::this_thread::yield();
}
}

bool mutex_v2_impl::try_lock(void* sch) noexcept
{
scoped_lock<detail::mutex_v2_impl::lock_type> lock_(_lock);
return try_lock_lockless(sch);
}

bool mutex_v2_impl::try_lock_lockless(void* sch) noexcept
{
void* oldValue = _owner.load(std::memory_order_relaxed);
if (oldValue == nullptr || oldValue == sch)
{
_owner.store(sch, std::memory_order_relaxed);
_counter.fetch_add(1, std::memory_order_relaxed);

return true;
}
return false;
}

bool mutex_v2_impl::unlock(void* sch)
{
scoped_lock<lock_type> lock_(_lock);

void* oldValue = _owner.load(std::memory_order_relaxed);
if (oldValue == sch)
{
if (_counter.fetch_sub(1, std::memory_order_relaxed) == 1)
{
if (!_wait_awakes.empty())
{
state_mutex_ptr state = _wait_awakes.front();
_wait_awakes.pop_front();

//锁定状态转移到新的state上
_owner.store(state->get_root(), std::memory_order_relaxed);
_counter.fetch_add(1, std::memory_order_relaxed);

state->on_notify();
}
else
{
_owner.store(nullptr, std::memory_order_relaxed);
}
}

return true;
}

return false;
}

void mutex_v2_impl::add_wait_list_lockless(state_mutex_t* state)
{
assert(state != nullptr);

_wait_awakes.push_back(state);
}
}

inline namespace mutex_v2
{
mutex_t::mutex_t()
: _mutex(std::make_shared<detail::mutex_v2_impl>())
{
}

mutex_t::mutex_t(std::adopt_lock_t) noexcept
{
}

mutex_t::~mutex_t() noexcept
{
}
}
}

+ 40
- 0
librf/src/mutex_v2.h View File

@@ -0,0 +1,40 @@
#pragma once

RESUMEF_NS
{
namespace detail
{
struct mutex_v2_impl;
}

inline namespace mutex_v2
{
struct scoped_lock_mutex_t;

struct mutex_t
{
typedef std::shared_ptr<detail::mutex_v2_impl> mutex_impl_ptr;
typedef std::chrono::system_clock clock_type;

mutex_t();
mutex_t(std::adopt_lock_t) noexcept;
~mutex_t() noexcept;

struct [[nodiscard]] awaiter;

awaiter lock() const noexcept;

scoped_lock_mutex_t lock(scheduler_t* sch) const noexcept;
bool try_lock(scheduler_t* sch) const noexcept;
void unlock(scheduler_t* sch) const noexcept;

mutex_t(const mutex_t&) = default;
mutex_t(mutex_t&&) = default;
mutex_t& operator = (const mutex_t&) = default;
mutex_t& operator = (mutex_t&&) = default;
private:
friend struct scoped_lock_mutex_t;
mutex_impl_ptr _mutex;
};
}
}

+ 203
- 0
librf/src/mutex_v2.inl View File

@@ -0,0 +1,203 @@
#pragma once

RESUMEF_NS
{
namespace detail
{
struct state_mutex_t : public state_base_t
{
virtual void resume() override;
virtual bool has_handler() const noexcept override;
virtual state_base_t* get_parent() const noexcept override;

bool on_notify();

inline scheduler_t* get_scheduler() const noexcept
{
return _scheduler;
}

inline void on_await_suspend(coroutine_handle<> handler, scheduler_t* sch, state_base_t* root) noexcept
{
this->_scheduler = sch;
this->_coro = handler;
this->_root = root;
}

private:
state_base_t* _root;
//friend mutex_v2::mutex_t;
};

//做成递归锁?
struct mutex_v2_impl : public std::enable_shared_from_this<mutex_v2_impl>
{
mutex_v2_impl() {}

inline void* owner() const noexcept
{
return _owner.load(std::memory_order_relaxed);
}

bool try_lock(void* sch) noexcept; //内部加锁
bool unlock(void* sch); //内部加锁
void lock_until_succeed(void* sch); //内部加锁
public:
static constexpr bool USE_SPINLOCK = true;

using lock_type = std::conditional_t<USE_SPINLOCK, spinlock, std::recursive_mutex>;
using state_mutex_ptr = counted_ptr<state_mutex_t>;
using wait_queue_type = std::list<state_mutex_ptr>;

bool try_lock_lockless(void* sch) noexcept; //内部不加锁,加锁由外部来进行
void add_wait_list_lockless(state_mutex_t* state); //内部不加锁,加锁由外部来进行

lock_type _lock; //保证访问本对象是线程安全的
private:
std::atomic<void*> _owner = nullptr; //锁标记
std::atomic<intptr_t> _counter = 0; //递归锁的次数
wait_queue_type _wait_awakes; //等待队列

// No copying/moving
mutex_v2_impl(const mutex_v2_impl&) = delete;
mutex_v2_impl(mutex_v2_impl&&) = delete;
mutex_v2_impl& operator=(const mutex_v2_impl&) = delete;
mutex_v2_impl& operator=(mutex_v2_impl&&) = delete;
};
}

inline namespace mutex_v2
{
struct scoped_lock_mutex_t
{
typedef std::shared_ptr<detail::mutex_v2_impl> mutex_impl_ptr;

//此函数,应该在try_lock()获得锁后使用
//或者在协程里,由awaiter使用
scoped_lock_mutex_t(std::adopt_lock_t, detail::mutex_v2_impl* mtx, void* sch)
: _mutex(mtx->shared_from_this())
, _owner(sch)
{}

//此函数,适合在非协程里使用
scoped_lock_mutex_t(detail::mutex_v2_impl* mtx, void* sch)
: _mutex(mtx->shared_from_this())
, _owner(sch)
{
if (sch != nullptr)
_mutex->lock_until_succeed(sch);
}


scoped_lock_mutex_t(std::adopt_lock_t, const mutex_t& mtx, void* sch)
: scoped_lock_mutex_t(std::adopt_lock, mtx._mutex.get(), sch)
{}
scoped_lock_mutex_t(const mutex_t& mtx, void* sch)
: scoped_lock_mutex_t(mtx._mutex.get(), sch)
{}

~scoped_lock_mutex_t()
{
if (_mutex != nullptr)
_mutex->unlock(_owner);
}

inline void unlock() noexcept
{
if (_mutex != nullptr)
{
_mutex->unlock(_owner);
_mutex = nullptr;
}
}

scoped_lock_mutex_t(const scoped_lock_mutex_t&) = delete;
scoped_lock_mutex_t& operator = (const scoped_lock_mutex_t&) = delete;
scoped_lock_mutex_t(scoped_lock_mutex_t&&) = default;
scoped_lock_mutex_t& operator = (scoped_lock_mutex_t&&) = default;
private:
mutex_impl_ptr _mutex;
void* _owner;
};


struct [[nodiscard]] mutex_t::awaiter
{
awaiter(detail::mutex_v2_impl* evt) noexcept
: _mutex(evt)
{
}

~awaiter() noexcept(false)
{
assert(_mutex == nullptr);
if (_mutex != nullptr)
{
throw lock_exception(error_code::not_await_lock);
}
}

bool await_ready() noexcept
{
return false;
}

template<class _PromiseT, typename = std::enable_if_t<traits::is_promise_v<_PromiseT>>>
bool await_suspend(coroutine_handle<_PromiseT> handler)
{
_PromiseT& promise = handler.promise();
auto* parent = promise.get_state();
_root = parent->get_root();

scoped_lock<detail::mutex_v2_impl::lock_type> lock_(_mutex->_lock);
if (_mutex->try_lock_lockless(_root))
return false;

_state = new detail::state_mutex_t();
(void)_state->on_await_suspend(handler, parent->get_scheduler(), _root);

_mutex->add_wait_list_lockless(_state.get());

return true;
}

scoped_lock_mutex_t await_resume() noexcept
{
detail::mutex_v2_impl* mtx = _mutex;
_mutex = nullptr;

return { std::adopt_lock, mtx, _root };
}
protected:
detail::mutex_v2_impl* _mutex;
counted_ptr<detail::state_mutex_t> _state;
state_base_t* _root = nullptr;
};

inline mutex_t::awaiter mutex_t::lock() const noexcept
{
return { _mutex.get() };
}

inline scoped_lock_mutex_t mutex_t::lock(scheduler_t* sch) const noexcept
{
if (sch != nullptr)
_mutex->lock_until_succeed(sch);

return { std::adopt_lock, _mutex.get(), sch };
}

inline bool mutex_t::try_lock(scheduler_t* sch) const noexcept
{
if (sch == nullptr)
return false;
return _mutex->try_lock(sch);
}

inline void mutex_t::unlock(scheduler_t* sch) const noexcept
{
assert(sch != nullptr);
_mutex->unlock(sch);
}
}
}

+ 1
- 0
librf/src/scheduler.cpp View File

@@ -18,6 +18,7 @@ RESUMEF_NS
"unlock_more",
"read_before_write",
"timer_canceled",
"not_await_lock",
};
char sz_future_error_buffer[256];

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

@@ -15,7 +15,7 @@ RESUMEF_NS
static const int FREE_VALUE = 0;
static const int LOCKED_VALUE = 1;
volatile std::atomic<int> lck;
std::atomic<int> lck;
#if _DEBUG
std::thread::id owner_thread_id;
#endif

+ 10
- 0
librf/src/state.cpp View File

@@ -10,6 +10,11 @@ RESUMEF_NS
{
delete this;
}
state_base_t* state_base_t::get_parent() const noexcept
{
return nullptr;
}
void state_future_t::destroy_deallocate()
{
@@ -88,6 +93,11 @@ RESUMEF_NS
return true;
}
state_base_t* state_future_t::get_parent() const noexcept
{
return _parent;
}
void state_future_t::resume()
{
std::unique_lock<lock_type> __guard(_mtx);

+ 15
- 5
librf/src/state.h View File

@@ -33,6 +33,7 @@ RESUMEF_NS
public:
virtual void resume() = 0;
virtual bool has_handler() const noexcept = 0;
virtual state_base_t* get_parent() const noexcept;
void set_scheduler(scheduler_t* sch)
{
@@ -42,6 +43,18 @@ RESUMEF_NS
{
return _coro;
}
state_base_t* get_root() const noexcept
{
state_base_t* root = const_cast<state_base_t*>(this);
state_base_t* next = root->get_parent();
while (next != nullptr)
{
root = next;
next = next->get_parent();
}
return root;
}
};
struct state_generator_t : public state_base_t
@@ -125,7 +138,8 @@ RESUMEF_NS
virtual void destroy_deallocate() override;
virtual void resume() override;
virtual bool has_handler() const noexcept override;
virtual state_base_t* get_parent() const noexcept override;
inline bool is_ready() const noexcept
{
//msvc认为是constexpr表达式(不写还给警告),然而,clang不这么认为。
@@ -149,10 +163,6 @@ RESUMEF_NS
return _parent ? _parent->get_scheduler() : _scheduler;
}
inline state_base_t * get_parent() const noexcept
{
return _parent;
}
inline uint32_t get_alloc_size() const noexcept
{
return _alloc_size;

+ 5
- 4
tutorial/test_async_mutex.cpp View File

@@ -19,7 +19,7 @@ future_t<> test_mutex_pop(size_t idx)
for (size_t i = 0; i < 10; ++i)
{
co_await resumf_guard_lock(g_lock);
auto _locker = co_await g_lock.lock();
if (g_queue.size() > 0)
{
@@ -32,14 +32,15 @@ future_t<> test_mutex_pop(size_t idx)
}
}
future_t<> test_mutex_push()
future_t<> test_mutex_push(size_t idx)
{
using namespace std::chrono;
for (size_t i = 0; i < 10; ++i)
{
co_await resumf_guard_lock(g_lock);
auto _locker = co_await g_lock.lock();
g_queue.push_back(i);
std::cout << i << " on " << idx << std::endl;
co_await sleep_for(500ms);
}
@@ -47,7 +48,7 @@ future_t<> test_mutex_push()
void resumable_main_mutex()
{
go test_mutex_push();
go test_mutex_push(0);
go test_mutex_pop(1);
this_scheduler()->run_until_notask();

+ 2
- 1
vs_proj/librf.cpp View File

@@ -47,7 +47,8 @@ int main(int argc, const char* argv[])
//resumable_main_event();
//resumable_main_event_timeout();
//resumable_main_sleep();
//return 0;
resumable_main_mutex();
return 0;
//if (argc > 1)
// resumable_main_benchmark_asio_client(atoi(argv[1]));

+ 5
- 1
vs_proj/librf.vcxproj View File

@@ -183,7 +183,8 @@
<ClCompile Include="..\benchmark\benchmark_channel_passing_next.cpp" />
<ClCompile Include="..\librf\src\event_v1.cpp" />
<ClCompile Include="..\librf\src\event_v2.cpp" />
<ClCompile Include="..\librf\src\mutex.cpp" />
<ClCompile Include="..\librf\src\mutex_v1.cpp" />
<ClCompile Include="..\librf\src\mutex_v2.cpp" />
<ClCompile Include="..\librf\src\rf_task.cpp" />
<ClCompile Include="..\librf\src\scheduler.cpp" />
<ClCompile Include="..\librf\src\sleep.cpp" />
@@ -233,6 +234,8 @@
<ClInclude Include="..\librf\src\future.h" />
<ClInclude Include="..\librf\src\generator.h" />
<ClInclude Include="..\librf\src\intrusive_link_queue.h" />
<ClInclude Include="..\librf\src\mutex_v1.h" />
<ClInclude Include="..\librf\src\mutex_v2.h" />
<ClInclude Include="..\librf\src\promise.h" />
<ClInclude Include="..\librf\src\mutex.h" />
<ClInclude Include="..\librf\src\rf_task.h" />
@@ -260,6 +263,7 @@
<None Include="..\librf\src\event_v2.inl" />
<None Include="..\librf\src\exception.inl" />
<None Include="..\librf\src\macro_def.inl" />
<None Include="..\librf\src\mutex_v2.inl" />
<None Include="..\librf\src\promise.inl" />
<None Include="..\librf\src\state.inl" />
<None Include="..\librf\src\type_concept.inl" />

+ 15
- 3
vs_proj/librf.vcxproj.filters View File

@@ -25,9 +25,6 @@
<ClCompile Include="librf.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\librf\src\mutex.cpp">
<Filter>librf\src</Filter>
</ClCompile>
<ClCompile Include="..\librf\src\rf_task.cpp">
<Filter>librf\src</Filter>
</ClCompile>
@@ -121,6 +118,12 @@
<ClCompile Include="..\librf\src\when_v2.cpp">
<Filter>librf\src</Filter>
</ClCompile>
<ClCompile Include="..\librf\src\mutex_v1.cpp">
<Filter>librf\src</Filter>
</ClCompile>
<ClCompile Include="..\librf\src\mutex_v2.cpp">
<Filter>librf\src</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="..\librf\librf.h">
@@ -228,6 +231,12 @@
<ClInclude Include="..\librf\src\when_v2.h">
<Filter>librf\src</Filter>
</ClInclude>
<ClInclude Include="..\librf\src\mutex_v1.h">
<Filter>librf\src</Filter>
</ClInclude>
<ClInclude Include="..\librf\src\mutex_v2.h">
<Filter>librf\src</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<None Include="..\librf\src\asio_task_1.12.0.inl">
@@ -261,5 +270,8 @@
<None Include="..\librf\src\type_concept.inl">
<Filter>librf\src</Filter>
</None>
<None Include="..\librf\src\mutex_v2.inl">
<Filter>librf\src</Filter>
</None>
</ItemGroup>
</Project>

Loading…
Cancel
Save