Don't throw an exception every 10ms in the RPC worker

Cuts the time taken to run the react native tests on my machine from 198
seconds to 41 seconds. Probably has a similar impact on the react native
debugger performance.
This commit is contained in:
Thomas Goyne 2017-08-31 15:29:57 -07:00
parent 806146b07c
commit 360a5fbd07
2 changed files with 26 additions and 41 deletions

View File

@ -20,37 +20,26 @@
#include <condition_variable>
#include <deque>
#include <exception>
#include <mutex>
#include <realm/util/optional.hpp>
namespace realm {
class ConcurrentDequeTimeout : public std::exception {
public:
ConcurrentDequeTimeout() : std::exception() {}
};
template <typename T>
class ConcurrentDeque {
public:
T pop_front(size_t timeout = 0) {
public:
T pop_back() {
std::unique_lock<std::mutex> lock(m_mutex);
while (m_deque.empty()) {
wait(lock, timeout);
}
T item = std::move(m_deque.front());
m_deque.pop_front();
return item;
m_condition.wait(lock, [this] { return !m_deque.empty(); });
return do_pop_back();
}
T pop_back(size_t timeout = 0) {
util::Optional<T> try_pop_back(size_t timeout) {
std::unique_lock<std::mutex> lock(m_mutex);
while (m_deque.empty()) {
wait(lock, timeout);
}
T item = std::move(m_deque.back());
m_deque.pop_back();
return item;
m_condition.wait_for(lock, std::chrono::milliseconds(timeout),
[this] { return !m_deque.empty(); });
return m_deque.empty() ? util::none : util::make_optional(do_pop_back());
}
void push_front(T&& item) {
@ -72,19 +61,16 @@ class ConcurrentDeque {
return m_deque.empty();
}
void wait(std::unique_lock<std::mutex> &lock, size_t timeout = 0) {
if (!timeout) {
m_condition.wait(lock);
}
else if (m_condition.wait_for(lock, std::chrono::milliseconds(timeout)) == std::cv_status::timeout) {
throw ConcurrentDequeTimeout();
}
}
private:
private:
std::condition_variable m_condition;
std::mutex m_mutex;
std::deque<T> m_deque;
T do_pop_back() {
T item = std::move(m_deque.back());
m_deque.pop_back();
return item;
}
};
} // realm

View File

@ -77,17 +77,16 @@ json RPCWorker::pop_task_result() {
}
void RPCWorker::try_run_task() {
try {
// Use a 10 millisecond timeout to keep this thread unblocked.
auto task = m_tasks.pop_back(10);
task();
// Use a 10 millisecond timeout to keep this thread unblocked.
auto task = m_tasks.try_pop_back(10);
if (!task) {
return;
}
// Since this can be called recursively, it must be pushed to the front of the queue *after* running the task.
m_futures.push_front(task.get_future());
}
catch (ConcurrentDequeTimeout &) {
// We tried.
}
(*task)();
// Since this can be called recursively, it must be pushed to the front of the queue *after* running the task.
m_futures.push_front(task->get_future());
}
void RPCWorker::stop() {