11 if (
m_is_processing.load(std::memory_order_acquire) || processor->m_active_processing.load(std::memory_order_acquire) > 0) {
20 auto processor_token = processor->get_processing_token();
25 if (rejection_reason) {
26 *rejection_reason =
"Processor token (" + std::to_string(
static_cast<uint32_t
>(processor_token)) +
") does not exactly match chain's preferred token (" + std::to_string(
static_cast<uint32_t
>(
m_token_filter_mask)) +
") in STRICT mode";
34 if (rejection_reason) {
35 *rejection_reason =
"Processor token (" + std::to_string(
static_cast<uint32_t
>(processor_token)) +
") is not compatible with chain's preferred token (" + std::to_string(
static_cast<uint32_t
>(
m_token_filter_mask)) +
") in FILTERED mode";
59 auto it = std::ranges::find(processors, processor);
61 if (it != processors.end()) {
62 if (rejection_reason) {
63 *rejection_reason =
"Processor already exists in chain for this buffer";
68 processors.push_back(processor);
69 processor->on_attach(
buffer);
85 const std::shared_ptr<BufferProcessor>& processor,
86 const std::shared_ptr<Buffer>&
buffer,
87 bool search_all_slots)
94 if (search_all_slots) {
104 auto it = std::ranges::find(processors, processor);
106 if (it != processors.end()) {
107 processor->on_detach(
buffer);
108 processors.erase(it);
119 auto processor_it = std::ranges::find(regular_it->second, processor);
120 if (processor_it != regular_it->second.end()) {
121 processor->on_detach(
buffer);
122 regular_it->second.erase(processor_it);
129 auto remove_slot = [&processor, &
buffer](
auto& slots,
const auto& key) {
130 auto it = slots.find(key);
131 if (it == slots.end() || it->second != processor)
134 it->second->on_detach(
buffer);
157 for (
auto& processor : it->second) {
158 bool should_process =
true;
161 auto processor_token = processor->get_processing_token();
165 if (should_process) {
166 processor->process_non_owning(
buffer);
177 bool expected =
false;
179 std::memory_order_acquire, std::memory_order_relaxed)) {
193 for (
auto& processor : it->second) {
194 bool should_process =
true;
197 auto processor_token = processor->get_processing_token();
201 if (should_process) {
202 processor->process(
buffer);
224 if (m_pending_op.active.load(std::memory_order_acquire)) {
225 auto& op = m_pending_op;
227 if (op.is_addition) {
229 }
else if (op.search_all_slots) {
235 op.processor.reset();
237 op.active.store(
false, std::memory_order_release);
245 processor->on_attach(
buffer);
251 processor->on_attach(
buffer);
257 processor->on_attach(
buffer);
269 static const std::vector<std::shared_ptr<BufferProcessor>> empty_vector;
279std::shared_ptr<BufferProcessor>
286std::shared_ptr<BufferProcessor>
293std::shared_ptr<BufferProcessor>
304 pre_it->second->process(
buffer);
312 post_it->second->process(
buffer);
320 final_it->second->process(
buffer);
326 for (
const auto& [
buffer, processors] : other->get_chain()) {
331 target_processors.reserve(target_processors.size() + processors.size());
333 for (
const auto& processor : processors) {
334 if (std::ranges::find(target_processors, processor) == target_processors.end()) {
335 target_processors.push_back(processor);
345 if (processors.empty()) {
349 std::vector<std::shared_ptr<BufferProcessor>> compatible_processors;
350 std::vector<std::shared_ptr<BufferProcessor>> incompatible_processors;
352 for (
auto& processor : processors) {
353 auto processor_token = processor->get_processing_token();
355 compatible_processors.push_back(processor);
357 incompatible_processors.push_back(processor);
363 processors.insert(processors.end(), compatible_processors.begin(), compatible_processors.end());
366 processors.insert(processors.end(), incompatible_processors.begin(), incompatible_processors.end());
374 std::erase_if(processors, [
this](
const std::shared_ptr<BufferProcessor>& processor) {
375 auto processor_token = processor->get_processing_token();
384 std::vector<TokenCompatibilityReport> reports;
392 for (
const auto& processor : processors) {
403 reports.push_back(report);
411 bool all_compatible =
true;
414 for (
const auto& processor : processors) {
415 auto processor_token = processor->get_processing_token();
417 all_compatible =
false;
418 if (incompatibility_reasons) {
419 incompatibility_reasons->push_back(
420 "Processor with token " + std::to_string(
static_cast<uint32_t
>(processor_token)) +
" incompatible with chain preferred token " + std::to_string(
static_cast<uint32_t
>(
m_token_filter_mask)));
426 return all_compatible;
432 for (
auto& processor : processors) {
433 auto processor_token = processor->get_processing_token();
438 }
catch (
const std::exception& e) {
440 std::source_location::current(),
441 "Failed to enforce chain token on processor: " + std::string(e.what()));
449 const std::shared_ptr<BufferProcessor>& processor,
450 const std::shared_ptr<Buffer>&
buffer,
452 bool search_all_slots,
453 std::string* rejection_reason)
456 bool expected =
false;
457 if (m_pending_op.active.compare_exchange_strong(
459 std::memory_order_acquire,
460 std::memory_order_relaxed)) {
462 m_pending_op.processor = processor;
463 m_pending_op.buffer =
buffer;
464 m_pending_op.is_addition = is_addition;
465 m_pending_op.search_all_slots = search_all_slots;
471 if (rejection_reason && is_addition) {
472 *rejection_reason =
"Processor operation queue full";
std::shared_ptr< NetworkGeometryBuffer > buffer
std::shared_ptr< BufferProcessor > get_preprocessor(const std::shared_ptr< Buffer > &buffer) const
Returns the preprocessor for a buffer, or nullptr if none is set.
void process_complete(const std::shared_ptr< Buffer > &buffer)
Applies preprocessors, processing chain, post processors and final processors sequentially to a buffe...
void add_final_processor(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
Sets a special processor to be applied after the main pipeline.
void remove_processor_anywhere(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
Removes a processor from any slot associated with a buffer.
void process(const std::shared_ptr< Buffer > &buffer)
Applies the transformation pipeline to a buffer with intelligent execution.
std::atomic< bool > m_is_processing
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< BufferProcessor > > m_final_processors
Map of buffers to their final processors.
void add_preprocessor(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
Sets a preprocessor to be applied before the main pipeline.
void add_postprocessor(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
Sets a postprocessor to be applied after the main pipeline.
std::unordered_map< std::shared_ptr< Buffer >, std::unordered_set< std::shared_ptr< BufferProcessor > > > m_pending_removal
Map of buffers to processors pending removal.
void remove_processor_internal(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer, bool search_all_slots)
std::vector< TokenCompatibilityReport > analyze_token_compatibility() const
Analyzes token compatibility across all processors in the chain.
void remove_processor_anywhere_direct(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
std::atomic< uint32_t > m_pending_count
ProcessingToken m_token_filter_mask
Preferred processing token for this chain.
std::unordered_map< std::shared_ptr< Buffer >, std::vector< std::shared_ptr< BufferProcessor > > > m_buffer_processors
Map of buffers to their processor sequences.
void process_non_owning(const std::shared_ptr< Buffer > &buffer)
Internal processing method for non-owning buffer contexts.
void preprocess(const std::shared_ptr< Buffer > &buffer)
Applies the preprocessor to a buffer.
std::shared_ptr< BufferProcessor > get_postprocessor(const std::shared_ptr< Buffer > &buffer) const
Returns the postprocessor for a buffer, or nullptr if none is set.
bool validate_all_processors(std::vector< std::string > *incompatibility_reasons=nullptr) const
Validates all processors in the chain against the preferred processing token.
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< BufferProcessor > > m_preprocessors
Map of buffers to their preprocessors.
const std::vector< std::shared_ptr< BufferProcessor > > & get_processors(const std::shared_ptr< Buffer > &buffer) const
Gets all processors in a buffer's transformation pipeline.
bool add_processor(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer, std::string *rejection_reason=nullptr)
Adds a processor to the transformation pipeline for a specific buffer.
void remove_processor(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
Removes a processor from the pipeline for a specific buffer.
void cleanup_rejected_processors(const std::shared_ptr< Buffer > &buffer)
Validates the processing token against the chain's preferred token.
void merge_chain(const std::shared_ptr< BufferProcessingChain > &other)
Combines another processing pipeline into this one with optimization.
void process_pending_processor_operations()
Process pending processor operations.
void enforce_chain_token_on_processors()
Enforces the chain's preferred processing token on all processors.
bool queue_pending_processor_op(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer, bool is_addition, bool search_all_slots=false, std::string *rejection_reason=nullptr)
std::shared_ptr< BufferProcessor > get_final_processor(const std::shared_ptr< Buffer > &buffer) const
Returns the final processor for a buffer, or nullptr if none is set.
TokenEnforcementStrategy m_enforcement_strategy
Token enforcement strategy for this chain.
void remove_processor_direct(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer)
void postprocess(const std::shared_ptr< Buffer > &buffer)
Applies the postprocessor to a buffer.
void optimize_for_tokens(const std::shared_ptr< Buffer > &buffer)
Optimizes the processing pipeline for improved performance.
PendingProcessorOp m_pending_ops[MAX_PENDING_PROCESSORS]
bool has_processors(const std::shared_ptr< Buffer > &buffer) const
Checks if a buffer has any processors in its pipeline.
void process_final(const std::shared_ptr< Buffer > &buffer)
Applies the final processor to a buffer with guaranteed execution.
bool add_processor_direct(const std::shared_ptr< BufferProcessor > &processor, const std::shared_ptr< Buffer > &buffer, std::string *rejection_reason=nullptr)
std::unordered_map< std::shared_ptr< Buffer >, std::unordered_set< std::shared_ptr< BufferProcessor > > > m_conditional_processors
Map of buffers to processors that are conditionally applied.
std::unordered_map< std::shared_ptr< Buffer >, std::shared_ptr< BufferProcessor > > m_postprocessors
Map of buffers to their postprocessors.
bool are_tokens_compatible(ProcessingToken preferred, ProcessingToken current)
Determines if two processing tokens are compatible for joint execution.
@ OVERRIDE_SKIP
Allows token overrides but skips processing for incompatible operations.
@ STRICT
Strictly enforces token assignment with no cross-token sharing.
@ OVERRIDE_REJECT
Allows token overrides but rejects incompatible processors from chains.
@ FILTERED
Filters processors through token enumeration, allowing compatible combinations.
@ IGNORE
Ignores token assignments completely, allowing any processing combination.
@ BufferProcessing
Buffer processing (Buffers::BufferManager, processing chains)
@ Buffers
Buffers, Managers, processors and processing chains.
std::shared_ptr< BufferProcessor > processor
ProcessingToken processor_token
Holds information about a processor's compatibility with a buffer's processing token.
std::shared_ptr< Buffer > buffer
TokenEnforcementStrategy enforcement_strategy
ProcessingToken chain_preferred_token
std::vector< ProcessorTokenInfo > processor_infos
Holds the results of token compatibility analysis for a buffer processing chain.