@@ -83,16 +83,26 @@ class CoordinateSelector {
8383 explicit CoordinateSelector (Dataset& dataset)
8484 : dataset_(dataset), base_domain_(dataset.domain) {}
8585
86- template <typename OutT, typename ... Ops>
87- Future<std::vector<OutT>> ReadDataVariable (const std::string& data_variable,
88- Ops const &... ops) {
89- // 1) apply filters & sorts in the exact order given
86+ template <typename ... OutTs, typename ... Ops>
87+ Future<std::tuple<std::vector<OutTs>...>> ReadDataVariables (
88+ std::vector<std::string> const & data_variables,
89+ Ops const &... ops)
90+ {
91+ if (data_variables.size () != sizeof ...(OutTs)) {
92+ return absl::InvalidArgumentError (
93+ " ReadDataVariables: number of names must match number of OutTs" );
94+ }
95+ // 1) apply all filters & sorts in order
9096 absl::Status st = absl::OkStatus ();
9197 ((st = st.ok () ? _applyOp (ops).status () : st), ...);
9298 if (!st.ok ()) return st;
9399
94- // 2) finally read out the requested variable
95- return readSelection<OutT>(data_variable);
100+ // 2) kick off and await all reads
101+ return _readMultiple<OutTs...>(data_variables);
102+ }
103+
104+ void reset () {
105+ kept_runs_.clear ();
96106 }
97107
98108 /* *
@@ -249,6 +259,43 @@ class CoordinateSelector {
249259 }
250260 }
251261
262+ // helper: expands readSelection<OutTs>(vars[I])...
263+ template <typename ... OutTs, std::size_t ... I>
264+ Future<std::tuple<std::vector<OutTs>...>> _readMultipleImpl (
265+ std::vector<std::string> const & vars,
266+ std::index_sequence<I...>)
267+ {
268+ // 1) start all reads
269+ auto futs = std::make_tuple (
270+ readSelection<OutTs>(vars[I])...
271+ );
272+
273+ // 2) wait on them in order
274+ absl::Status st = absl::OkStatus ();
275+ std::tuple<std::vector<OutTs>...> results;
276+ // fold over I...
277+ (
278+ [&](){
279+ if (!st.ok ()) return ;
280+ auto & f = std::get<I>(futs);
281+ st = f.status ();
282+ if (st.ok ()) std::get<I>(results) = std::move (f.value ());
283+ }(),
284+ ...
285+ );
286+ if (!st.ok ()) return st;
287+ return results;
288+ }
289+
290+ template <typename ... OutTs>
291+ Future<std::tuple<std::vector<OutTs>...>> _readMultiple (
292+ std::vector<std::string> const & vars)
293+ {
294+ return _readMultipleImpl<OutTs...>(
295+ vars, std::index_sequence_for<OutTs...>{}
296+ );
297+ }
298+
252299 /*
253300 TODO: The built RangeDescriptors aren't behaving as I hoped.
254301 They are building the longest runs possible properly, however
0 commit comments