Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
T
typon-concurrency
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Xavier Thompson
typon-concurrency
Commits
6d4be662
Commit
6d4be662
authored
Jul 13, 2022
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement asychronous mutex in mutex.hpp
parent
bcfdf8a3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
89 additions
and
0 deletions
+89
-0
rt/include/typon/mutex.hpp
rt/include/typon/mutex.hpp
+88
-0
rt/include/typon/typon.hpp
rt/include/typon/typon.hpp
+1
-0
No files found.
rt/include/typon/mutex.hpp
0 → 100644
View file @
6d4be662
#ifndef TYPON_MUTEX_HPP_INCLUDED
#define TYPON_MUTEX_HPP_INCLUDED
#include <atomic>
#include <coroutine>
#include <typon/scheduler.hpp>
#include <typon/stack.hpp>
namespace
typon
{
/* An asynchronous mutex.
Based on the MCS lock, but without the spinning. This means it should be
easy to implement spinning before suspension.
Disadvantage: each lock acquisition incurs an allocation. The alternative
is to potentially spin when unlocking.
*/
struct
Mutex
{
struct
Node
{
std
::
atomic
<
Node
*>
_next
{
nullptr
};
Stack
*
_stack
;
};
std
::
atomic
<
Node
*>
_state
{
nullptr
};
[[
nodiscard
]]
auto
lock
()
noexcept
{
struct
awaitable
{
std
::
atomic
<
Node
*>
&
_state
;
Node
*
_prev
;
Node
*
_node
;
bool
await_ready
()
noexcept
{
return
!
_prev
;
}
void
await_suspend
(
std
::
coroutine_handle
<>
coroutine
)
noexcept
{
auto
stack
=
_node
->
_stack
=
Scheduler
::
suspend
(
coroutine
);
auto
ready
=
_prev
->
_next
.
exchange
(
_node
);
if
(
ready
)
{
delete
_prev
;
Scheduler
::
enable
(
stack
);
}
}
void
await_resume
()
noexcept
{};
~
awaitable
()
{
Node
*
node
=
_node
;
bool
waiters
=
!
_state
.
compare_exchange_strong
(
node
,
nullptr
);
if
(
waiters
)
{
node
=
_node
;
auto
next
=
node
->
_next
.
exchange
(
_node
);
if
(
next
)
{
delete
node
;
Scheduler
::
enable
(
next
->
_stack
);
}
}
else
{
delete
node
;
}
}
};
auto
node
=
new
Node
();
auto
prev
=
_state
.
exchange
(
node
);
return
awaitable
{
this
->
_state
,
prev
,
node
};
}
};
}
#endif // TYPON_MUTEX_HPP_INCLUDED
rt/include/typon/typon.hpp
View file @
6d4be662
...
...
@@ -7,6 +7,7 @@
#include <typon/forked.hpp>
#include <typon/future.hpp>
#include <typon/join.hpp>
#include <typon/mutex.hpp>
#include <typon/promise.hpp>
#include <typon/root.hpp>
#include <typon/task.hpp>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment