1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#include "map/booking_filter_processor.hpp"
#include "map/booking_availability_filter.hpp"
#include "search/result.hpp"
namespace booking
{
namespace filter
{
FilterProcessor::FilterProcessor(DataSourceBase const & dataSource, booking::Api const & api)
: m_dataSource(dataSource)
, m_api(api)
{
m_filters.emplace(Type::Deals, std::make_unique<AvailabilityFilter>(*this));
m_filters.emplace(Type::Availability, std::make_unique<AvailabilityFilter>(*this));
}
void FilterProcessor::ApplyFilters(search::Results const & results, TasksInternal && tasks,
ApplicationMode const mode)
{
GetPlatform().RunTask(Platform::Thread::File, [this, results, tasks = std::move(tasks), mode]() mutable
{
CHECK(!tasks.empty(), ());
switch (mode)
{
case Independent: ApplyIndependently(results, tasks); break;
case Consecutive: ApplyConsecutively(results, tasks); break;
}
});
}
void FilterProcessor::OnParamsUpdated(Type const type,
std::shared_ptr<ParamsBase> const & apiParams)
{
GetPlatform().RunTask(Platform::Thread::File,
[this, type, apiParams = std::move(apiParams)]() mutable
{
m_filters.at(type)->UpdateParams(*apiParams);
});
}
void FilterProcessor::GetFeaturesFromCache(Types const & types, search::Results const & results,
FillSearchMarksCallback const & callback)
{
GetPlatform().RunTask(Platform::Thread::File, [this, types, results, callback]()
{
CachedResults cachedResults;
for (auto const type : types)
{
std::vector<FeatureID> featuresSorted;
m_filters.at(type)->GetFeaturesFromCache(results, featuresSorted);
ASSERT(std::is_sorted(featuresSorted.begin(), featuresSorted.end()), ());
cachedResults.emplace_back(type, std::move(featuresSorted));
}
callback(std::move(cachedResults));
});
}
DataSourceBase const & FilterProcessor::GetDataSource() const
{
return m_dataSource;
}
Api const & FilterProcessor::GetApi() const
{
return m_api;
}
void FilterProcessor::ApplyConsecutively(search::Results const & results, TasksInternal & tasks)
{
for (size_t i = tasks.size() - 1; i > 0; --i)
{
auto const & cb = tasks[i - 1].m_filterParams.m_callback;
tasks[i - 1].m_filterParams.m_callback =
[this, cb, nextTask = std::move(tasks[i])](search::Results const & results) mutable
{
cb(results);
// Run the next filter with obtained results from the previous one.
// Post different task on the file thread to increase granularity.
GetPlatform().RunTask(Platform::Thread::File, [this, results, nextTask = std::move(nextTask)]()
{
m_filters.at(nextTask.m_type)->ApplyFilter(results, nextTask.m_filterParams);
});
};
}
// Run the first filter.
m_filters.at(tasks.front().m_type)->ApplyFilter(results, tasks.front().m_filterParams);
}
void FilterProcessor::ApplyIndependently(search::Results const & results,
TasksInternal const & tasks)
{
for (auto const & task : tasks)
m_filters.at(task.m_type)->ApplyFilter(results, task.m_filterParams);
}
} // namespace filter
} // namespace booking
|