init commit
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
namespace radar::ipc {
|
||||
|
||||
struct Complex32 {
|
||||
float re = 0.0F;
|
||||
float im = 0.0F;
|
||||
};
|
||||
|
||||
struct ComboKey {
|
||||
// Zero-based switch positions.
|
||||
std::uint32_t input_pos = 0;
|
||||
std::uint32_t output_pos = 0;
|
||||
|
||||
[[nodiscard]] auto operator==(const ComboKey& other) const -> bool {
|
||||
return input_pos == other.input_pos && output_pos == other.output_pos;
|
||||
}
|
||||
};
|
||||
|
||||
struct ComboKeyHash {
|
||||
[[nodiscard]] auto operator()(const ComboKey& key) const noexcept -> std::size_t {
|
||||
return (static_cast<std::size_t>(key.input_pos) << 32U) ^ static_cast<std::size_t>(key.output_pos);
|
||||
}
|
||||
};
|
||||
|
||||
struct SweepTraceBlock {
|
||||
ComboKey combo{};
|
||||
// Frequency axis in Hz. Must have the same size as `s21`.
|
||||
std::vector<float> frequency_hz{};
|
||||
// Complex S21 samples for matching frequency points.
|
||||
std::vector<Complex32> s21{};
|
||||
};
|
||||
|
||||
struct RawSweepCollection {
|
||||
std::uint64_t collection_id = 0;
|
||||
std::uint64_t monotonic_ns = 0;
|
||||
std::vector<SweepTraceBlock> traces{};
|
||||
};
|
||||
|
||||
using PreprocessedCollection = RawSweepCollection;
|
||||
|
||||
enum class ResultKind : std::uint8_t {
|
||||
TraceComplex = 1,
|
||||
ScalarF32 = 2,
|
||||
};
|
||||
|
||||
struct ResultPayload {
|
||||
std::string processing_name{};
|
||||
ResultKind kind = ResultKind::TraceComplex;
|
||||
// Valid for TraceComplex payloads.
|
||||
std::vector<float> frequency_hz{};
|
||||
// Valid for TraceComplex payloads.
|
||||
std::vector<Complex32> trace{};
|
||||
// Valid for ScalarF32 payloads.
|
||||
float scalar_value = 0.0F;
|
||||
};
|
||||
|
||||
struct ResultBlock {
|
||||
ComboKey combo{};
|
||||
std::vector<ResultPayload> payloads{};
|
||||
};
|
||||
|
||||
struct ResultCollection {
|
||||
std::uint64_t collection_id = 0;
|
||||
std::uint64_t monotonic_ns = 0;
|
||||
std::vector<ResultBlock> blocks{};
|
||||
};
|
||||
|
||||
// Wire-format serialization helpers for IPC rings.
|
||||
[[nodiscard]] auto serialize_raw_collection(const RawSweepCollection& collection) -> std::vector<std::uint8_t>;
|
||||
[[nodiscard]] auto deserialize_raw_collection(std::span<const std::uint8_t> bytes) -> RawSweepCollection;
|
||||
|
||||
[[nodiscard]] auto serialize_preprocessed_collection(const PreprocessedCollection& collection)
|
||||
-> std::vector<std::uint8_t>;
|
||||
[[nodiscard]] auto deserialize_preprocessed_collection(std::span<const std::uint8_t> bytes)
|
||||
-> PreprocessedCollection;
|
||||
|
||||
[[nodiscard]] auto serialize_result_collection(const ResultCollection& collection) -> std::vector<std::uint8_t>;
|
||||
[[nodiscard]] auto deserialize_result_collection(std::span<const std::uint8_t> bytes) -> ResultCollection;
|
||||
|
||||
// Monotonic timestamp helper used for produced collections.
|
||||
[[nodiscard]] auto current_monotonic_ns() -> std::uint64_t;
|
||||
|
||||
} // namespace radar::ipc
|
||||
@@ -0,0 +1,61 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <span>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace radar::ipc {
|
||||
|
||||
class ShmRing {
|
||||
public:
|
||||
ShmRing() = default;
|
||||
~ShmRing();
|
||||
|
||||
ShmRing(const ShmRing&) = delete;
|
||||
auto operator=(const ShmRing&) -> ShmRing& = delete;
|
||||
|
||||
ShmRing(ShmRing&& other) noexcept;
|
||||
auto operator=(ShmRing&& other) noexcept -> ShmRing&;
|
||||
|
||||
[[nodiscard]] static auto open_or_create(
|
||||
const std::string& name,
|
||||
std::uint32_t capacity,
|
||||
std::uint32_t slot_size_bytes
|
||||
) -> ShmRing;
|
||||
|
||||
// Opens ring by name and validates wire-format header fields.
|
||||
[[nodiscard]] static auto open_existing(const std::string& name) -> ShmRing;
|
||||
// Removes shared memory object by name (safe if it does not exist).
|
||||
static void unlink_ring(const std::string& name);
|
||||
|
||||
[[nodiscard]] auto is_open() const -> bool;
|
||||
[[nodiscard]] auto capacity() const -> std::uint32_t;
|
||||
[[nodiscard]] auto slot_size_bytes() const -> std::uint32_t;
|
||||
[[nodiscard]] auto dropped_count() const -> std::uint64_t;
|
||||
|
||||
// Pushes payload with overwrite-oldest policy on overflow.
|
||||
[[nodiscard]] auto push(std::span<const std::uint8_t> payload) -> bool;
|
||||
// Pops the next payload if available.
|
||||
[[nodiscard]] auto pop(std::vector<std::uint8_t>& payload) -> bool;
|
||||
|
||||
private:
|
||||
struct Header;
|
||||
struct SlotHeader;
|
||||
|
||||
int fd_ = -1;
|
||||
std::size_t mapped_size_ = 0;
|
||||
void* mapped_ = nullptr;
|
||||
Header* header_ = nullptr;
|
||||
|
||||
// Slot geometry helpers.
|
||||
[[nodiscard]] auto slot_stride_bytes() const -> std::size_t;
|
||||
[[nodiscard]] auto slot_header(std::uint64_t sequence) const -> SlotHeader*;
|
||||
[[nodiscard]] auto slot_payload(SlotHeader* slot) const -> std::uint8_t*;
|
||||
|
||||
void close();
|
||||
static void validate_name(const std::string& name);
|
||||
};
|
||||
|
||||
} // namespace radar::ipc
|
||||
Reference in New Issue
Block a user