//===- record_section_tracker.h -- for fixed-sized record sects -*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // RecordSectionsTracker: Responsible for managing sections of metadata records // with fixed sizes. // //===----------------------------------------------------------------------===// #ifndef ORC_RT_RECORD_SECTION_TRACKER_H #define ORC_RT_RECORD_SECTION_TRACKER_H #include "error.h" #include "executor_address.h" #include #include namespace orc_rt { /// Used to manage sections of fixed-sized metadata records (e.g. pointer /// sections, selector refs, etc.) template class RecordSectionsTracker { public: /// Add a section to the "new" list. void add(span Sec) { New.push_back(std::move(Sec)); } /// Returns true if there are new sections to process. bool hasNewSections() const { return !New.empty(); } /// Returns the number of new sections to process. size_t numNewSections() const { return New.size(); } /// Process all new sections. template std::enable_if_t>>> processNewSections(ProcessSectionFunc &&ProcessSection) { for (auto &Sec : New) ProcessSection(Sec); moveNewToProcessed(); } /// Proces all new sections with a fallible handler. /// /// Successfully handled sections will be moved to the Processed /// list. template std::enable_if_t< std::is_same_v< Error, std::invoke_result_t>>, Error> processNewSections(ProcessSectionFunc &&ProcessSection) { for (size_t I = 0; I != New.size(); ++I) { if (auto Err = ProcessSection(New[I])) { for (size_t J = 0; J != I; ++J) Processed.push_back(New[J]); New.erase(New.begin(), New.begin() + I); return Err; } } moveNewToProcessed(); return Error::success(); } /// Move all sections back to New for reprocessing. void reset() { moveNewToProcessed(); New = std::move(Processed); } /// Remove the section with the given range. bool removeIfPresent(ExecutorAddrRange R) { if (removeIfPresent(New, R)) return true; return removeIfPresent(Processed, R); } private: void moveNewToProcessed() { if (Processed.empty()) Processed = std::move(New); else { Processed.reserve(Processed.size() + New.size()); std::copy(New.begin(), New.end(), std::back_inserter(Processed)); New.clear(); } } bool removeIfPresent(std::vector> &V, ExecutorAddrRange R) { auto RI = std::find_if( V.rbegin(), V.rend(), [RS = R.toSpan()](const span &E) { return E.data() == RS.data(); }); if (RI != V.rend()) { V.erase(std::next(RI).base()); return true; } return false; } std::vector> Processed; std::vector> New; }; } // namespace orc_rt #endif // ORC_RT_RECORD_SECTION_TRACKER_H