diff options
author | Andreas Kling <awesomekling@gmail.com> | 2019-09-21 17:32:26 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2019-09-21 17:32:26 +0200 |
commit | bdf23a3d23042e558183932585d49c9513393a06 (patch) | |
tree | fea9a721c42a6bf2a6f0e65fad20c168332fa39b | |
parent | ff6ce422ddecb7dcb7fd9f67d3ea0cfdec7e74ea (diff) | |
download | serenity-bdf23a3d23042e558183932585d49c9513393a06.zip |
LibCore: Make it possible to cancel pending CNetworkJobs
Subclasses of CNetworkJob handle this by overriding shutdown().
This patch implements it for CHttpJob by simply tearing down the
underlying socket.
We also automatically call shutdown() after the job finishes,
regardless of success or failure. :^)
-rw-r--r-- | Applications/ChanViewer/BoardListModel.cpp | 2 | ||||
-rw-r--r-- | Applications/ChanViewer/ThreadCatalogModel.cpp | 2 | ||||
-rw-r--r-- | Libraries/LibCore/CHttpJob.cpp | 11 | ||||
-rw-r--r-- | Libraries/LibCore/CHttpJob.h | 1 | ||||
-rw-r--r-- | Libraries/LibCore/CNetworkJob.cpp | 6 | ||||
-rw-r--r-- | Libraries/LibCore/CNetworkJob.h | 9 | ||||
-rw-r--r-- | Libraries/LibCore/ObjectPtr.h | 2 |
7 files changed, 31 insertions, 2 deletions
diff --git a/Applications/ChanViewer/BoardListModel.cpp b/Applications/ChanViewer/BoardListModel.cpp index 8f8b7dfbdc..425fdb48a0 100644 --- a/Applications/ChanViewer/BoardListModel.cpp +++ b/Applications/ChanViewer/BoardListModel.cpp @@ -21,6 +21,8 @@ void BoardListModel::update() CHttpRequest request; request.set_url("http://a.4cdn.org/boards.json"); + if (m_pending_job) + m_pending_job->cancel(); m_pending_job = request.schedule(); m_pending_job->on_finish = [this](bool success) { diff --git a/Applications/ChanViewer/ThreadCatalogModel.cpp b/Applications/ChanViewer/ThreadCatalogModel.cpp index 789b5d5f4d..4c18ee767b 100644 --- a/Applications/ChanViewer/ThreadCatalogModel.cpp +++ b/Applications/ChanViewer/ThreadCatalogModel.cpp @@ -29,6 +29,8 @@ void ThreadCatalogModel::update() CHttpRequest request; request.set_url(String::format("http://a.4cdn.org/%s/catalog.json", m_board.characters())); + if (m_pending_job) + m_pending_job->cancel(); m_pending_job = request.schedule(); if (on_load_started) diff --git a/Libraries/LibCore/CHttpJob.cpp b/Libraries/LibCore/CHttpJob.cpp index 472aae01d9..6ddde0475a 100644 --- a/Libraries/LibCore/CHttpJob.cpp +++ b/Libraries/LibCore/CHttpJob.cpp @@ -26,6 +26,8 @@ void CHttpJob::on_socket_connected() return deferred_invoke([this](auto&) { did_fail(CNetworkJob::Error::TransmissionFailed); }); m_socket->on_ready_to_read = [&] { + if (is_cancelled()) + return; if (m_state == State::InStatus) { if (!m_socket->can_read_line()) return; @@ -125,3 +127,12 @@ void CHttpJob::start() if (!success) return did_fail(CNetworkJob::Error::ConnectionFailed); } + +void CHttpJob::shutdown() +{ + if (!m_socket) + return; + m_socket->on_ready_to_read = nullptr; + m_socket->on_connected = nullptr; + m_socket = nullptr; +} diff --git a/Libraries/LibCore/CHttpJob.h b/Libraries/LibCore/CHttpJob.h index d0aa714920..3e3b758977 100644 --- a/Libraries/LibCore/CHttpJob.h +++ b/Libraries/LibCore/CHttpJob.h @@ -13,6 +13,7 @@ public: virtual ~CHttpJob() override; virtual void start() override; + virtual void shutdown() override; private: void on_socket_connected(); diff --git a/Libraries/LibCore/CNetworkJob.cpp b/Libraries/LibCore/CNetworkJob.cpp index 6522b355a7..4334cb67a7 100644 --- a/Libraries/LibCore/CNetworkJob.cpp +++ b/Libraries/LibCore/CNetworkJob.cpp @@ -16,7 +16,7 @@ void CNetworkJob::did_finish(NonnullRefPtr<CNetworkResponse>&& response) dbg() << *this << " job did_finish!"; ASSERT(on_finish); on_finish(true); - delete_later(); + shutdown(); } void CNetworkJob::did_fail(Error error) @@ -25,7 +25,7 @@ void CNetworkJob::did_fail(Error error) dbgprintf("%s{%p} job did_fail! error: %u (%s)\n", class_name(), this, (unsigned)error, to_string(error)); ASSERT(on_finish); on_finish(false); - delete_later(); + shutdown(); } const char* to_string(CNetworkJob::Error error) @@ -37,6 +37,8 @@ const char* to_string(CNetworkJob::Error error) return "ConnectionFailed"; case CNetworkJob::Error::TransmissionFailed: return "TransmissionFailed"; + case CNetworkJob::Error::Cancelled: + return "Cancelled"; default: return "(Unknown error)"; } diff --git a/Libraries/LibCore/CNetworkJob.h b/Libraries/LibCore/CNetworkJob.h index a0638dd46d..2d2bb02778 100644 --- a/Libraries/LibCore/CNetworkJob.h +++ b/Libraries/LibCore/CNetworkJob.h @@ -13,17 +13,26 @@ public: ConnectionFailed, TransmissionFailed, ProtocolFailed, + Cancelled, }; virtual ~CNetworkJob() override; Function<void(bool success)> on_finish; + bool is_cancelled() const { return m_error == Error::Cancelled; } bool has_error() const { return m_error != Error::None; } Error error() const { return m_error; } CNetworkResponse* response() { return m_response.ptr(); } const CNetworkResponse* response() const { return m_response.ptr(); } virtual void start() = 0; + virtual void shutdown() = 0; + + void cancel() + { + shutdown(); + m_error = Error::Cancelled; + } protected: CNetworkJob(); diff --git a/Libraries/LibCore/ObjectPtr.h b/Libraries/LibCore/ObjectPtr.h index a34c8f8224..98a4cd2bf0 100644 --- a/Libraries/LibCore/ObjectPtr.h +++ b/Libraries/LibCore/ObjectPtr.h @@ -76,6 +76,8 @@ public: T* ptr() const { return m_ptr; } T* leak_ptr() { return exchange(m_ptr, nullptr); } + operator bool() const { return !!m_ptr; } + private: T* m_ptr { nullptr }; }; |