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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // RecordSectionsTracker: Responsible for managing sections of metadata records 10 // with fixed sizes. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef ORC_RT_RECORD_SECTION_TRACKER_H 15 #define ORC_RT_RECORD_SECTION_TRACKER_H 16 17 #include "error.h" 18 #include "executor_address.h" 19 #include <algorithm> 20 #include <vector> 21 22 namespace orc_rt { 23 24 /// Used to manage sections of fixed-sized metadata records (e.g. pointer 25 /// sections, selector refs, etc.) 26 template <typename RecordElement> class RecordSectionsTracker { 27 public: 28 /// Add a section to the "new" list. add(span<RecordElement> Sec)29 void add(span<RecordElement> Sec) { New.push_back(std::move(Sec)); } 30 31 /// Returns true if there are new sections to process. hasNewSections()32 bool hasNewSections() const { return !New.empty(); } 33 34 /// Returns the number of new sections to process. numNewSections()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>>>> processNewSections(ProcessSectionFunc && ProcessSection)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 Processed 50 /// 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> processNewSections(ProcessSectionFunc && ProcessSection)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. reset()70 void reset() { 71 moveNewToProcessed(); 72 New = std::move(Processed); 73 } 74 75 /// Remove the section with the given range. removeIfPresent(ExecutorAddrRange R)76 bool removeIfPresent(ExecutorAddrRange R) { 77 if (removeIfPresent(New, R)) 78 return true; 79 return removeIfPresent(Processed, R); 80 } 81 82 private: moveNewToProcessed()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 removeIfPresent(std::vector<span<RecordElement>> & V,ExecutorAddrRange R)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_rt 112 113 #endif // ORC_RT_RECORD_SECTION_TRACKER_H 114