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
typon
typon-concurrency
Commits
913bc65a
Commit
913bc65a
authored
Aug 03, 2022
by
Xavier Thompson
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add minimal asynchronous I/O support
parent
9393f360
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
115 additions
and
0 deletions
+115
-0
rt/include/typon/io.hpp
rt/include/typon/io.hpp
+49
-0
rt/include/typon/scheduler.hpp
rt/include/typon/scheduler.hpp
+65
-0
rt/include/typon/typon.hpp
rt/include/typon/typon.hpp
+1
-0
No files found.
rt/include/typon/io.hpp
0 → 100644
View file @
913bc65a
#ifndef TYPON_IO_HPP_INCLUDED
#define TYPON_IO_HPP_INCLUDED
#include <chrono>
#include <coroutine>
#include <linux/time_types.h>
#include <liburing.h>
#include <typon/scheduler.hpp>
namespace
typon
::
io
{
template
<
typename
Rep
,
typename
Period
>
auto
sleep
(
std
::
chrono
::
duration
<
Rep
,
Period
>
duration
)
noexcept
{
struct
awaitable
:
std
::
suspend_always
{
__kernel_timespec
_ts
;
awaitable
(
std
::
chrono
::
duration
<
Rep
,
Period
>
duration
)
noexcept
{
using
namespace
std
::
chrono
;
auto
sec
=
duration_cast
<
seconds
>
(
duration
);
auto
nsec
=
duration_cast
<
nanoseconds
>
(
duration
-
sec
);
_ts
=
__kernel_timespec
({
sec
.
count
(),
nsec
.
count
()});
}
void
await_suspend
(
std
::
coroutine_handle
<>
continuation
)
noexcept
{
auto
stack
=
Scheduler
::
suspend
(
continuation
);
io_uring
*
ring
=
Scheduler
::
ring
();
io_uring_sqe
*
sqe
=
io_uring_get_sqe
(
ring
);
io_uring_prep_timeout
(
sqe
,
&
_ts
,
0
,
0
);
io_uring_sqe_set_data
(
sqe
,
stack
);
io_uring_submit
(
ring
);
}
};
return
awaitable
(
duration
);
}
}
#endif // TYPON_IO_HPP_INCLUDED
rt/include/typon/scheduler.hpp
View file @
913bc65a
...
...
@@ -28,6 +28,8 @@
#include <utility>
#include <vector>
#include <liburing.h>
#include <typon/event_count.hpp>
#include <typon/garbage_collector.hpp>
#include <typon/pool.hpp>
...
...
@@ -52,7 +54,9 @@ namespace typon
EventCount
<>
_notifyer
;
std
::
vector
<
Pool
>
_pool
;
std
::
vector
<
Stack
*>
_stack
;
std
::
vector
<
io_uring
>
_ring
;
std
::
vector
<
std
::
thread
>
_thread
;
std
::
vector
<
std
::
thread
>
_io_thread
;
GarbageCollector
_gc
;
static
inline
thread_local
uint
thread_id
;
...
...
@@ -63,6 +67,11 @@ namespace typon
return
scheduler
;
}
static
io_uring
*
ring
()
noexcept
{
return
&
(
get
().
_ring
[
thread_id
]);
}
static
void
schedule
(
std
::
coroutine_handle
<>
coroutine
)
noexcept
{
Pool
&
pool
=
get
().
random
();
...
...
@@ -124,8 +133,20 @@ namespace typon
,
_mask
((
1
<<
std
::
bit_width
(
concurrency
))
-
1
)
,
_pool
(
this
->
_mask
+
1
)
,
_stack
(
concurrency
,
nullptr
)
,
_ring
(
concurrency
)
,
_gc
(
concurrency
)
{
// Initialize I/O rings
for
(
uint
id
=
0
;
id
<
concurrency
;
id
++
)
{
// The queue depth can be 1 because we submit requests one by one
if
(
io_uring_queue_init
(
1
,
&
(
_ring
[
id
]),
0
))
{
std
::
terminate
();
}
}
// Spawn worker threads
for
(
uint
id
=
0
;
id
<
concurrency
;
id
++
)
{
_thread
.
emplace_back
([
this
,
id
]()
{
...
...
@@ -141,6 +162,29 @@ namespace typon
}
});
}
// Spawn I/O completion threads
for
(
uint
id
=
0
;
id
<
concurrency
;
id
++
)
{
_io_thread
.
emplace_back
([
this
,
id
]()
{
io_uring
*
ring
=
&
(
_ring
[
id
]);
for
(;;)
{
io_uring_cqe
*
cqe
;
if
(
io_uring_wait_cqe
(
ring
,
&
cqe
))
{
throw
std
::
runtime_error
(
"io_uring_wait_cqe() => failed"
);
}
void
*
data
=
io_uring_cqe_get_data
(
cqe
);
io_uring_cqe_seen
(
ring
,
cqe
);
if
(
!
data
)
{
break
;
}
Scheduler
::
enable
(
reinterpret_cast
<
Stack
*>
(
data
));
}
});
}
}
bool
wait_for_work
(
std
::
coroutine_handle
<>
&
coroutine
)
noexcept
...
...
@@ -269,12 +313,33 @@ namespace typon
~
Scheduler
()
noexcept
{
// Signal worker threads to stop
_done
.
store
(
true
);
_notifyer
.
notify_all
();
// Wait until all worker threads are done
for
(
auto
&
t
:
_thread
)
{
t
.
join
();
}
// Signal I/O threads to stop
for
(
uint
id
=
0
;
id
<
_concurrency
;
id
++
)
{
// An sqe should be available, because SQPOLL is not used
io_uring_sqe
*
sqe
=
io_uring_get_sqe
(
&
(
_ring
[
id
]));
io_uring_prep_nop
(
sqe
);
io_uring_sqe_set_data
(
sqe
,
nullptr
);
io_uring_submit
(
&
(
_ring
[
id
]));
}
// Wait until all I/O threads are done
for
(
auto
&
t
:
_io_thread
)
{
t
.
join
();
}
// Cleanup all I/O rings
for
(
uint
id
=
0
;
id
<
_concurrency
;
id
++
)
{
io_uring_queue_exit
(
&
(
_ring
[
id
]));
}
}
};
...
...
rt/include/typon/typon.hpp
View file @
913bc65a
...
...
@@ -6,6 +6,7 @@
#include <typon/fork.hpp>
#include <typon/forked.hpp>
#include <typon/future.hpp>
#include <typon/io.hpp>
#include <typon/join.hpp>
#include <typon/meta.hpp>
#include <typon/mutex.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