On this page
article
peary/interfaces/Endpoint.hpp
peary/interfaces/Endpoint.hpp
Peary Interface Endpoint. More…
Namespaces
| Name |
|---|
| peary |
| peary::interface |
Classes
| Name | |
|---|---|
| class | peary::interface::InterfaceLock Helper class to hold the interface type-tagged lock. |
| class | peary::interface::Endpoint Communication interface endpoint. |
Detailed Description
Peary Interface Endpoint.
Copyright: Copyright (c) 2026 CERN and the Peary Caribou authors. This software is distributed under the terms of the LGPL-3.0-only License, copied verbatim in the file “LICENSE.md”. SPDX-License-Identifier: LGPL-3.0-only
Source code
#pragma once
#include <concepts>
#include <mutex>
#include <utility>
#include <vector>
#include "peary/interfaces/exceptions.hpp"
#include "peary/log/log.hpp"
#include "peary/utils/type.hpp"
namespace peary::interface {
/* Concept for the interface tag to be an empty struct */
template <typename T>
concept InterfaceTag = std::is_class_v<T> && std::is_empty_v<T>;
template <typename InterfaceTag> class InterfaceLock {
public:
InterfaceLock() : lock_(mutex()) {
LOG(TRACE) << "Lock acquired for interface " << utils::demangle(typeid(InterfaceTag));
}
~InterfaceLock() { LOG(TRACE) << "Lock released for interface " << utils::demangle(typeid(InterfaceTag)); }
InterfaceLock(const InterfaceLock&) = delete;
InterfaceLock& operator=(const InterfaceLock&) = delete;
private:
static std::mutex& mutex() {
static std::mutex m;
return m;
}
std::scoped_lock<std::mutex> lock_;
};
template <typename InterfaceTag, typename RegisterType, typename DataType> class Endpoint {
public:
/* Defining shorthand notations for data types */
using reg_t = RegisterType;
using data_t = DataType;
using pair_t = std::pair<RegisterType, DataType>;
using vector_t = std::vector<DataType>;
/* Delete copy constructors, since these endpoints communicate with hardware, they cannot be copied */
Endpoint(const Endpoint&) = delete;
Endpoint& operator=(const Endpoint&) = delete;
/* Disallow move semantics */
Endpoint(Endpoint&&) noexcept = delete;
Endpoint& operator=(Endpoint&&) noexcept = delete;
std::string info() const { return endpoint_info_; }
data_t write(const data_t& value) {
InterfaceLock<InterfaceTag> lock;
return write_impl(value);
}
vector_t write(const vector_t& values) {
InterfaceLock<InterfaceTag> lock;
return write_impl(values);
}
pair_t write(const pair_t& regData) {
InterfaceLock<InterfaceTag> lock;
return write_impl(regData);
}
vector_t write(const reg_t& reg, const vector_t& values) {
InterfaceLock<InterfaceTag> lock;
return write_impl(reg, values);
}
std::vector<pair_t> write(const std::vector<pair_t>& regDataVec) {
InterfaceLock<InterfaceTag> lock;
return write_impl(regDataVec);
}
data_t read() {
InterfaceLock<InterfaceTag> lock;
return read_impl();
}
vector_t read(unsigned int count) {
InterfaceLock<InterfaceTag> lock;
return read_impl(count);
}
vector_t read(const reg_t& reg, unsigned int count) {
InterfaceLock<InterfaceTag> lock;
return read_impl(reg, count);
}
protected:
/* Protected constructor and destructor */
Endpoint(const std::string& info) : endpoint_info_(info) {};
virtual ~Endpoint() = default;
/* write function interface with default implementations which throw */
virtual data_t write_impl(const data_t& /* data */) { throw CommunicationError("write(data) not supported"); }
virtual vector_t write_impl(const vector_t& /* data */) { throw CommunicationError("write(vector) not supported"); }
virtual pair_t write_impl(const pair_t& /* data */) {
throw CommunicationError("write(pair<reg,data>) not supported");
}
virtual vector_t write_impl(const reg_t& /* reg */, const vector_t& /* data */) {
throw CommunicationError("write(reg,vector) not supported");
}
virtual std::vector<pair_t> write_impl(const std::vector<pair_t>& /* data */) {
throw CommunicationError("write(vector<pair<reg,data>>) not supported");
}
/* read function interface with default implementations which throw */
virtual data_t read_impl() { throw CommunicationError("read() not supported"); }
virtual vector_t read_impl(const unsigned int /* length */) {
throw CommunicationError("read(count) not supported");
}
virtual vector_t read_impl(const reg_t& /* reg */, const unsigned int /* length */) {
throw CommunicationError("read(reg,count) not supported");
}
private:
/* Endpoint info, provided by implementations */
std::string endpoint_info_;
};
} // namespace peary::interface
Updated on 2026-01-30 at 22:01:05 +0100