Compare commits

..

3 Commits

Author SHA1 Message Date
92be88ee19 zmq fixed WIP 2020-04-27 18:43:41 +02:00
56bc9c4e08 fix for segfault WIP 2020-04-27 14:00:00 +02:00
edbd70e91a free fix WIP 2020-04-27 13:53:13 +02:00
14 changed files with 983 additions and 1369 deletions

View File

@ -674,6 +674,9 @@ class Detector {
void setRxZmqIP(const IpAddr ip, Positions pos = {});
Result<bool> getClientZmq(Positions pos = {}) const;
void setClientZmq(const bool enable, Positions pos = {});
Result<int> getClientZmqPort(Positions pos = {}) const;
/**

View File

@ -1,157 +0,0 @@
#pragma once
#include <array>
#include <cstddef>
#include <iostream>
#include <numeric>
namespace sls{
template <typename T> class Container3 {
std::array<size_t, 3> shape_{0, 0, 0};
T *data_{nullptr};
public:
Container3(){};
Container3(std::array<size_t, 3> shape)
: Container3(shape[0], shape[1], shape[2]) {}
Container3(std::array<size_t, 3> shape, T value)
: Container3(shape[0], shape[1], shape[2], value) {}
Container3(size_t x, size_t y, size_t z)
: shape_{x, y, z}, data_(new T[size()]{}) {}
Container3(size_t x, size_t y, size_t z, const T &value)
: shape_{x, y, z}, data_(new T[size()]) {
std::fill_n(data_, size(), value);
}
// Copy constructor
Container3(const Container3 &other) {
shape_ = other.shape_;
data_ = new T[size()];
std::copy(other.data_, other.data_ + size(), data_);
}
// Move constructor
Container3(Container3 &&other) {
shape_ = other.shape_;
other.shape_ = {0, 0, 0};
data_ = other.data_;
other.data_ = nullptr;
}
// Copy assignment
Container3 &operator=(const Container3 &other) {
if (this != &other) {
Container3<T> tmp(other);
std::swap(shape_, tmp.shape_);
std::swap(data_, tmp.data_);
}
return *this;
}
// Move assignment
Container3 &operator=(Container3 &&other) {
if (this != &other) {
shape_ = other.shape_;
other.shape_ = {0, 0, 0};
delete[] data_;
data_ = other.data_;
other.data_ = nullptr;
}
return *this;
}
~Container3() { delete[] data_; }
size_t size() const noexcept {
return std::accumulate(std::begin(shape_), std::end(shape_), 1,
std::multiplies<size_t>());
}
size_t size(size_t i) const noexcept { return shape_[i]; }
std::array<size_t, 3> shape() const noexcept { return shape_; }
T *data() noexcept { return data_; }
const T *data() const noexcept { return data_; }
bool is_valid_index(size_t x, size_t y, size_t z) const noexcept {
return x < shape_[0] && y < shape_[1] && z < shape_[2];
}
// Will truncate if other is larger in any dimension
// In the future move object out of other, rename function
void copy_data(const Container3 &other) {
for (size_t i = 0; i < std::min(size(0), other.size(0)); ++i) {
for (size_t j = 0; j < std::min(size(1), other.size(1)); ++j) {
for (size_t k = 0; k < std::min(size(2), other.size(2)); ++k) {
(*this)(i, j, k) = other(i, j, k);
}
}
}
}
void move_data(Container3 &other) {
for (size_t i = 0; i < std::min(size(0), other.size(0)); ++i) {
for (size_t j = 0; j < std::min(size(1), other.size(1)); ++j) {
for (size_t k = 0; k < std::min(size(2), other.size(2)); ++k) {
(*this)(i, j, k) = std::move(other(i, j, k));
}
}
}
}
void resize(size_t x, size_t y, size_t z) {
Container3<T> tmp(x, y, z);
tmp.move_data(*this);
*this = std::move(tmp);
}
T &operator()(size_t x, size_t y, size_t z) noexcept {
return data_[element_offset(x, y, z)];
}
const T &operator()(size_t x, size_t y, size_t z) const noexcept {
return data_[element_offset(x, y, z)];
}
// throws on out of bounds access
const T &at(size_t x, size_t y, size_t z) const {
if (!is_valid_index(x, y, z))
throw std::runtime_error("Index error");
return data_[element_offset(x, y, z)];
}
T &at(size_t x, size_t y, size_t z) {
return const_cast<T &>(
static_cast<const Container3 &>(*this).at(x, y, z));
}
T &operator[](size_t i) { return data_[i]; }
const T &operator[](size_t i) const { return data_[i]; }
T *begin() { return data_; }
T *end() { return data_ + size(); }
void clear(){
*this = Container3<T>();
}
// reference to position, grow if needed, prefer resize and .at()
T &at_can_grow(size_t x, size_t y, size_t z) {
if (!is_valid_index(x, y, z)) {
resize(std::max(x + 1, size(0)), std::max(y + 1, size(1)),
std::max(z + 1, size(2)));
}
return data_[element_offset(x, y, z)];
}
private:
size_t element_offset(size_t x, size_t y, size_t z) const noexcept {
return x * shape_[1] * shape_[2] + y * shape_[2] + z;
}
};
} // namespace sls

View File

@ -9,8 +9,6 @@
#include "Receiver.h"
#include "sls_detector_defs.h"
#include "versionAPI.h"
#include "Parallel.h"
#include "MaskGenerator.h"
#include <fstream>
@ -20,19 +18,25 @@ void freeSharedMemory(int detectorId, int moduleId) {
// single
if (moduleId >= 0) {
SharedMemory<sharedModule> moduleShm(detectorId, moduleId);
int numReceivers = 0, numReceivers2 = 0;
if (moduleShm.IsExisting()) {
moduleShm.OpenSharedMemory();
int numReceivers = 0, numReceivers2 = 0;
if (Module::hasSharedMemoryReceiverList(moduleShm()->shmversion)) {
numReceivers = moduleShm()->numberOfReceivers;
numReceivers2 = moduleShm()->numberOfReceivers2;
}
moduleShm.RemoveSharedMemory();
}
for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, 0, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, 1, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
}
return;
@ -50,19 +54,25 @@ void freeSharedMemory(int detectorId, int moduleId) {
for (int iModule = 0; iModule < numDetectors; ++iModule) {
SharedMemory<sharedModule> moduleShm(detectorId, iModule);
int numReceivers = 0, numReceivers2 = 0;
if (moduleShm.IsExisting()) {
moduleShm.OpenSharedMemory();
int numReceivers = 0, numReceivers2 = 0;
if (Module::hasSharedMemoryReceiverList(moduleShm()->shmversion)) {
numReceivers = moduleShm()->numberOfReceivers;
numReceivers2 = moduleShm()->numberOfReceivers2;
}
moduleShm.RemoveSharedMemory();
}
for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule, 0, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule, 1, iReceiver);
if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory();
}
}
}
}
@ -199,6 +209,7 @@ void Detector::registerDataCallback(void (*func)(detectorData *, uint64_t,
uint32_t, void *),
void *pArg) {
pimpl->registerDataCallback(func, pArg);
setClientZmq(true);
}
bool Detector::getGapPixelsinCallback() const {
@ -567,11 +578,12 @@ Result<int> Detector::getNumberofUDPInterfaces(Positions pos) const {
}
void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
int previouslyClientStreaming = pimpl->enableDataStreamingToClient();
bool prevClientZmq = getClientZmq().tsquash(
"Inconsistent number client zmq sockets");
bool useReceiver = getUseReceiverFlag().squash(false);
bool previouslyReceiverStreaming = false;
bool prevRxZmq = false;
if (useReceiver) {
previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(true);
prevRxZmq = getRxZmqDataStream(pos).squash(true);
}
pimpl->Parallel(&Module::setNumberofUDPInterfaces, pos, n);
// ensure receiver zmq socket ports are multiplied by 2 (2 interfaces)
@ -580,11 +592,11 @@ void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
setRxZmqPort(startingPort, -1);
}
// redo the zmq sockets if enabled
if (previouslyClientStreaming != 0) {
pimpl->enableDataStreamingToClient(0);
pimpl->enableDataStreamingToClient(1);
if (prevClientZmq) {
setClientZmq(false);
setClientZmq(true);
}
if (previouslyReceiverStreaming) {
if (prevRxZmq) {
setRxZmqDataStream(false, pos);
setRxZmqDataStream(true, pos);
}
@ -757,7 +769,15 @@ Result<bool> Detector::getUseReceiverFlag(Positions pos) const {
}
Result<std::string> Detector::getRxHostname(const int udpInterface, Positions pos) const {
return pimpl->getRxHostname(pos, udpInterface);
switch (udpInterface) {
case 1:
return pimpl->Parallel1(&Receiver::getHostname, pos, {});
case 2:
return pimpl->Parallel2(&Receiver::getHostname, pos, {});
default:
throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface));
}
}
void Detector::setRxHostname(const int udpInterface, const std::string &hostname, Positions pos) {
@ -766,21 +786,32 @@ void Detector::setRxHostname(const int udpInterface, const std::string &hostname
void Detector::setRxHostname(const int udpInterface, const std::string &hostname, const int port,
int module_id) {
if (module_id == -1 && size() > 1) {
throw sls::RuntimeError("Cannot set same rx_tcpport and rx_hostname for multiple receivers");
if (module_id == -1) {
if (size() > 1) {
throw sls::RuntimeError("Cannot set same rx_tcpport and rx_hostname for multiple receivers");
} else {
module_id = 0;
}
}
pimpl->configureReceiver(udpInterface, module_id, hostname, port);
}
Result<int> Detector::getRxPort(const int udpInterface, Positions pos) const {
return pimpl->getRxPort(pos, udpInterface);
switch (udpInterface) {
case 1:
return pimpl->Parallel1(&Receiver::getTCPPort, pos, {});
case 2:
return pimpl->Parallel2(&Receiver::getTCPPort, pos, {});
default:
throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface));
}
}
void Detector::setRxPort(const int udpInterface, int port, int module_id) {
if (!pimpl->isReceiverInitialized(udpInterface)) {
pimpl->initReceiver(udpInterface);
}
// return pimpl->setRxPort();
if (udpInterface == 1) {
if (module_id == -1) {
for (int idet = 0; idet < size(); ++idet) {
@ -958,6 +989,8 @@ Result<int> Detector::getRxZmqPort(Positions pos) const {
}
void Detector::setRxZmqPort(int port, int module_id) {
bool previouslyReceiverStreaming =
getRxZmqDataStream({module_id}).squash(false);
if (module_id == -1) {
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel1(&Receiver::setZmqPort, {idet},
@ -967,6 +1000,10 @@ void Detector::setRxZmqPort(int port, int module_id) {
pimpl->Parallel1(&Receiver::setZmqPort, {module_id},
{}, port++);
}
if (previouslyReceiverStreaming) {
setRxZmqDataStream(false, {module_id});
setRxZmqDataStream(true, {module_id});
}
}
Result<IpAddr> Detector::getRxZmqIP(Positions pos) const {
@ -982,11 +1019,25 @@ void Detector::setRxZmqIP(const IpAddr ip, Positions pos) {
}
}
Result<bool> Detector::getClientZmq(Positions pos) const {
return pimpl->Parallel3(&Receiver::getClientZmq);
}
void Detector::setClientZmq(const bool enable, Positions pos) {
try {
pimpl->Parallel3(&Receiver::setClientZmq, enable);
} catch (...) {
throw;
}
}
Result<int> Detector::getClientZmqPort(Positions pos) const {
return pimpl->Parallel1(&Receiver::getClientZmqPort, pos, {});
}
void Detector::setClientZmqPort(int port, int module_id) {
bool prevClientZmq = getClientZmq().tsquash(
"Inconsistent number of client zmq sockets");
if (module_id == -1) {
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel1(&Receiver::setClientZmqPort, {idet},
@ -996,6 +1047,10 @@ void Detector::setClientZmqPort(int port, int module_id) {
pimpl->Parallel1(&Receiver::setClientZmqPort, {module_id},
{}, port);// FIXME: Needs a clientzmqport2
}
if (prevClientZmq) {
setClientZmq(false);
setClientZmq(true);
}
}
Result<IpAddr> Detector::getClientZmqIp(Positions pos) const {
@ -1003,11 +1058,12 @@ Result<IpAddr> Detector::getClientZmqIp(Positions pos) const {
}
void Detector::setClientZmqIp(const IpAddr ip, Positions pos) {
int previouslyClientStreaming = pimpl->enableDataStreamingToClient(-1);
bool prevClientZmq = getClientZmq().tsquash(
"Inconsistent number of client zmq sockets");
pimpl->Parallel3(&Receiver::setClientZmqIP, ip);
if (previouslyClientStreaming != 0) {
pimpl->enableDataStreamingToClient(0);
pimpl->enableDataStreamingToClient(1);
if (prevClientZmq) {
setClientZmq(false);
setClientZmq(true);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,10 @@
#pragma once
#include "Container3.h"
#include "Result.h"
#include "SharedMemory.h"
#include "logger.h"
#include "sls_detector_defs.h"
class ZmqSocket;
class detectorData;
#include <memory>
@ -22,7 +21,7 @@ class detectorData;
#include <future>
#include <numeric>
namespace sls {
namespace sls{
class Module;
class Receiver;
@ -75,23 +74,21 @@ class DetectorImpl : public virtual slsDetectorDefs {
* @param update true to update last user pid, date etc
*/
explicit DetectorImpl(int detector_id = 0, bool verify = true,
bool update = true);
bool update = true);
/**
* Destructor
*/
virtual ~DetectorImpl();
template <class CT> struct NonDeduced { using type = CT; };
template <typename RT, typename... CT>
sls::Result<RT> Parallel(RT (sls::Module::*somefunc)(CT...),
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
@ -118,8 +115,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
@ -146,8 +143,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
@ -171,8 +168,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<int> positions,
typename NonDeduced<CT>::type... Args) const {
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (detectors.size() == 0)
throw sls::RuntimeError("No detectors added");
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(detectors.size());
@ -191,101 +188,467 @@ class DetectorImpl : public virtual slsDetectorDefs {
}
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
return {};
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
return {};
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {}
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {}
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
return {};
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
return {};
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {}
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {}
std::vector<int> dPositions,
std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
// for all , but dont complain if receiver2 doesnt exist
template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) {
typename NonDeduced<CT>::type... Args) {
return {};
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const {
typename NonDeduced<CT>::type... Args) const {
return {};
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
}
template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) {}
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const {}
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
/** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag);
void setAcquiringFlag(bool flag);
/** return detector shared memory ID */
int getDetectorId() const;
/** Free specific shared memory from the command line without creating
* object */
/** Free specific shared memory from the command line without creating object */
static void freeSharedMemory(int detectorId, int moduleId = -1);
/** Free all modules from current multi Id shared memory and delete members
*/
void freeSharedMemory();
/** Free all modules from current multi Id shared memory and delete members */
void freeSharedMemory();
/** Get user details of shared memory */
std::string getUserDetails();
std::string getUserDetails();
bool getInitialChecks() const;
@ -300,45 +663,35 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/
void setVirtualDetectorServers(const int numdet, const int port);
void setHostname(const std::vector<std::string> &name);
void setHostname(const std::vector<std::string> &name);
void setHostname(const std::vector<std::string> &name,
const std::vector<int> &port);
Result<std::string> getRxHostname(Positions pos, int udpInterface);
Result<int> getRxPort(Positions pos, int udpInterface);
const std::vector<int> &port);
int getNumberofReceiversPerModule() const;
void initReceiver(const int udpInterface);
bool isReceiverInitialized(const int udpInterface);
void removeReceivers(const int udpInterface);
void configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname);
void configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port);
void configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname);
void configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port);
/** Gets the total number of detectors */
int size() const;
slsDetectorDefs::xy getNumberOfDetectors() const;
slsDetectorDefs::xy getNumberOfDetectors() const;
slsDetectorDefs::xy getNumberOfChannels() const;
slsDetectorDefs::xy getNumberOfChannels() const;
/** Must be set before setting hostname
* Sets maximum number of channels of all sls detectors */
void setNumberOfChannels(const slsDetectorDefs::xy c);
void setNumberOfChannels(const slsDetectorDefs::xy c);
/** [Eiger][Jungfrau] */
bool getGapPixelsinCallback() const;
/** [Eiger][Jungfrau] */
void setGapPixelsinCallback(const bool enable);
/**
* Enable data streaming to client
* @param enable 0 to disable, 1 to enable, -1 to get the value
* @returns data streaming to client enable
*/
bool enableDataStreamingToClient(int enable = -1);
/**
* register callback for accessing acquisition final data
* @param func function to be called at the end of the acquisition.
@ -368,7 +721,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* index, loops for measurements, calls required call backs.
* @returns OK or FAIL depending on if it already started
*/
int acquire();
int acquire();
/**
* Combines data from all readouts and gives it to the gui
@ -380,7 +733,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* Convert raw file
* [Jungfrau][Ctb] from pof file
* [Mythen3][Gotthard2] from rbf file
* @param fname name of pof/rbf file
* @param fname name of pof/rbf file
* @param fpgasrc pointer in memory to read programming file to
* @returns file size
*/
@ -424,13 +777,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
void updateDetectorSize();
/**
* Create Receiving Data Sockets
* @param destroy is true to destroy all the sockets
* @returns OK or FAIL
*/
int createReceivingDataSockets(const bool destroy = false);
/**
* Reads frames from receiver through a constant socket
* Called during acquire() when call back registered or when using gui
@ -447,8 +793,8 @@ class DetectorImpl : public virtual slsDetectorDefs {
* @param nPixelsy number of pixels in Y axis (updated)
* @returns total data bytes for updated image
*/
int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr,
int &nPixelsx, int &nPixelsy);
int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr,
int &nPixelsx, int &nPixelsy);
void printProgress(double progress);
@ -482,20 +828,10 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<std::unique_ptr<sls::Module>> detectors;
/** pointers to the Receiver structures, each row for a module */
// std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers;
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers;
/** for the second udp port [Eiger][Jungfrau] */
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers2;
sls::Container3<std::unique_ptr<sls::Receiver>> receivers;
// sls::Container3<Receiver> receivers;
/** data streaming (down stream) enabled in client (zmq sckets created) */
bool client_downstream{false};
/** ZMQ Socket - Receiver to Client */
std::vector<std::unique_ptr<ZmqSocket>> zmqSocket;
/** semaphore to let postprocessing thread continue for next
* scan/measurement */
sem_t sem_newRTAcquisition;
@ -523,4 +859,4 @@ class DetectorImpl : public virtual slsDetectorDefs {
void *pCallbackArg{nullptr};
};
} // namespace sls
}//namespace sls

View File

@ -1,59 +0,0 @@
#pragma once
#include "Container3.h"
#include <initializer_list>
#include <vector>
namespace sls{
class MaskGenerator {
enum class OperationMode { ALL, ROW, SINGLE };
OperationMode mode_{OperationMode::ALL};
std::vector<int> idx0; // hack
size_t x_{0};
size_t y_{0};
size_t z_{0};
public:
MaskGenerator(){};
explicit MaskGenerator(size_t i) : mode_(OperationMode::SINGLE), x_(i) {}
MaskGenerator(size_t i, size_t j)
: mode_(OperationMode::SINGLE), x_(i), y_(j) {}
MaskGenerator(size_t i, size_t j, size_t k)
: mode_(OperationMode::SINGLE), x_(i), y_(j), z_(k) {}
explicit MaskGenerator(const std::vector<int> vec)
: mode_(OperationMode::ROW), idx0(vec) {}
explicit MaskGenerator(const std::vector<int> vec, size_t y)
: mode_(OperationMode::ROW), idx0(vec), y_(y) {}
template <typename T> Container3<bool> mask(const Container3<T>& cont) {
return mask(cont.shape());
}
Container3<bool> mask(std::array<size_t, 3> shape) {
Container3<bool> m(shape);
if (idx0.size()== 1 && idx0[0] == -1){
idx0.resize(m.size(0));
std::iota(begin(idx0), end(idx0), 0);
}
switch (mode_) {
case OperationMode::ALL:
for (auto &item : m)
item = true;
break;
case OperationMode::ROW:
for (auto i : idx0) {
m(i, 0, 0) = true;
}
break;
case OperationMode::SINGLE:
m(x_, y_, z_) = true;
break;
}
return m;
}
Container3<bool> mask() { return {}; }
};
} // namespace sls

View File

@ -1,85 +0,0 @@
#pragma once
#include "Container3.h"
#include "Result.h"
#include <future>
#include <vector>
/*
Can't use std::forward<CT>(Args)...) in parallel call since it would
end up moving temporary objects into the first called function
leaving the other ones with moved from args.
*/
namespace experimental {
using sls::Container3;
template <class CT> struct NonDeduced { using type = CT; };
template <typename RT, typename Class, typename... CT>
sls::Result<RT> Parallel(RT (Class::*func)(CT...) const,
const Container3<std::unique_ptr<Class>> &objects,
const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<RT>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, objects[i].get(), Args...));
}
sls::Result<RT> result;
for (auto &f : futures) {
result.push_back(f.get());
}
return result;
}
template <typename RT, typename Class, typename... CT>
sls::Result<RT> Parallel(RT (Class::*func)(CT...),
const Container3<std::unique_ptr<Class>> &objects,
const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<RT>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
sls::Result<RT> result;
for (auto &f : futures) {
result.push_back(f.get());
}
return result;
}
template <typename Class, typename... CT>
void Parallel(void (Class::*func)(CT...) const,
const Container3<std::unique_ptr<Class>> &objects,
const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<void>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
for (auto &f : futures) {
f.get();
}
}
template <typename Class, typename... CT>
void Parallel(void (Class::*func)(CT...),
const Container3<std::unique_ptr<Class>> &objects,
const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<void>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
for (auto &f : futures)
f.get();
}
} // namespace experimental

View File

@ -1,10 +1,13 @@
#include "Receiver.h"
#include "ClientSocket.h"
#include "ZmqSocket.h"
#include "FixedCapacityContainer.h"
#include "string_utils.h"
#include "versionAPI.h"
#include "ToString.h"
#include "container_utils.h"
namespace sls {
// create shm
@ -144,7 +147,7 @@ sls::MacAddr Receiver::configure(slsDetectorDefs::rxParameters arg) {
arg.udpInterfaces = 2;
}
LOG(logDEBUG1)
LOG(logDEBUG)
<< "detType:" << arg.detType << std::endl
<< "detectorSize.x:" << arg.detectorSize.x << std::endl
<< "detectorSize.y:" << arg.detectorSize.y << std::endl
@ -389,6 +392,38 @@ void Receiver::setClientZmqIP(const sls::IpAddr ip) {
shm()->zmqIp = ip;
}
bool Receiver::getClientZmq() const {
return (zmqSocket != nullptr);
}
void Receiver::setClientZmq(const bool enable) {
// destroy
if (!enable) {
if (zmqSocket != nullptr) {
zmqSocket.reset();
}
}
// create
else {
if (zmqSocket == nullptr) {
try {
zmqSocket = sls::make_unique<ZmqSocket>(
shm()->zmqIp.str().c_str(), shm()->zmqPort);
LOG(logINFO) << "Zmq Client[" << indexString << "] at "
<< zmqSocket->GetZmqServerAddress();
} catch(...) {
throw RuntimeError(
"Could not create Zmq socket [" + indexString
+ " on port " + std::to_string(shm()->zmqPort));
}
}
}
}
ZmqSocket* Receiver::getZmqSocket() {
return zmqSocket.get();
}
/** Receiver Parameters */
bool Receiver::getLock() const {

View File

@ -1,62 +1,58 @@
#pragma once
#include "SharedMemory.h"
#include "logger.h"
#include "network_utils.h"
#include "sls_detector_defs.h"
#include "network_utils.h"
#include <map>
#include <memory>
#define RECEIVER_SHMVERSION 0x200421
class ZmqSocket;
namespace sls {
struct sharedReceiver {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
int shmversion;
char hostname[MAX_STR_LENGTH];
int tcpPort;
/** END OF FIXED PATTERN -----------------------------------------------*/
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
int shmversion;
char hostname[MAX_STR_LENGTH];
int tcpPort;
/** END OF FIXED PATTERN -----------------------------------------------*/
int stoppedFlag;
int zmqPort;
sls::IpAddr zmqIp;
int stoppedFlag;
int zmqPort;
sls::IpAddr zmqIp;
};
class Receiver : public virtual slsDetectorDefs {
const int receiverId{0};
const int interfaceId{0};
const int moduleId{0};
std::string indexString;
mutable sls::SharedMemory<sharedReceiver> shm{0, 0, 0, 0};
public:
public:
static size_t getNumReceivers();
// create shm
explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, int tcp_port = 0,
std::string hostname = "", int zmq_port = 0);
int receiver_id, int tcp_port = 0, std::string hostname = "",
int zmq_port = 0);
// open shm
explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, bool verify);
int receiver_id, bool verify);
virtual ~Receiver();
void createIndexString();
/**************************************************
* *
* Configuration *
* *
* ************************************************/
* *
* Configuration *
* *
* ************************************************/
/**
* Free shared memory and delete shared memory structure
* occupied by the sharedReceiver structure
* Is only safe to call if one deletes the Receiver object afterward
* and frees multi shared memory/updates
* thisMultiDetector->numberOfReceivers
*/
* Free shared memory and delete shared memory structure
* occupied by the sharedReceiver structure
* Is only safe to call if one deletes the Receiver object afterward
* and frees multi shared memory/updates
* thisMultiDetector->numberOfReceivers
*/
void freeSharedMemory();
std::string getHostname() const;
void setHostname(const std::string &hostname);
@ -67,10 +63,10 @@ class Receiver : public virtual slsDetectorDefs {
int64_t getSoftwareVersion() const;
/**************************************************
* *
* Acquisition *
* *
* ************************************************/
* *
* Acquisition *
* *
* ************************************************/
void start();
void stop();
slsDetectorDefs::runStatus getStatus() const;
@ -82,10 +78,10 @@ class Receiver : public virtual slsDetectorDefs {
uint64_t getCurrentFrameIndex() const;
/**************************************************
* *
* Network Configuration (Detector<->Receiver) *
* *
* ************************************************/
* *
* Network Configuration (Detector<->Receiver) *
* *
* ************************************************/
sls::MacAddr setUDPIP(const sls::IpAddr ip);
void setUDPPort(const int udpport);
int64_t getUDPSocketBufferSize() const;
@ -93,10 +89,10 @@ class Receiver : public virtual slsDetectorDefs {
int64_t getRealUDPSocketBufferSize() const;
/**************************************************
* *
* ZMQ Streaming Parameters (Receiver<->Client)*
* *
* ************************************************/
* *
* ZMQ Streaming Parameters (Receiver<->Client)*
* *
* ************************************************/
bool getZmq() const;
void setZmq(const bool enable);
int getZmqFrequency() const;
@ -104,7 +100,7 @@ class Receiver : public virtual slsDetectorDefs {
void setZmqFrequency(const int freq);
int getZmqTimer() const;
void setZmqTimer(const int time_in_ms = 200);
int getZmqPort() const;
int getZmqPort() const;
void setZmqPort(int port);
sls::IpAddr getZmqIP() const;
void setZmqIP(const sls::IpAddr ip);
@ -112,16 +108,19 @@ class Receiver : public virtual slsDetectorDefs {
void setClientZmqPort(const int port);
sls::IpAddr getClientZmqIP() const;
void setClientZmqIP(const sls::IpAddr ip);
bool getClientZmq() const;
void setClientZmq(const bool enable);
ZmqSocket* getZmqSocket();
/**************************************************
* *
* Receiver Parameters *
* *
* ************************************************/
* *
* Receiver Parameters *
* *
* ************************************************/
bool getLock() const;
void setLock(const bool lock);
sls::IpAddr getLastClientIP() const;
void exitServer();
void exitServer();
bool getDeactivatedPaddingMode() const;
void setDeactivatedPaddingMode(const bool padding);
@ -137,10 +136,10 @@ class Receiver : public virtual slsDetectorDefs {
void setSilentMode(const bool value);
/**************************************************
* *
* File *
* *
* ************************************************/
* *
* File *
* *
* ************************************************/
std::string getFilePath() const;
void setFilePath(const std::string &path);
std::string getFileName() const;
@ -161,10 +160,10 @@ class Receiver : public virtual slsDetectorDefs {
void setFileOverWrite(const bool value);
/**************************************************
* *
* Detector Parameters *
* *
* ************************************************/
* *
* Detector Parameters *
* *
* ************************************************/
void setNumberOfFrames(const int64_t value);
void setNumberOfTriggers(const int64_t value);
void setNumberOfBursts(const int64_t value);
@ -186,7 +185,7 @@ class Receiver : public virtual slsDetectorDefs {
void clearROI();
std::vector<int> getDbitList() const;
/** digital data bits enable (CTB only) */
void setDbitList(const std::vector<int> &list);
void setDbitList(const std::vector<int>& list);
int getDbitOffset() const;
/** Set digital data offset in bytes (CTB only) */
void setDbitOffset(const int value);
@ -195,22 +194,22 @@ class Receiver : public virtual slsDetectorDefs {
void setCounterMask(const uint32_t mask);
/**************************************************
* *
* Json *
* *
* ************************************************/
* *
* Json *
* *
* ************************************************/
std::map<std::string, std::string> getAdditionalJsonHeader() const;
/** empty vector deletes entire additional json header */
void setAdditionalJsonHeader(
const std::map<std::string, std::string> &jsonHeader);
void setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader);
std::string getAdditionalJsonParameter(const std::string &key) const;
/** Sets the value for the additional json header parameter key if found,
/** Sets the value for the additional json header parameter key if found,
else append it. If value empty, then deletes parameter */
void setAdditionalJsonParameter(const std::string &key,
const std::string &value);
void setAdditionalJsonParameter(const std::string &key, const std::string &value);
private:
private:
void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size);
@ -235,9 +234,11 @@ class Receiver : public virtual slsDetectorDefs {
template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
template <typename Ret> Ret sendToReceiver(int fnum);
template <typename Ret>
Ret sendToReceiver(int fnum);
template <typename Ret> Ret sendToReceiver(int fnum) const;
template <typename Ret>
Ret sendToReceiver(int fnum) const;
template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args);
@ -246,6 +247,12 @@ class Receiver : public virtual slsDetectorDefs {
Ret sendToReceiver(int fnum, const Arg &args) const;
void checkVersionCompatibility();
const int receiverId{0};
const int interfaceId{0};
const int moduleId{0};
std::string indexString;
mutable sls::SharedMemory<sharedReceiver> shm{0, 0, 0, 0};
std::unique_ptr<ZmqSocket> zmqSocket;
};
} // namespace sls
} // sls

View File

@ -13,9 +13,6 @@ target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-global.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Result.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Container3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-MaskGenerator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Receiver.cpp
)
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")

View File

@ -144,10 +144,10 @@ TEST_CASE("rx_printconfig", "[.cmd][.rx][.new]") {
/* Receiver Config */
// TEST_CASE("rx_hostname", "[.cmd][.rx][.new]") {
// Detector det;
// CmdProxy proxy(&det);
// auto prev_val = det.getRxHostname();
TEST_CASE("rx_hostname", "[.cmd][.rx][.new]") {
Detector det;
CmdProxy proxy(&det);
auto prev_val = det.getRxHostname();
// Cannot set rx_hostname (will reset parameters in rxr and no shm variables to update)
// {
@ -168,37 +168,37 @@ TEST_CASE("rx_printconfig", "[.cmd][.rx][.new]") {
// for (int i = 0; i != det.size(); ++i) {
// det.setRxHostname(prev_val[i], {i});
// }
// {
// std::ostringstream oss;
// proxy.Call("rx_hostname", {}, 0, GET, oss);
// REQUIRE(oss.str() == "rx_hostname " + prev_val[0] + "\n");
// }
// }
{
std::ostringstream oss;
proxy.Call("rx_hostname", {}, 0, GET, oss);
REQUIRE(oss.str() == "rx_hostname " + prev_val[0] + "\n");
}
}
// TEST_CASE("rx_tcpport", "[.cmd][.rx][.new]") {
// Detector det;
// CmdProxy proxy(&det);
// auto prev_val = det.getRxPort();
TEST_CASE("rx_tcpport", "[.cmd][.rx][.new]") {
Detector det;
CmdProxy proxy(&det);
auto prev_val = det.getRxPort();
// int port = 3500;
// proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
// for (int i = 0; i != det.size(); ++i) {
// std::ostringstream oss;
// proxy.Call("rx_tcpport", {}, i, GET, oss);
// REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
// }
// REQUIRE_THROWS(proxy.Call("rx_tcpport", {"15"}, -1, PUT));
// port = 5754;
// proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
// for (int i = 0; i != det.size(); ++i) {
// std::ostringstream oss;
// proxy.Call("rx_tcpport", {}, i, GET, oss);
// REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
// }
// for (int i = 0; i != det.size(); ++i) {
// det.setRxPort(prev_val[i], i);
// }
// }
int port = 3500;
proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
for (int i = 0; i != det.size(); ++i) {
std::ostringstream oss;
proxy.Call("rx_tcpport", {}, i, GET, oss);
REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
}
REQUIRE_THROWS(proxy.Call("rx_tcpport", {"15"}, -1, PUT));
port = 5754;
proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
for (int i = 0; i != det.size(); ++i) {
std::ostringstream oss;
proxy.Call("rx_tcpport", {}, i, GET, oss);
REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
}
for (int i = 0; i != det.size(); ++i) {
det.setRxPort(prev_val[i], i);
}
}
TEST_CASE("rx_fifodepth", "[.cmd][.rx][.new]") {
Detector det;

View File

@ -1,330 +0,0 @@
#include "catch.hpp"
#include "Container3.h"
using sls::Container3;
TEST_CASE("Default construction gives container of size 0") {
Container3<int> c;
CHECK(c.size() == 0);
CHECK(c.size(0) == 0);
CHECK(c.size(1) == 0);
CHECK(c.size(2) == 0);
}
TEST_CASE("Construct container with size") {
Container3<int> c(3, 4, 5);
CHECK(c.size() == 3 * 4 * 5);
CHECK(c.size(0) == 3);
CHECK(c.size(1) == 4);
CHECK(c.size(2) == 5);
}
TEST_CASE("Constructor with default value") {
constexpr int val = 7;
Container3<int> c({1, 1, 5}, val);
for (size_t i = 0; i < c.size(); ++i) {
CHECK(c[i] == val);
}
}
TEST_CASE("Container3 can be iterated with range for") {
constexpr int val = 7;
Container3<int> c({1, 1, 5}, val);
for (const auto& item : c) {
CHECK(item == val);
}
}
TEST_CASE(
"() gives access to an element for both const and non const objects") {
Container3<int> c{1, 1, 1};
CHECK(c(0, 0, 0) == 0);
const Container3<int> c2{1, 1, 1};
CHECK(c2(0, 0, 0) == 0);
}
TEST_CASE("() can be used to modify object") {
Container3<int> c{1, 1, 1};
c(0, 0, 0) = 7;
CHECK(c(0, 0, 0) == 7);
}
TEST_CASE("at() can be used to modify object") {
Container3<int> c{1, 1, 1};
c.at(0, 0, 0) = 7;
CHECK(c(0, 0, 0) == 7);
}
TEST_CASE("at throws outsize range for both const and non const objects") {
Container3<int> c{1, 1, 1};
const Container3<double> c2{1, 1, 1};
CHECK_THROWS(c.at(5, 5, 5));
CHECK_THROWS(c2.at(5, 5, 5));
}
TEST_CASE("Set values") {
Container3<int> c(2, 3, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Check if index is valid") {
Container3<int> c(2, 3, 4);
CHECK(c.is_valid_index(1,1,1));
CHECK(c.is_valid_index(1,2,3));
CHECK(c.is_valid_index(1,2,3));
CHECK_FALSE(c.is_valid_index(1,7,1));
CHECK_FALSE(c.is_valid_index(1,1,4));
CHECK_FALSE(c.is_valid_index(3,1,1));
}
TEST_CASE("Copy data from one container to another") {
Container3<int> c(2, 1, 2);
for (size_t i = 0; i < c.size(); ++i) {
c[i] = i;
}
Container3<int> c2(3, 3, 3);
c2.copy_data(c);
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
CHECK(c2(i, j, k) == c(i, j, k));
}
}
}
}
TEST_CASE("Copy assignment copies values") {
Container3<int> c(2, 3, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
Container3<int> c2;
c2 = c;
count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c2(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Copy constructor copies values") {
Container3<int> c(18, 23, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
Container3<int> c2 = c;
count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c2(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Copy assignment create disjoint objects") {
Container3<int> c(2, 3, 4);
Container3<int> c2;
c2 = c;
c2(1, 1, 1) = 72;
CHECK(c2(1, 1, 1) == 72);
CHECK(c(1, 1, 1) != 72);
}
TEST_CASE("Move constructor") {
Container3<int> c(2, 3, 4);
// explicit move only for testing
Container3<int> c2(std::move(c));
// Moved from object is in an ok state
CHECK(c.data() == nullptr);
for (size_t i = 0; i < 3; ++i) {
CHECK(c.size(i) == 0);
}
// new object has the correct size and owns some data
CHECK(c2.data() != nullptr);
CHECK(c2.size(0) == 2);
CHECK(c2.size(1) == 3);
CHECK(c2.size(2) == 4);
}
TEST_CASE("Move assignment ") {
Container3<int> c(2, 3, 4);
Container3<int> c2(5, 5, 5);
c2 = std::move(c);
// Moved from object is in an ok state
CHECK(c.data() == nullptr);
for (size_t i = 0; i < 3; ++i) {
CHECK(c.size(i) == 0);
}
// new object has the correct size and owns some data
CHECK(c2.data() != nullptr);
CHECK(c2.size(0) == 2);
CHECK(c2.size(1) == 3);
CHECK(c2.size(2) == 4);
}
TEST_CASE("Resize to a larger size") {
Container3<int> c(2, 3, 4);
// Assign values
auto shape = c.shape();
CHECK(shape == std::array<size_t, 3>{2,3,4});
size_t count = 0;
for (size_t i = 0; i < shape[0]; ++i) {
for (size_t j = 0; j < shape[1]; ++j) {
for (size_t k = 0; k < shape[2]; ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
++count;
}
}
}
c.resize(3, 4, 5);
CHECK(c.shape() == std::array<size_t, 3>{3,4,5});
// Values should remain the same in the old region
count = 0;
for (size_t i = 0; i < shape[0]; ++i) {
for (size_t j = 0; j < shape[1]; ++j) {
for (size_t k = 0; k < shape[2]; ++k) {
CHECK(c(i, j, k) == count);
++count;
}
}
}
// Default constructed values outsize
CHECK(c(2, 2, 2) == 0);
CHECK(c(2, 3, 2) == 0);
}
TEST_CASE("Inserting values outside range with a empty receiver") {
Container3<int> c;
c.at_can_grow(0, 0, 0) = 5;
CHECK(c(0, 0, 0) == 5);
CHECK(c.size() == 1);
CHECK(c.size(0) == 1);
CHECK(c.size(1) == 1);
CHECK(c.size(2) == 1);
c.at_can_grow(0, 0, 1) = 6;
CHECK(c.size() == 2);
CHECK(c.size(0) == 1);
CHECK(c.size(1) == 1);
CHECK(c.size(2) == 2);
}
TEST_CASE("Inserting a value outside of the current size") {
Container3<int> c{1, 2, 3};
for (size_t i = 0; i < c.size(); ++i) {
c[i] = i;
}
Container3<int> copy;
copy = c;
c.at_can_grow(2, 2, 2) = 7;
CHECK(c.size(0) == 3);
CHECK(c.size(1) == 3);
CHECK(c.size(2) == 3);
for (size_t i = 0; i < copy.size(0); ++i) {
for (size_t j = 0; j < copy.size(0); ++j) {
for (size_t k = 0; k < copy.size(0); ++k) {
CHECK(copy(i, j, k) == c(i, j, k));
}
}
}
}
TEST_CASE("Clear sets size to zero and clears memory"){
Container3<int> c(5,5,5);
CHECK(c.shape() == std::array<size_t, 3>{5,5,5});
c.clear();
CHECK(c.shape() == std::array<size_t, 3>{0,0,0});
CHECK(c.size() == 0);
}
TEST_CASE("Put unique pointer in Container3"){
Container3<std::unique_ptr<int>> c(3,1,1);
c(0,0,0) = std::unique_ptr<int>(new int);
CHECK(c(0,0,0) != nullptr);
CHECK(c(1,0,0) == nullptr);
CHECK(c(2,0,0) == nullptr);
*c(0,0,0) = 5;
CHECK(*c(0,0,0) == 5);
}
TEST_CASE("Resize with unique ptr"){
Container3<std::unique_ptr<int>> c(2,1,1);
c(1,0,0) = std::unique_ptr<int>(new int);
*c(1,0,0) = 7;
c.resize(3,1,1);
CHECK(c.size() == 3);
CHECK(*c(1,0,0) == 7);
}

View File

@ -1,99 +0,0 @@
#include "catch.hpp"
#include "MaskGenerator.h"
using sls::MaskGenerator;
using sls::Container3;
TEST_CASE("Default construction gives an mask of size 0") {
auto m = MaskGenerator().mask();
CHECK(m.shape() == std::array<size_t, 3>{0, 0, 0});
CHECK(m.size() == 0);
}
TEST_CASE("Default behaviour with shape is all true and same shape") {
Container3<int> c{1, 2, 3};
auto m = MaskGenerator().mask(c.shape());
CHECK(m.shape() == std::array<size_t, 3>{1, 2, 3});
for (auto &i : m)
CHECK(i == true);
}
TEST_CASE("With std::vector we give back the first index and 0, 0") {
Container3<int> rec{14, 1, 3};
auto m = MaskGenerator(std::vector<int>{0, 3, 5}).mask(rec.shape());
CHECK(m.shape() == std::array<size_t, 3>{14, 1, 3});
CHECK(m(0, 0, 0) == true);
CHECK(m(3, 0, 0) == true);
CHECK(m(5, 0, 0) == true);
std::vector<int> positions(rec.size(0));
std::iota(begin(positions), end(positions), 0);
positions.erase(std::remove(positions.begin(), positions.end(), 0),
positions.end());
positions.erase(std::remove(positions.begin(), positions.end(), 3),
positions.end());
positions.erase(std::remove(positions.begin(), positions.end(), 5),
positions.end());
for (auto i : positions) {
for (size_t j = 0; j < rec.size(1); ++j) {
for (size_t k = 0; k < rec.size(2); ++k) {
REQUIRE(m(i, j, k) == false);
}
}
}
}
TEST_CASE("With single number we get that detector x,0,0") {
Container3<int> rec{2, 2, 1};
auto m = MaskGenerator(1).mask(rec);
CHECK(m(1, 0, 0) == true);
CHECK(m(1, 1, 0) == false);
CHECK(m(0, 1, 0) == false);
CHECK(m(0, 0, 0) == false);
}
TEST_CASE("With two numbers we get x,y,0") {
Container3<int> rec{2, 2, 1};
auto m = MaskGenerator(1, 1).mask(rec);
CHECK(m(1, 1, 0) == true);
CHECK(m(1, 0, 0) == false);
CHECK(m(0, 1, 0) == false);
CHECK(m(0, 0, 0) == false);
}
TEST_CASE("With three numbers we get x,y,z") {
Container3<int> rec{9, 7, 5};
auto m = MaskGenerator(3, 4, 1).mask(rec);
REQUIRE(m.shape() == rec.shape());
REQUIRE(m(3, 4, 1) == true);
for (size_t i = 0; i < rec.size(0); ++i) {
for (size_t j = 0; j < rec.size(1); ++j) {
for (size_t k = 0; k < rec.size(2); ++k) {
if (!(i == 3 && j == 4 && k == 1)) {
REQUIRE(m(i, j, k) == false);
}
}
}
}
}
TEST_CASE("Passing in -1 as the only element in the vector gives all rows"){
Container3<int> r{3,3,3};
std::vector<int> vec{-1};
auto m = MaskGenerator(vec, 0).mask(r);
REQUIRE(m.shape() == std::array<size_t, 3>{3,3,3});
CHECK(m(0,0,0) == true);
CHECK(m(1,0,0) == true);
CHECK(m(2,0,0) == true);
CHECK(m(0,1,0) == false);
CHECK(m(0,2,0) == false);
CHECK(m(0,0,1) == false);
}

View File

@ -1,10 +0,0 @@
#include "catch.hpp"
#include "Container3.h"
#include "Receiver.h"
using sls::Receiver;
// TEST_CASE("Receiver can be default constructed"){
// }