Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-11-05 10:02:05

0001 // Copyright 2023, Jefferson Science Associates, LLC.
0002 // Subject to the terms in the LICENSE file found in the top-level directory.
0003 
0004 #pragma once
0005 
0006 #include <JANA/Topology/JArrow.h>
0007 #include <JANA/JEventUnfolder.h>
0008 
0009 class JUnfoldArrow : public JArrow {
0010 public:
0011     enum PortIndex {PARENT_IN=0, CHILD_IN=1, CHILD_OUT=2, REJECTED_PARENT_OUT=3};
0012 
0013 private:
0014     JEventUnfolder* m_unfolder = nullptr;
0015     JEvent* m_parent_event = nullptr;
0016     JEvent* m_child_event = nullptr;
0017 
0018 public:
0019     JUnfoldArrow(std::string name, JEventUnfolder* unfolder) : m_unfolder(unfolder) {
0020         set_name(name);
0021         create_ports(2, 2);
0022         m_next_input_port = PARENT_IN;
0023         m_ports[CHILD_OUT].establishes_ordering=true; // Just in case there's a folder that needs this
0024     }
0025 
0026     void initialize() final {
0027         m_unfolder->DoInit();
0028         LOG_INFO(m_logger) << "Initialized JEventUnfolder '" << m_unfolder->GetTypeName() << "'" << LOG_END;
0029     }
0030 
0031     void finalize() final {
0032         m_unfolder->DoFinish();
0033         LOG_INFO(m_logger) << "Finalized JEventUnfolder '" << m_unfolder->GetTypeName() << "'" << LOG_END;
0034     }
0035 
0036     void fire(JEvent* event, OutputData& outputs, size_t& output_count, JArrow::FireResult& status) final {
0037 
0038         // Take whatever we were given
0039         if (this->m_next_input_port == PARENT_IN) {
0040             assert(m_parent_event == nullptr);
0041             m_parent_event = event;
0042             m_parent_event->TakeRefToSelf();
0043         }
0044         else if (this->m_next_input_port == CHILD_IN) {
0045             assert(m_child_event == nullptr);
0046             m_child_event = event;
0047         }
0048         else {
0049             throw JException("Invalid input port for JEventUnfolder!");
0050         }
0051 
0052         // Check if we should exit early because we don't have a parent event
0053         if (m_parent_event == nullptr) {
0054             m_next_input_port = PARENT_IN;
0055             output_count = 0;
0056             status = JArrow::FireResult::KeepGoing;
0057             return;
0058         }
0059 
0060         // Check if we should exit early because we don't have a child event
0061         if (m_child_event == nullptr) {
0062             m_next_input_port = CHILD_IN;
0063             output_count = 0;
0064             status = JArrow::FireResult::KeepGoing;
0065             return;
0066         }
0067 
0068         // At this point we know we have both inputs, so we can run the unfolder. First we validate 
0069         // that the events we received are at the correct level for the unfolder. Hopefully the only 
0070         // way to end up here is to override the JTopologyBuilder wiring and do it wrong
0071 
0072         if (m_parent_event->GetLevel() != m_unfolder->GetLevel()) {
0073             throw JException("JUnfolder: Expected parent with level %s, got %s", toString(m_unfolder->GetLevel()).c_str(), toString(m_parent_event->GetLevel()).c_str());
0074         }
0075 
0076         if (m_child_event->GetLevel() != m_unfolder->GetChildLevel()) {
0077             throw JException("JUnfolder: Expected child with level %s, got %s", toString(m_unfolder->GetChildLevel()).c_str(), toString(m_child_event->GetLevel()).c_str());
0078         }
0079 
0080         auto result = m_unfolder->DoUnfold(*m_parent_event, *m_child_event);
0081         LOG_DEBUG(m_logger) << "Unfold succeeded: Parent event = " << m_parent_event->GetEventNumber() << ", child event = " << m_child_event->GetEventNumber() << LOG_END;
0082 
0083         if (result == JEventUnfolder::Result::KeepChildNextParent) {
0084             // KeepChildNextParent is a little more complicated because we have to handle the case of the parent having no children.
0085             // In this case the parent obviously doesn't get shared among any children, and instead it is sent to the REJECTED_PARENT_OUT port.
0086             int child_count = m_parent_event->ReleaseRefToSelf(); // Decrement the reference count so that this can be recycled
0087             LOG_DEBUG(m_logger) << "Unfold finished with parent event = " << m_parent_event->GetEventNumber() << " (" << child_count << " children emitted)";
0088 
0089             if (child_count > 0) {
0090                 // Parent DOES have children even though this particular child isn't one of them
0091                 m_parent_event = nullptr;
0092                 output_count = 0;
0093                 m_next_input_port = PARENT_IN;
0094                 status = JArrow::FireResult::KeepGoing;
0095                 return;
0096             }
0097             else {
0098                 // Parent has NO children
0099                 output_count = 1;
0100                 outputs[0] = {m_parent_event, REJECTED_PARENT_OUT};
0101                 m_parent_event = nullptr;
0102                 m_next_input_port = PARENT_IN;
0103                 status = JArrow::FireResult::KeepGoing;
0104                 return;
0105             }
0106         }
0107         else if (result == JEventUnfolder::Result::NextChildKeepParent) {
0108             m_child_event->SetParent(m_parent_event);
0109             outputs[0] = {m_child_event, CHILD_OUT};
0110             output_count = 1;
0111             m_child_event = nullptr;
0112             m_next_input_port = CHILD_IN;
0113             status = JArrow::FireResult::KeepGoing;
0114             return;
0115         }
0116         else if (result == JEventUnfolder::Result::NextChildNextParent) {
0117             m_child_event->SetParent(m_parent_event);
0118             m_parent_event->ReleaseRefToSelf(); // Decrement the reference count so that this can be recycled
0119             outputs[0] = {m_child_event, CHILD_OUT};
0120             output_count = 1;
0121             LOG_DEBUG(m_logger) << "Unfold finished with parent event = " << m_parent_event->GetEventNumber() << LOG_END;
0122             m_child_event = nullptr;
0123             m_parent_event = nullptr;
0124             m_next_input_port = PARENT_IN;
0125             status = JArrow::FireResult::KeepGoing;
0126             return;
0127         }
0128         else {
0129             throw JException("Unsupported (corrupt?) JEventUnfolder::Result");
0130         }
0131     }
0132 };
0133 
0134