114 lines · c
1//===- record_section_tracker.h -- for fixed-sized record sects -*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// RecordSectionsTracker: Responsible for managing sections of metadata records10// with fixed sizes.11//12//===----------------------------------------------------------------------===//13 14#ifndef ORC_RT_RECORD_SECTION_TRACKER_H15#define ORC_RT_RECORD_SECTION_TRACKER_H16 17#include "error.h"18#include "executor_address.h"19#include <algorithm>20#include <vector>21 22namespace orc_rt {23 24/// Used to manage sections of fixed-sized metadata records (e.g. pointer25/// sections, selector refs, etc.)26template <typename RecordElement> class RecordSectionsTracker {27public:28 /// Add a section to the "new" list.29 void add(span<RecordElement> Sec) { New.push_back(std::move(Sec)); }30 31 /// Returns true if there are new sections to process.32 bool hasNewSections() const { return !New.empty(); }33 34 /// Returns the number of new sections to process.35 size_t numNewSections() const { return New.size(); }36 37 /// Process all new sections.38 template <typename ProcessSectionFunc>39 std::enable_if_t<std::is_void_v<40 std::invoke_result_t<ProcessSectionFunc, span<RecordElement>>>>41 processNewSections(ProcessSectionFunc &&ProcessSection) {42 for (auto &Sec : New)43 ProcessSection(Sec);44 moveNewToProcessed();45 }46 47 /// Proces all new sections with a fallible handler.48 ///49 /// Successfully handled sections will be moved to the Processed50 /// list.51 template <typename ProcessSectionFunc>52 std::enable_if_t<53 std::is_same_v<54 Error, std::invoke_result_t<ProcessSectionFunc, span<RecordElement>>>,55 Error>56 processNewSections(ProcessSectionFunc &&ProcessSection) {57 for (size_t I = 0; I != New.size(); ++I) {58 if (auto Err = ProcessSection(New[I])) {59 for (size_t J = 0; J != I; ++J)60 Processed.push_back(New[J]);61 New.erase(New.begin(), New.begin() + I);62 return Err;63 }64 }65 moveNewToProcessed();66 return Error::success();67 }68 69 /// Move all sections back to New for reprocessing.70 void reset() {71 moveNewToProcessed();72 New = std::move(Processed);73 }74 75 /// Remove the section with the given range.76 bool removeIfPresent(ExecutorAddrRange R) {77 if (removeIfPresent(New, R))78 return true;79 return removeIfPresent(Processed, R);80 }81 82private:83 void moveNewToProcessed() {84 if (Processed.empty())85 Processed = std::move(New);86 else {87 Processed.reserve(Processed.size() + New.size());88 std::copy(New.begin(), New.end(), std::back_inserter(Processed));89 New.clear();90 }91 }92 93 bool removeIfPresent(std::vector<span<RecordElement>> &V,94 ExecutorAddrRange R) {95 auto RI = std::find_if(96 V.rbegin(), V.rend(),97 [RS = R.toSpan<RecordElement>()](const span<RecordElement> &E) {98 return E.data() == RS.data();99 });100 if (RI != V.rend()) {101 V.erase(std::next(RI).base());102 return true;103 }104 return false;105 }106 107 std::vector<span<RecordElement>> Processed;108 std::vector<span<RecordElement>> New;109};110 111} // namespace orc_rt112 113#endif // ORC_RT_RECORD_SECTION_TRACKER_H114