1 /* 2 * Copyright 2022 Google LLC 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef FCP_AGGREGATION_CORE_AGGREGATOR_H_ 18 #define FCP_AGGREGATION_CORE_AGGREGATOR_H_ 19 20 #include "fcp/base/monitoring.h" 21 22 namespace fcp { 23 namespace aggregation { 24 25 // Abstract base for aggregators that compute an aggregate of input items of 26 // type T into a final aggregate of type R using a multi-stage process in which 27 // items are first partially aggregated at an intermediate layer, then the 28 // partial aggregates are further combined, and finally projected into the 29 // result. This multi-stage process consists of the following: 30 // a) The aggregator is created with a zero value of an arbitrary intermediate 31 // type U. Please note that the type U is never surfaced and considered an 32 // implementation detail, so it doesn't need to be explicitlty parameterized. 33 // b) The method Accumulate is used to accumulate T-typed client items into the 34 // U-typed partial aggregate. 35 // c) The method Merge is used to merge the intermediate U-typed aggregates of 36 // the two aggregator instances producing a merged U-typed aggregate. 37 // d) The method Report is used to project the top-level U-typed aggregate into 38 // the final R-typed result. 39 // The typename Self is used to specify the actual derived class. 40 template <typename T, typename R, typename Self> 41 class Aggregator { 42 public: 43 Aggregator() = default; 44 virtual ~Aggregator() = default; 45 46 // Aggregator derived classes are not copyable. 47 Aggregator(const Aggregator&) = delete; 48 49 // Accumulates an input into the intermediate aggregate. 50 // The method may fail if the input isn't compatible with the current 51 // Aggregator or if the Aggregator instance has already been 'consumed'. 52 virtual Status Accumulate(T input) = 0; 53 54 // Merges intermediate aggregates from the other Aggregator instance into the 55 // current Aggregator instance. Doing so 'consumes' the other Aggregator 56 // instance. 57 // The method may fail if the two Aggregator instances aren't compatible. 58 virtual Status MergeWith(Self&& other) = 0; 59 60 // Returns true if the current Aggregator instance can produce a report, for 61 // example if a sufficient number of inputs has been accumulated. 62 virtual bool CanReport() const = 0; 63 64 // Produces the final report, 'consuming' the current Aggregator instance. 65 // Once the current instance is consumed it can no longer perform any 66 // operations. 67 // This method fails when CanReport method returns false. 68 virtual StatusOr<R> Report() && = 0; 69 }; 70 71 } // namespace aggregation 72 } // namespace fcp 73 74 #endif // FCP_AGGREGATION_CORE_AGGREGATOR_H_ 75