From 5b54a8f0613183596c8a8259c659e4a942b1304d Mon Sep 17 00:00:00 2001 From: Henning Baldersheim Date: Tue, 1 Dec 2020 10:40:36 +0000 Subject: - Separate out the tail of the EventLoop into separate method to ease readability. - Also separate out timeout handling of old connections to separate method and unify on vespalib::time. --- fnet/src/tests/scheduling/schedule.cpp | 4 +-- fnet/src/tests/scheduling/sloweventloop.cpp | 10 +++---- fnet/src/vespa/fnet/config.cpp | 4 +-- fnet/src/vespa/fnet/config.h | 4 +-- fnet/src/vespa/fnet/iocomponent.cpp | 2 +- fnet/src/vespa/fnet/iocomponent.h | 4 +-- fnet/src/vespa/fnet/scheduler.cpp | 8 ++--- fnet/src/vespa/fnet/scheduler.h | 31 ++++++++++---------- fnet/src/vespa/fnet/transport_thread.cpp | 45 +++++++++++++++++------------ fnet/src/vespa/fnet/transport_thread.h | 7 +++-- 10 files changed, 62 insertions(+), 57 deletions(-) (limited to 'fnet/src') diff --git a/fnet/src/tests/scheduling/schedule.cpp b/fnet/src/tests/scheduling/schedule.cpp index fc5b5687c87..bf9f688b271 100644 --- a/fnet/src/tests/scheduling/schedule.cpp +++ b/fnet/src/tests/scheduling/schedule.cpp @@ -3,8 +3,8 @@ #include #include -using my_clock = FNET_Scheduler::clock; -using time_point = my_clock::time_point; +using my_clock = vespalib::steady_clock; +using time_point = vespalib::steady_time; using ms_double = std::chrono::duration; time_point _time; diff --git a/fnet/src/tests/scheduling/sloweventloop.cpp b/fnet/src/tests/scheduling/sloweventloop.cpp index a36afbc9d92..33070aa29e9 100644 --- a/fnet/src/tests/scheduling/sloweventloop.cpp +++ b/fnet/src/tests/scheduling/sloweventloop.cpp @@ -18,14 +18,14 @@ public: TEST("slow event loop") { - FNET_Scheduler::time_point t(std::chrono::milliseconds(0)); + vespalib::steady_time t(vespalib::duration::zero()); FNET_Scheduler scheduler(&t, &t); MyTask task(scheduler); MyTask task2(scheduler); scheduler.CheckTasks(); - t += std::chrono::milliseconds(10000); + t += 10s; task.Schedule(5.0); uint32_t cnt = 0; @@ -35,7 +35,7 @@ TEST("slow event loop") { break; } ++cnt; - t += std::chrono::milliseconds(1); + t += 1ms; } if (!EXPECT_TRUE(cnt > 4700 && cnt < 4800)) { @@ -43,7 +43,7 @@ TEST("slow event loop") { } scheduler.CheckTasks(); - t += std::chrono::milliseconds(10000); + t += 10s; task2.Schedule(5.0); uint32_t cnt2 = 0; @@ -53,7 +53,7 @@ TEST("slow event loop") { break; } ++cnt2; - t += std::chrono::milliseconds(10000); + t += 10s; } if (!EXPECT_TRUE(cnt2 > 15 && cnt2 < 25)) { diff --git a/fnet/src/vespa/fnet/config.cpp b/fnet/src/vespa/fnet/config.cpp index aee9ac6f2c1..856d0ab4c1c 100644 --- a/fnet/src/vespa/fnet/config.cpp +++ b/fnet/src/vespa/fnet/config.cpp @@ -3,8 +3,8 @@ #include "config.h" FNET_Config::FNET_Config() - : _events_before_wakeup(1), - _iocTimeOut(0), + : _iocTimeOut(vespalib::duration::zero()), + _events_before_wakeup(1), _maxInputBufferSize(0x10000), _maxOutputBufferSize(0x10000), _tcpNoDelay(true) diff --git a/fnet/src/vespa/fnet/config.h b/fnet/src/vespa/fnet/config.h index f512d7cde75..fd6f9f8557d 100644 --- a/fnet/src/vespa/fnet/config.h +++ b/fnet/src/vespa/fnet/config.h @@ -2,7 +2,7 @@ #pragma once -#include +#include /** * This class is used internally by the @ref FNET_Transport to keep @@ -11,8 +11,8 @@ class FNET_Config { public: + vespalib::duration _iocTimeOut; uint32_t _events_before_wakeup; - uint32_t _iocTimeOut; uint32_t _maxInputBufferSize; uint32_t _maxOutputBufferSize; bool _tcpNoDelay; diff --git a/fnet/src/vespa/fnet/iocomponent.cpp b/fnet/src/vespa/fnet/iocomponent.cpp index 7afab188b66..471156f53ea 100644 --- a/fnet/src/vespa/fnet/iocomponent.cpp +++ b/fnet/src/vespa/fnet/iocomponent.cpp @@ -16,7 +16,7 @@ FNET_IOComponent::FNET_IOComponent(FNET_TransportThread *owner, _ioc_selector(nullptr), _ioc_spec(nullptr), _flags(shouldTimeOut), - _ioc_timestamp(clock::now()), + _ioc_timestamp(vespalib::steady_clock::now()), _ioc_lock(), _ioc_cond(), _ioc_refcnt(1) diff --git a/fnet/src/vespa/fnet/iocomponent.h b/fnet/src/vespa/fnet/iocomponent.h index 5fd5079a8af..ee228e0126d 100644 --- a/fnet/src/vespa/fnet/iocomponent.h +++ b/fnet/src/vespa/fnet/iocomponent.h @@ -25,8 +25,6 @@ class FNET_IOComponent FNET_IOComponent &operator=(const FNET_IOComponent &); using Selector = vespalib::Selector; - using clock = FNET_Scheduler::clock; - using time_point = clock::time_point; struct Flags { Flags(bool shouldTimeout) : @@ -50,7 +48,7 @@ protected: Selector *_ioc_selector; // attached event selector char *_ioc_spec; // connect/listen spec Flags _flags; // Compressed representation of boolean flags; - time_point _ioc_timestamp; // last I/O activity + vespalib::steady_time _ioc_timestamp; // last I/O activity std::mutex _ioc_lock; // synchronization std::condition_variable _ioc_cond; // synchronization uint32_t _ioc_refcnt; // reference counter diff --git a/fnet/src/vespa/fnet/scheduler.cpp b/fnet/src/vespa/fnet/scheduler.cpp index a4d504db752..f54d3d6a9bb 100644 --- a/fnet/src/vespa/fnet/scheduler.cpp +++ b/fnet/src/vespa/fnet/scheduler.cpp @@ -9,8 +9,8 @@ LOG_SETUP(".fnet.scheduler"); -FNET_Scheduler::FNET_Scheduler(time_point *sampler, - time_point *now) +FNET_Scheduler::FNET_Scheduler(vespalib::steady_time *sampler, + vespalib::steady_time *now) : _cond(), _next(), _now(), @@ -29,7 +29,7 @@ FNET_Scheduler::FNET_Scheduler(time_point *sampler, if (now != nullptr) { _next = *now; } else { - _next = clock::now(); + _next = vespalib::steady_clock::now(); } _next += tick_ms; } @@ -146,7 +146,7 @@ FNET_Scheduler::CheckTasks() if (_sampler != nullptr) { _now = *_sampler; } else { - _now = clock::now(); + _now = vespalib::steady_clock::now(); } // assume timely value propagation diff --git a/fnet/src/vespa/fnet/scheduler.h b/fnet/src/vespa/fnet/scheduler.h index 81ff8977f89..98a9442799e 100644 --- a/fnet/src/vespa/fnet/scheduler.h +++ b/fnet/src/vespa/fnet/scheduler.h @@ -2,9 +2,9 @@ #pragma once +#include #include #include -#include class FNET_Task; @@ -19,9 +19,8 @@ class FNET_Task; class FNET_Scheduler { public: - using clock = std::chrono::steady_clock; - using time_point = clock::time_point; - static constexpr auto tick_ms = std::chrono::milliseconds(10); + using clock = vespalib::steady_clock; + static constexpr auto tick_ms = 10ms; enum scheduler_constants { NUM_SLOTS = 4096, @@ -32,16 +31,16 @@ public: private: std::mutex _lock; std::condition_variable _cond; - FNET_Task *_slots[NUM_SLOTS + 1]; - time_point _next; - time_point _now; - time_point *_sampler; - uint32_t _currIter; - uint32_t _currSlot; - FNET_Task *_currPt; - FNET_Task *_tailPt; - FNET_Task *_performing; - bool _waitTask; + FNET_Task *_slots[NUM_SLOTS + 1]; + vespalib::steady_time _next; + vespalib::steady_time _now; + vespalib::steady_time *_sampler; + uint32_t _currIter; + uint32_t _currSlot; + FNET_Task *_currPt; + FNET_Task *_tailPt; + FNET_Task *_performing; + bool _waitTask; FNET_Scheduler(const FNET_Scheduler &); FNET_Scheduler &operator=(const FNET_Scheduler &); @@ -73,8 +72,8 @@ public: * @param now if given, indicates the current time. This value is * used by the constructor to init internal variables. **/ - FNET_Scheduler(time_point *sampler = nullptr, - time_point *now = nullptr); + FNET_Scheduler(vespalib::steady_time *sampler = nullptr, + vespalib::steady_time *now = nullptr); virtual ~FNET_Scheduler(); diff --git a/fnet/src/vespa/fnet/transport_thread.cpp b/fnet/src/vespa/fnet/transport_thread.cpp index 6b66b1ebe4b..44292dfde42 100644 --- a/fnet/src/vespa/fnet/transport_thread.cpp +++ b/fnet/src/vespa/fnet/transport_thread.cpp @@ -19,6 +19,7 @@ using vespalib::ServerSocket; using vespalib::SocketHandle; using vespalib::SocketSpec; using OptimizeFor = vespalib::Executor::OptimizeFor; +using vespalib::steady_clock; namespace { @@ -207,7 +208,7 @@ extern "C" { FNET_TransportThread::FNET_TransportThread(FNET_Transport &owner_in) : _owner(owner_in), - _now(clock::now()), + _now(steady_clock ::now()), _scheduler(&_now), _componentsHead(nullptr), _timeOutHead(nullptr), @@ -397,7 +398,7 @@ FNET_TransportThread::InitEventLoop() LOG(error, "Transport: InitEventLoop: object already active!"); return false; } - _now = clock::now(); + _now = steady_clock::now(); return true; } @@ -471,17 +472,15 @@ FNET_TransportThread::handle_event(FNET_IOComponent &ctx, bool read, bool write) bool -FNET_TransportThread::EventLoopIteration() -{ - FNET_IOComponent *component = nullptr; - int msTimeout = FNET_Scheduler::tick_ms.count(); +FNET_TransportThread::EventLoopIteration() { if (!IsShutDown()) { + int msTimeout = FNET_Scheduler::tick_ms.count(); // obtain I/O events _selector.poll(msTimeout); // sample current time (performed once per event loop iteration) - _now = clock::now(); + _now = steady_clock::now(); handle_wakeup_events(); @@ -489,16 +488,8 @@ FNET_TransportThread::EventLoopIteration() _selector.dispatch(*this); // handle IOC time-outs - if (getConfig()._iocTimeOut > 0) { - time_point oldest = (_now - std::chrono::milliseconds(getConfig()._iocTimeOut)); - while (_timeOutHead != nullptr && - oldest > _timeOutHead->_ioc_timestamp) { - - component = _timeOutHead; - RemoveComponent(component); - component->Close(); - AddDeleteComponent(component); - } + if (getConfig()._iocTimeOut > vespalib::duration::zero()) { + checkTimedoutComponents(getConfig()._iocTimeOut); } // perform pending tasks @@ -513,6 +504,23 @@ FNET_TransportThread::EventLoopIteration() if (_finished) return false; + endEventLoop(); + return false; +} + +void +FNET_TransportThread::checkTimedoutComponents(vespalib::duration timeout) { + vespalib::steady_time oldest = (_now - timeout); + while (_timeOutHead != nullptr && oldest > _timeOutHead->_ioc_timestamp) { + FNET_IOComponent *component = _timeOutHead; + RemoveComponent(component); + component->Close(); + AddDeleteComponent(component); + } +} + +void +FNET_TransportThread::endEventLoop() { // flush event queue { std::lock_guard guard(_lock); @@ -531,7 +539,7 @@ FNET_TransportThread::EventLoopIteration() } // close and remove all I/O Components - component = _componentsHead; + FNET_IOComponent *component = _componentsHead; while (component != nullptr) { assert(component == _componentsHead); FNET_IOComponent *tmp = component; @@ -557,7 +565,6 @@ FNET_TransportThread::EventLoopIteration() LOG(spam, "Transport: event loop finished."); - return false; } diff --git a/fnet/src/vespa/fnet/transport_thread.h b/fnet/src/vespa/fnet/transport_thread.h index c649a677cb4..83332fb4cc8 100644 --- a/fnet/src/vespa/fnet/transport_thread.h +++ b/fnet/src/vespa/fnet/transport_thread.h @@ -30,12 +30,10 @@ class FNET_TransportThread : public FastOS_Runnable public: using Selector = vespalib::Selector; - using clock = FNET_Scheduler::clock; - using time_point = clock::time_point; private: FNET_Transport &_owner; // owning transport layer - time_point _now; // current time sampler + vespalib::steady_time _now; // current time sampler FNET_Scheduler _scheduler; // transport thread scheduler FNET_IOComponent *_componentsHead; // I/O component list head FNET_IOComponent *_timeOutHead; // first IOC in list to time out @@ -156,6 +154,9 @@ private: **/ bool InitEventLoop(); + void endEventLoop(); + void checkTimedoutComponents(vespalib::duration timeout); + /** * Perform a single transport thread event loop iteration. This * method is called by the FRT_Transport::Run method. If you want to -- cgit v1.2.3