summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Kling <awesomekling@gmail.com>2019-09-21 17:32:26 +0200
committerAndreas Kling <awesomekling@gmail.com>2019-09-21 17:32:26 +0200
commitbdf23a3d23042e558183932585d49c9513393a06 (patch)
treefea9a721c42a6bf2a6f0e65fad20c168332fa39b
parentff6ce422ddecb7dcb7fd9f67d3ea0cfdec7e74ea (diff)
downloadserenity-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.cpp2
-rw-r--r--Applications/ChanViewer/ThreadCatalogModel.cpp2
-rw-r--r--Libraries/LibCore/CHttpJob.cpp11
-rw-r--r--Libraries/LibCore/CHttpJob.h1
-rw-r--r--Libraries/LibCore/CNetworkJob.cpp6
-rw-r--r--Libraries/LibCore/CNetworkJob.h9
-rw-r--r--Libraries/LibCore/ObjectPtr.h2
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 };
};