-
Notifications
You must be signed in to change notification settings - Fork 473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for linux scheduler and timer #64
base: master
Are you sure you want to change the base?
support for linux scheduler and timer #64
Conversation
I will move over to using std::invoke_result_t once I have confirmed that it is supported by clang/libc++ as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@neo5167 Thanks very much for the PR.
I've had a read over the code and made some notes on some issues I found.
I think some of the functions with #ifdefs are a bit messy where we're trying to keep some common logic but then also having Linux-specific and Windows-specific parts. I wonder whether it would be more maintainable to put the #ifdefs outside of the function for some of these functions and cop a little bit of duplication between Windows/Linux versions in return for more readable code.
I'm also considering separating out the platform-specific bits into separate *_win32.cpp
or *_linux.cpp
files for some abstractions rather than sprinkling #ifdef around everywhere. It may require some refactoring to get there, though, so we can move towards that direction in time.
lib/linux.cpp
Outdated
{ | ||
m_mqdt = -1; | ||
uuid_t unique_name; | ||
const char* cppcoro_qname_prefix = "/cppcoro-"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a pity the Linux API doesn't provide a way to create anonymous message queues...
lib/linux.cpp
Outdated
for(;;) | ||
{ | ||
uuid_generate(unique_name); | ||
uuid_unparse(unique_name, m_qname + sizeof(cppcoro_qname_prefix)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sizeof(cppcoro_qname_prefix)
is really just doing a sizeof(const char*)
which will always be 4 or 8.
I assume you meant for this to be using strlen(cppcoro_qname_prefix)
?
Or perhaps declare cppcoro_qname_prefix
to have type const char[10]
?
lib/linux.cpp
Outdated
{ | ||
close(m_epollfd); | ||
assert(mq_close(m_mqdt) == 0); | ||
assert(mq_unlink(m_qname) == 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Won't these calls to mq_close
and mq_unlink
be compiled out under optimised builds when NDEBUG
is defined?
Can the calls be moved out of the assert()
statements and just assert()
the comparison of the result.
lib/linux.cpp
Outdated
} | ||
|
||
message qmsg; | ||
ssize_t status = mq_receive(m_mqdt, (char*)&qmsg, sizeof(message), NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think there might be a possible race condition here if multiple threads concurrently call dequeue_message()
that could cause one of the threads to block on the mq_receive
call.
eg. consider if there is a single item in the queue and this signals the epoll handle. Both threads enter dequeue_message()
and the call to epoll_wait()
returns immediately with 1 for both threads since the message queue file descriptor is ready. The first thread to call mq_receive()
dequeues the only message and the second thread to call mq_receive()
blocks, waiting for another item to be queued to the message queue.
This may not be an issue in practice for calls that pass true
to the wait
parameter, but could lead to long delays for calls that pass false
to concurrent calls.
test/scheduling_operator_tests.cpp
Outdated
|
||
#if CPPCORO_OS_LINUX | ||
#define THREAD_ID unsigned long long | ||
#define GET_THIS_THREAD_ID get_thread_id() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why are all of these macros necessary?
As far as I can see, all of the usages down below were previously just comparing std::thread::id
values, so I don't quite follow why we need to try and convert the thread id into an unsigned long long
.
I would have thought that std::this_thread::get_id()
would work just fine.
Is it an issue with unresolved symbols for the operator<<
for std::thread::id
due to the use of the doctest CHECK()
macros?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd really rather avoid use of macros like this here if possible.
If it's really still needed then perhaps just use a typdef and write a local get_thread_id()
function for all platforms?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sadly, on Linux thread id's are are not comparable directly. Have to convert to unsigned long long first to be able to compare. I will remove the macros and add functions instead.
include/cppcoro/detail/linux.hpp
Outdated
#include <sys/epoll.h> | ||
#include <unistd.h> | ||
|
||
typedef int DWORD; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd like to avoid adding new global-scope typedefs and #defines like this in public headers.
I don't want to introduce any issues or potential conflicts with other libraries that may be used in conjunction with cppcoro.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this is only required for timeout values inside cppcoro::io_service::timer_thread_state::run()
, so maybe its definition could be localised to that file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Fixed it.
@@ -0,0 +1,63 @@ | |||
#pragma once |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you change this to use #ifdef include guards to be consistent with other headers?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add a copyright/license header as per the existing source files?
Please attribute copyright to the appropriate entity.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will have to circle back on this. Have to speak with our team here to get the appropriate rights entity name.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
include/cppcoro/io_service.hpp
Outdated
@@ -76,8 +84,8 @@ namespace cppcoro | |||
template<typename REP, typename PERIOD> | |||
[[nodiscard]] | |||
timed_schedule_operation schedule_after( | |||
const std::chrono::duration<REP, PERIOD>& delay, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There are a number of unnecessary whitespace changes in these commits.
Have you tried running clang-format over the files?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will circle back on this. I am fixing my editor to have the same whitespace language as yours.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Alright. Things are now "tab"-bed according to clang-format-6.0.el from my emacs. That fixed it.
lib/linux.cpp
Outdated
uuid_t unique_name; | ||
const char* cppcoro_qname_prefix = "/cppcoro-"; | ||
|
||
if(NAME_MAX < UUID_STRING_SIZE + sizeof(cppcoro_qname_prefix) + 1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The sizeof(cppcoro_qname_prefix)
here will be sizeof(const char*)
and not sizeof("/cppcoro-")
.
I assume that was not the intent here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yikes. Meant strlen. Good catch!
lib/linux.cpp
Outdated
attr.mq_msgsize = sizeof(cppcoro::detail::linux::message); | ||
attr.mq_curmsgs = 0; | ||
|
||
m_mqdt = mq_open((const char*)m_qname, O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC, S_IRWXU, &attr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think the (const char*)m_qname
cast is necessary here.
There should be an implicit decay cast from char[NAME_MAX]
to const char*
possible here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yup!
The clang mainline has now been branched for clang-6 and mainline now uses clang-7 version.
@lewissbaker Cool. Thanks for the comments. Working on the easiest ones now. For the more complex ones, let's chat in the comments on how to proceed. |
@neo5167 How are you going with the changes? Any questions I can help you with? |
@lewissbaker Sorry. Progress has been a little slow. I am hoping to send another commit in the next several days. Plan is to fix the comments by end of this month. |
If the library is used as part of a bigger project some definitions can be provided via external build files.
Remove possible warnings with redefinitions of WIN32_LEAN_AND_MEAN.
Several tests are currently failing due to what seems to be compiler bugs. Ignore tests for now and revisit once MSVC 15.7 is released.
Update appveyor.yml to ignore x86 optimised failures
Correct file_write_operation's friend class
The AppVeyor 'Visual Studio 2017 Preview' image has now been updated with VS 2017.7 Preview 2
The msvcurt[d].lib is actually intended for C++/CLI usage and seems to no longer being bundled with the default VS install in more recent Visual Studio 2017 installs. Should fix lewissbaker#73
@lewissbaker take a look at the latest commit. Also, any ideas on how we should proceed with the whole ifdef thing? Is the main branch still ifdef based or have you already structured it more cleanly? |
@lewissbaker I was thinking of working on file support at a later time but push this PR through first. What do you think? If that is ok then I will work on rebasing with the main... let me know... |
Linux support for scheduler and timer with epoll, timerfd, eventfd, and other such sundry stuff. I am restructuring the code with less ifdefs. But I want to do that with guidance from you guys. Also, its a fork of an older version. I am working rebasing it to something more recent as well. In this PR, please comment on how to structure the code so that we can move platform dependent stuff into something more manageable.