diff --git a/CMakeLists.txt b/CMakeLists.txt index 2ce0082..df51d0d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 11) set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_VISIBILITY_PRESET hidden) + set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # For JetBrains IDE @@ -49,11 +52,12 @@ if (MSVC) # MSVC: add_definitions(-DWIN32_LEAN_AND_MEAN -D_WIN32_WINNT=0x0A00 -DNOMINMAX) add_compile_options( - /W4 # I think this means 'turn on lots of warnings' - /wd4068 # ignore unknown pragma - /wd4100 # ignore unused fn parameters - /wd4244 # ignore implicit sign conversion - /wd4267 # ignore implicit integer truncation + "/wd4068;/wd4100;/wd4244;/wd4267" + # /W4 # I think this means 'turn on lots of warnings' + # /wd4068 # ignore unknown pragma + # /wd4100 # ignore unused fn parameters + # /wd4244 # ignore implicit sign conversion + # /wd4267 # ignore implicit integer truncation ) else() # Clang & GCC: @@ -76,7 +80,8 @@ else() add_compile_options( -Wno-gnu-zero-variadic-macro-arguments -Wno-gnu-conditional-omitted-operand # Allow `x ?: y` - -Wno-gnu-statement-expression-from-macro-expansion # Allow `({...})` + -Wno-gnu-statement-expression # Allow `({...})` + -Wno-gnu-statement-expression-from-macro-expansion ) endif() endif() diff --git a/include/Awaitable.hh b/include/Awaitable.hh index 135f530..1bdbc1f 100644 --- a/include/Awaitable.hh +++ b/include/Awaitable.hh @@ -19,6 +19,8 @@ #pragma once #include "Result.hh" +#include + namespace crouton { /** Pure-virtual interface declaring the coroutine methods needed to support `co_await` diff --git a/include/Base.hh b/include/Base.hh index 5f5eee9..fb58fce 100644 --- a/include/Base.hh +++ b/include/Base.hh @@ -42,6 +42,23 @@ #endif +#ifndef __has_attribute +#define __has_attribute(x) 0 +#endif + +#if __has_attribute(__unused__) +#define __unused __attribute__((__unused__)) +#else +#define __unused +#endif + +#if __has_attribute(__pure__) +#define pure __attribute__((__pure__)) +#else +#define pure +#endif + + // Synonyms for coroutine primitives. Optional, but they're more visible in the code. #define AWAIT co_await #define YIELD co_yield diff --git a/include/Error.hh b/include/Error.hh index 1b9cd3b..fb52dff 100644 --- a/include/Error.hh +++ b/include/Error.hh @@ -21,7 +21,7 @@ #include #include -#include +#include #include #include @@ -51,7 +51,7 @@ namespace crouton { template concept ErrorDomain = requires { std::is_enum_v; - std::same_as, errorcode_t>; + requires std::same_as, errorcode_t>; {ErrorDomainInfo::name} -> std::convertible_to; {ErrorDomainInfo::description} -> std::convertible_to; }; diff --git a/include/EventLoop.hh b/include/EventLoop.hh index dacdd17..f337f30 100644 --- a/include/EventLoop.hh +++ b/include/EventLoop.hh @@ -20,6 +20,7 @@ #include "Future.hh" #include +#include struct uv_timer_s; diff --git a/include/Future.hh b/include/Future.hh index 54e3b7f..6e783ff 100644 --- a/include/Future.hh +++ b/include/Future.hh @@ -61,7 +61,7 @@ namespace crouton { template class Future : public Coroutine>, public ISelectable { public: - using nonvoidT = std::conditional, std::byte, T>::type; + using nonvoidT = typename std::conditional, std::byte, T>::type; /// Creates a Future from a FutureProvider. explicit Future(FutureProvider state) :_state(std::move(state)) {assert(_state);} @@ -260,7 +260,7 @@ namespace crouton { public: using super = CoroutineImpl, true>; using handle_type = typename super::handle_type; - using nonvoidT = std::conditional, std::byte, T>::type; + using nonvoidT = typename std::conditional, std::byte, T>::type; FutureImpl() = default; diff --git a/include/LinkedList.hh b/include/LinkedList.hh index ca7b268..f33b0ab 100644 --- a/include/LinkedList.hh +++ b/include/LinkedList.hh @@ -111,6 +111,8 @@ namespace crouton::util { protected: Link* _begin() {return _head._next;} Link* _end() {return &_head;} + Link const* _begin() const {return _head._next;} + Link const* _end() const {return &_head;} template static LINK& downcast(Link& link) {return static_cast(link);} diff --git a/include/PubSub.hh b/include/PubSub.hh index 3528d55..d35be65 100644 --- a/include/PubSub.hh +++ b/include/PubSub.hh @@ -12,6 +12,10 @@ #include "Select.hh" #include "Task.hh" +#include +#include +#include + namespace crouton::ps { /** Type-erasing wrapper around any Series implementation. */ diff --git a/include/Queue.hh b/include/Queue.hh index 90f13c9..9590569 100644 --- a/include/Queue.hh +++ b/include/Queue.hh @@ -87,8 +87,8 @@ namespace crouton { size_t size() const {return _queue.size();} Error error() const {return empty() ? _closeError : noerror;} - using iterator = std::deque::iterator; - using const_iterator = std::deque::const_iterator; + using iterator = typename std::deque::iterator; + using const_iterator = typename std::deque::const_iterator; iterator begin() {return _queue.begin();} iterator end() {return _queue.end();} @@ -120,7 +120,7 @@ namespace crouton { } /// Adds an item at the position of the iterator, i.e. before whatever's at the iterator. - virtual bool pushBefore(std::deque::iterator i, T item) { + virtual bool pushBefore(typename std::deque::iterator i, T item) { if (_state != Open) return false; _queue.emplace(i, std::move(item)); @@ -245,7 +245,7 @@ namespace crouton { this->closeWhenEmpty(); break; } - if (!(YIELD 0)) + if (bool ok = YIELD 0; !ok) break; } } @@ -266,7 +266,7 @@ namespace crouton { return !full() && super::push(std::move(t)); } - [[nodiscard]] bool pushBefore(std::deque::iterator i, T item) override { + [[nodiscard]] bool pushBefore(typename std::deque::iterator i, T item) override { return !full() && super::pushBefore(i, std::move(item)); } diff --git a/include/Result.hh b/include/Result.hh index c26d994..048a8a0 100644 --- a/include/Result.hh +++ b/include/Result.hh @@ -133,6 +133,7 @@ namespace crouton { +#if 0 /// Syntactic sugar to handle a `Result`, similar to Swift's `try`. /// - If R has a value, evaluates to its value. /// - If R has an error, `co_return`s the error from the current coroutine. @@ -148,4 +149,5 @@ namespace crouton { /// - If the future returns a value, evaluates to that value. /// - If the future returns an error, `co_return`s the error. #define TRY_AWAIT(F) UNWRAP(AWAIT NoThrow(F)) +#endif } diff --git a/src/io/FileStream.cc b/src/io/FileStream.cc index 0f1da1d..b4f0c0c 100644 --- a/src/io/FileStream.cc +++ b/src/io/FileStream.cc @@ -108,9 +108,10 @@ namespace crouton::io { _readBuf = make_unique(); assert(_readBuf->empty()); MutableBytes buf(_readBuf->data, Buffer::kCapacity); - size_t n = TRY_AWAIT(_preadv(&buf, 1, -1)); - - _readBuf->size = uint32_t(n); + Result n = AWAIT _preadv(&buf, 1, -1); + if (auto err = n.error()) + RETURN err; + _readBuf->size = uint32_t(n.value()); _readBuf->used = 0; RETURN _readBuf->bytes(); } diff --git a/src/io/blip/BLIPConnection.hh b/src/io/blip/BLIPConnection.hh index 055e8c9..5191f66 100644 --- a/src/io/blip/BLIPConnection.hh +++ b/src/io/blip/BLIPConnection.hh @@ -23,6 +23,10 @@ #include "Message.hh" #include "Task.hh" +#include +#include +#include + namespace crouton::io::blip { class MessageBuilder; diff --git a/src/io/blip/BLIPIO.hh b/src/io/blip/BLIPIO.hh index 4ecd920..a2d53b6 100644 --- a/src/io/blip/BLIPIO.hh +++ b/src/io/blip/BLIPIO.hh @@ -19,7 +19,9 @@ #include "Message.hh" #include "MessageOut.hh" #include "Queue.hh" + #include +#include #include namespace crouton::io::blip { diff --git a/src/io/blip/Message.cc b/src/io/blip/Message.cc index 10dfaad..1391e74 100644 --- a/src/io/blip/Message.cc +++ b/src/io/blip/Message.cc @@ -214,11 +214,11 @@ namespace crouton::io::blip { _unackedBytes += frameSize; if (_unackedBytes >= kIncomingAckThreshold) { // Send an ACK after enough data has been received of this message: - MessageType msgType = isResponse() ? kAckResponseType : kAckRequestType; + auto msgType = FrameFlags(isResponse() ? kAckResponseType : kAckRequestType); char buf[10]; string payload(buf, putUVarint(_rawBytesReceived, buf)); _connection->send(make_shared(_connection, - (FrameFlags)(msgType|kUrgent|kNoReply), + FrameFlags(msgType|kUrgent|kNoReply), payload, _number)); _unackedBytes = 0; } diff --git a/src/io/blip/MessageBuilder.cc b/src/io/blip/MessageBuilder.cc index aba0c65..f557c88 100644 --- a/src/io/blip/MessageBuilder.cc +++ b/src/io/blip/MessageBuilder.cc @@ -57,7 +57,7 @@ namespace crouton::io::blip { FrameFlags MessageBuilder::flags() const { - int flags = type & kTypeMask; + int flags = FrameFlags(type) & kTypeMask; if (urgent) flags |= kUrgent; if (compressed) flags |= kCompressed; if (noreply) flags |= kNoReply; diff --git a/src/io/blip/MessageOut.cc b/src/io/blip/MessageOut.cc index d1ddf7a..ac44724 100644 --- a/src/io/blip/MessageOut.cc +++ b/src/io/blip/MessageOut.cc @@ -99,7 +99,7 @@ namespace crouton::io::blip { // Note: The MessageIn's flags will be updated when the 1st frame of the response arrives; // the type might become kErrorType, and kUrgent or kCompressed might be set. return new MessageIn(_connection, - (FrameFlags)kResponseType, + FrameFlags(kResponseType), _number, _uncompressedBytesSent, std::move(_onResponse)); diff --git a/src/support/StringUtils.hh b/src/support/StringUtils.hh index 85fd6e2..b960e2f 100644 --- a/src/support/StringUtils.hh +++ b/src/support/StringUtils.hh @@ -18,6 +18,8 @@ #pragma once #include "Base.hh" + +#include #include namespace crouton { diff --git a/tests/test_generator.cc b/tests/test_generator.cc index 1812a49..311280b 100644 --- a/tests/test_generator.cc +++ b/tests/test_generator.cc @@ -182,7 +182,7 @@ TEST_CASE("Select Future and Generator", "[generator]") { int64_t expectedCount = 1; bool done = false; while (!done) { - switch (int which = AWAIT select) { + switch (AWAIT select) { case 0: { Result r = AWAIT count; cerr << r << ", ";