Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 10:01:39

0001 
0002 // Copyright 2020, Jefferson Science Associates, LLC.
0003 // Subject to the terms in the LICENSE file found in the top-level directory.
0004 
0005 #pragma once
0006 #include <JANA/JObject.h>
0007 
0008 using DetectorId = uint64_t;
0009 using Timestamp = uint64_t;
0010 
0011 
0012 /// JMessage is an interface for data that can be streamed using JTransports.
0013 ///
0014 /// The basic goal is to have an object wrapper around an old-fashioned `char*` buffer
0015 /// which can be created automatically on either the stack or the heap. Most importantly,
0016 /// it encapsulates the mess arising from variable message lengths. A common pattern
0017 /// for solving this problem in C is to use flexible array members. Do NOT do this here,
0018 /// as this causes a variety of problems when it comes to type safety and memory safety,
0019 /// and it is not even part of any C++ standard. Instead, agree upon a max message size
0020 /// (which your transport needs anyway), and declare an array of that length. The
0021 /// array length (a.k.a. 'capacity') should be a compile-time constant, and the length
0022 /// of the data contained (a.k.a. 'size') should be tracked in a separate variable.
0023 ///
0024 /// In addition to the pure virtual methods listed below, conforming implementations need
0025 /// a zero-argument constructor.
0026 
0027 struct JMessage {
0028 
0029     /// Expose the underlying buffer via a raw pointer
0030     /// \return A raw pointer to the buffer
0031     virtual char* as_buffer() = 0;
0032 
0033     /// Expose the underlying buffer via a raw pointer
0034     /// \return A raw pointer to the buffer
0035     virtual const char* as_buffer() const = 0;
0036 
0037     /// Determine the length of the buffer itself, a.k.a. the max number of bytes that can be written.
0038     /// \return The number of bytes allocated for the buffer
0039     virtual size_t get_buffer_capacity() const = 0;
0040 
0041     /// Determine the length of the buffer's contents, a.k.a. the number of bytes which ought to be read
0042     /// \return The number of bytes of meaningful data inside the buffer
0043     virtual size_t get_buffer_size() const { return get_buffer_capacity(); }
0044 
0045     /// Determine whether this is the last message.
0046     /// An end-of-stream message is assumed to also contain a meaningful payload. It is not empty like EOF.
0047     /// TODO: Figure out best way to handle empty end-of-stream as well as other control signals such as change-run.
0048     /// \return Whether this is the last message to expect from the producer
0049     virtual bool is_end_of_stream() const = 0;
0050 };
0051 
0052 
0053 /// A JEventMessage is an interface used by JTransport for streaming individual events.
0054 ///
0055 /// In other words, this assumes that event building is done upstream. Each JEventMessage will be inserted
0056 /// into its own brand new JEvent just like any other JObject. The implementor is responsible for figuring out
0057 /// the event and run numbers. The code for parsing the message payload could either be expressed as getter methods
0058 /// on the JEventMessage implementation, or in its own JFactory. If the message format is the same as the in-memory
0059 /// representation (non-portable but fast), the JEventMessage can be defined as a plain-old-data struct and the `char*`
0060 /// buffer obtained via `reinterpret_cast`.
0061 
0062 struct JEventMessage : public JMessage, public JObject {
0063 
0064     /// Determine what the event number should be for the JEvent that gets emitted for this message. This information
0065     /// should be available from the message payload. If not, return zero, in which case the JStreamingEventSource
0066     /// will issue an event number automatically.
0067     virtual size_t get_event_number() const = 0;
0068 
0069     /// Determine what the run number should be for the JEvent that gets emitted for this message. This information
0070     /// should be available from the message payload. If not, return zero, in which case the JStreamingEventSource
0071     /// will use the last known run number.
0072     virtual size_t get_run_number() const = 0;
0073 };
0074 
0075 
0076 /// A JHitMessage is an interface used by JTransport for streaming detector hits.
0077 ///
0078 /// Either we do event building ourselves using JEventBuilder, or we hydrate an existing event using JDiscreteJoin.
0079 ///
0080 /// These methods extract the information necessary to figure out which JEvent this Hit belongs to,
0081 /// and also whether we've received data from all detectors needed before emitting a new Event.
0082 /// This works for both discrete-in-time data and continuous-in-time data.
0083 
0084 struct JHitMessage : public JMessage {
0085 
0086     /// Extract the detector ID from the message payload. This is mandatory.
0087     virtual DetectorId get_source_id() const = 0;
0088 
0089     /// Extract the detector ID from the message payload. This is mandatory.
0090     virtual Timestamp get_timestamp() const = 0;
0091 };
0092