Using background thread for calling m_extrapolatedLocationUpdate.

This commit is contained in:
Vladimir Byko-Ianko 2018-05-22 16:57:47 +03:00 committed by mpimenov
parent 031471b0c6
commit 9438c73a3a
5 changed files with 67 additions and 94 deletions

View file

@ -70,52 +70,17 @@ location::GpsInfo LinearExtrapolation(location::GpsInfo const & gpsInfo1,
return result;
}
// Extrapolator::Routine ---------------------------------------------------------------------------
Extrapolator::Routine::Routine(ExtrapolatedLocationUpdate const & update)
// Extrapolator ------------------------------------------------------------------------------------
Extrapolator::Extrapolator(ExtrapolatedLocationUpdateFn const & update)
: m_extrapolatedLocationUpdate(update)
{
}
void Extrapolator::Routine::Do()
{
while (!IsCancelled())
GetPlatform().RunTask(Platform::Thread::Background, [this]
{
{
GetPlatform().RunTask(Platform::Thread::Gui, [this]() {
lock_guard<mutex> guard(m_mutex);
uint64_t const extrapolationTimeMs = kExtrapolationPeriodMs * m_extrapolationCounter;
if (extrapolationTimeMs >= kMaxExtrapolationTimeMs)
return;
if (DoesExtrapolationWork(extrapolationTimeMs))
{
location::GpsInfo gpsInfo =
LinearExtrapolation(m_beforeLastGpsInfo, m_lastGpsInfo, extrapolationTimeMs);
m_extrapolatedLocationUpdate(gpsInfo);
}
else
{
if (m_lastGpsInfo.m_source != location::EUndefined)
{
location::GpsInfo gpsInfo = m_lastGpsInfo;
m_extrapolatedLocationUpdate(gpsInfo);
}
}
});
lock_guard<mutex> guard(m_mutex);
if (m_extrapolationCounter != m_extrapolationCounterUndefined)
++m_extrapolationCounter;
}
// @TODO(bykoinako) Method m_extrapolatedLocationUpdate() is run on gui thread every
// |kExtrapolationPeriodMs| milliseconds. But after changing GPS position
// (that means after a call of method Routine::SetGpsInfo())
// m_extrapolatedLocationUpdate() should be run immediately on gui thread.
this_thread::sleep_for(std::chrono::milliseconds(kExtrapolationPeriodMs));
}
ExtrapolatedLocationUpdate();
});
}
void Extrapolator::Routine::SetGpsInfo(location::GpsInfo const & gpsInfo)
void Extrapolator::OnLocationUpdate(location::GpsInfo const & gpsInfo)
{
lock_guard<mutex> guard(m_mutex);
m_beforeLastGpsInfo = m_lastGpsInfo;
@ -123,15 +88,55 @@ void Extrapolator::Routine::SetGpsInfo(location::GpsInfo const & gpsInfo)
m_extrapolationCounter = 0;
}
bool Extrapolator::Routine::DoesExtrapolationWork(uint64_t extrapolationTimeMs) const
void Extrapolator::ExtrapolatedLocationUpdate()
{
location::GpsInfo gpsInfo;
do
{
lock_guard<mutex> guard(m_mutex);
uint64_t const extrapolationTimeMs = kExtrapolationPeriodMs * m_extrapolationCounter;
if (extrapolationTimeMs >= kMaxExtrapolationTimeMs || !m_lastGpsInfo.IsValid())
break;
if (DoesExtrapolationWork(extrapolationTimeMs))
{
gpsInfo = LinearExtrapolation(m_beforeLastGpsInfo, m_lastGpsInfo, extrapolationTimeMs);
break;
}
if (m_lastGpsInfo.IsValid())
gpsInfo = m_lastGpsInfo;
} while (false);
if (gpsInfo.IsValid())
{
GetPlatform().RunTask(Platform::Thread::Gui, [this, gpsInfo]() {
m_extrapolatedLocationUpdate(gpsInfo);
});
}
{
lock_guard<mutex> guard(m_mutex);
if (m_extrapolationCounter != m_extrapolationCounterUndefined)
++m_extrapolationCounter;
}
// Call ExtrapolatedLocationUpdate() every |kExtrapolationPeriodMs| milliseconds.
auto constexpr kSExtrapolationPeriod = std::chrono::milliseconds(kExtrapolationPeriodMs);
GetPlatform().RunDelayedTask(Platform::Thread::Background, kSExtrapolationPeriod, [this]
{
ExtrapolatedLocationUpdate();
});
}
bool Extrapolator::DoesExtrapolationWork(uint64_t extrapolationTimeMs) const
{
// Note. It's possible that m_beforeLastGpsInfo.m_timestamp >= m_lastGpsInfo.m_timestamp.
// It may happen in rare cases because GpsInfo::m_timestamp is not monotonic generally.
// Please see comment in declaration of class GpsInfo for details.
if (m_extrapolationCounter == m_extrapolationCounterUndefined ||
m_lastGpsInfo.m_source == location::EUndefined ||
m_beforeLastGpsInfo.m_source == location::EUndefined ||
!m_lastGpsInfo.IsValid() || !m_beforeLastGpsInfo.IsValid() ||
m_beforeLastGpsInfo.m_timestamp >= m_lastGpsInfo.m_timestamp)
{
return false;
@ -146,18 +151,4 @@ bool Extrapolator::Routine::DoesExtrapolationWork(uint64_t extrapolationTimeMs)
return distM / timeS < kMaxExtrapolationSpeedMPS;
// @TODO(bykoianko) Switching off extrapolation based on acceleration should be implemented.
}
// Extrapolator ------------------------------------------------------------------------------------
Extrapolator::Extrapolator(ExtrapolatedLocationUpdate const & update)
: m_extrapolatedLocationThread()
{
m_extrapolatedLocationThread.Create(make_unique<Routine>(update));
}
void Extrapolator::OnLocationUpdate(location::GpsInfo const & info)
{
auto * routine = m_extrapolatedLocationThread.GetRoutineAs<Routine>();
CHECK(routine, ());
routine->SetGpsInfo(info);
}
} // namespace extrapolation

View file

@ -2,13 +2,10 @@
#include "platform/location.hpp"
#include "base/thread.hpp"
#include <cstdint>
#include <functional>
#include <limits>
#include <mutex>
#include <thread>
namespace extrapolation
{
@ -21,41 +18,26 @@ location::GpsInfo LinearExtrapolation(location::GpsInfo const & gpsInfo1,
class Extrapolator
{
public:
using ExtrapolatedLocationUpdate = std::function<void(location::GpsInfo &)>;
using ExtrapolatedLocationUpdateFn = std::function<void(location::GpsInfo const &)>;
static uint64_t constexpr m_extrapolationCounterUndefined = std::numeric_limits<uint64_t>::max();
/// \param update is a function which is called with params according to extrapolated position.
/// |update| will be called on gui thread.
explicit Extrapolator(ExtrapolatedLocationUpdate const & update);
void OnLocationUpdate(location::GpsInfo const & info);
explicit Extrapolator(ExtrapolatedLocationUpdateFn const & update);
void OnLocationUpdate(location::GpsInfo const & gpsInfo);
// @TODO(bykoianko) Gyroscope information should be taken into account as well for calculation
// extrapolated position.
void Cancel() { m_extrapolatedLocationThread.Cancel(); }
void ExtrapolatedLocationUpdate();
private:
class Routine : public threads::IRoutine
{
public:
explicit Routine(ExtrapolatedLocationUpdate const & update);
bool DoesExtrapolationWork(uint64_t extrapolationTimeMs) const;
// threads::IRoutine overrides:
void Do() override;
void SetGpsInfo(location::GpsInfo const & gpsInfo);
private:
bool DoesExtrapolationWork(uint64_t extrapolationTimeMs) const;
ExtrapolatedLocationUpdate m_extrapolatedLocationUpdate;
std::mutex m_mutex;
location::GpsInfo m_lastGpsInfo;
location::GpsInfo m_beforeLastGpsInfo;
uint64_t m_extrapolationCounter = m_extrapolationCounterUndefined;
};
threads::Thread m_extrapolatedLocationThread;
std::mutex m_mutex;
ExtrapolatedLocationUpdateFn m_extrapolatedLocationUpdate;
location::GpsInfo m_lastGpsInfo;
location::GpsInfo m_beforeLastGpsInfo;
uint64_t m_extrapolationCounter = m_extrapolationCounterUndefined;
};
} // namespace extrapolation

View file

@ -367,7 +367,7 @@ Framework::Framework(FrameworkParams const & params)
},
[this]() -> StringsBundle const & { return m_stringsBundle; }),
static_cast<RoutingManager::Delegate &>(*this))
, m_extrapolator([this](location::GpsInfo & gpsInfo) {
, m_extrapolator([this](location::GpsInfo const & gpsInfo) {
this->GetRoutingManager().OnLocationUpdate(gpsInfo);
})
, m_trafficManager(bind(&Framework::GetMwmsByRect, this, _1, false /* rough */),
@ -497,7 +497,6 @@ Framework::~Framework()
GetBookmarkManager().Teardown();
m_trafficManager.Teardown();
m_extrapolator.Cancel();
DestroyDrapeEngine();
m_model.SetOnMapDeregisteredCallback(nullptr);

View file

@ -918,17 +918,18 @@ void RoutingManager::MatchLocationToRoute(location::GpsInfo & location,
m_routingSession.MatchLocationToRoute(location, routeMatchingInfo);
}
void RoutingManager::OnLocationUpdate(location::GpsInfo & info)
void RoutingManager::OnLocationUpdate(location::GpsInfo const & info)
{
location::GpsInfo gpsInfo(info);
if (!m_drapeEngine)
m_gpsInfoCache = my::make_unique<location::GpsInfo>(info);
m_gpsInfoCache = my::make_unique<location::GpsInfo>(gpsInfo);
auto routeMatchingInfo = GetRouteMatchingInfo(info);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, info,
auto routeMatchingInfo = GetRouteMatchingInfo(gpsInfo);
m_drapeEngine.SafeCall(&df::DrapeEngine::SetGpsInfo, gpsInfo,
m_routingSession.IsNavigable(), routeMatchingInfo);
if (IsTrackingReporterEnabled())
m_trackingReporter.AddLocation(info, m_routingSession.MatchTraffic(routeMatchingInfo));
m_trackingReporter.AddLocation(gpsInfo, m_routingSession.MatchTraffic(routeMatchingInfo));
}
location::RouteMatchingInfo RoutingManager::GetRouteMatchingInfo(location::GpsInfo & info)

View file

@ -209,7 +209,7 @@ public:
void OnBuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
void OnRebuildRouteReady(routing::Route const & route, routing::RouterResultCode code);
void OnRoutePointPassed(RouteMarkType type, size_t intermediateIndex);
void OnLocationUpdate(location::GpsInfo & info);
void OnLocationUpdate(location::GpsInfo const & info);
void SetAllowSendingPoints(bool isAllowed)
{
m_trackingReporter.SetAllowSendingPoints(isAllowed);