Dev/proper free (#1005)

* first draft of fixing the free function available within the class

* removed class member function freeSharedmemory for both Detector and Module; made the free function freeSharedmemory accessible to python interface; setHostname if there is already a module in shm will recreate the Detector object while freeing shm completely and keeping detsize and intitialchecks (previous commit), sethostname called from DetectorClass in virtual command to have one point of entry (previous commit), testing Module class frees shared memory using free function

* Detector class: added copy and move constructor and assignmentoperators due to explicit destructor (DetectorImpl fwd declared), DetectorImpl class: included ZmqSocket to remove destructor (should not be virtual in any case), Module class: removed explciit destructor to allow compiler generated constructor and operators

* formatting

* minor fix for readme autocomplete

* updated client version date
This commit is contained in:
maliakal_d 2024-10-21 16:25:07 +02:00 committed by GitHub
parent 76ab0228ac
commit 6add9aad5d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 71 additions and 120 deletions

View File

@ -21,11 +21,13 @@ void init_det(py::module &m) {
using sls::Positions; using sls::Positions;
using sls::Result; using sls::Result;
m.def("freeSharedMemory",
(void (*)(const int, const int)) & sls::freeSharedMemory,
py::arg() = 0, py::arg() = -1);
py::class_<Detector> CppDetectorApi(m, "CppDetectorApi"); py::class_<Detector> CppDetectorApi(m, "CppDetectorApi");
CppDetectorApi.def(py::init<int>()); CppDetectorApi.def(py::init<int>());
CppDetectorApi.def("freeSharedMemory",
(void (Detector::*)()) & Detector::freeSharedMemory);
CppDetectorApi.def("loadConfig", CppDetectorApi.def("loadConfig",
(void (Detector::*)(const std::string &)) & (void (Detector::*)(const std::string &)) &
Detector::loadConfig, Detector::loadConfig,

View File

@ -18,6 +18,8 @@ void init_det(py::module &m) {
using sls::Positions; using sls::Positions;
using sls::Result; using sls::Result;
m.def("freeSharedMemory", (void (*)(const int, const int)) &sls::freeSharedMemory, py::arg() = 0, py::arg() = -1);
py::class_<Detector> CppDetectorApi(m, "CppDetectorApi"); py::class_<Detector> CppDetectorApi(m, "CppDetectorApi");
CppDetectorApi.def(py::init<int>()); CppDetectorApi.def(py::init<int>());

View File

@ -28,7 +28,7 @@ The dump.json is the AST of the file `slsDetectorPackage/slsSupportLib/src/ToStr
```sh ```sh
# to generate the dump.json file # to generate the dump.json file
cd slsSupportLib/src cd slsSupportLib/src
clang++ -Xclang -ast-dump=json -Xclang -ast-dump-filter -Xclang StringTo -c ToString.cpp -I ../include/ -std=gnu++11 > ../../slsDetectorSoftware/generator/autocomplete/dump.json clang++ -Xclang -ast-dump=json -Xclang -ast-dump-filter -Xclang StringTo -c ToString.cpp -I ../include/ -std=gnu++11 > ../../slsDetectorSoftware/generator/autocomplete/dump.json
# clang version used: 14.0.0-1ubuntu1.1 # clang version used: 14.0.0-1ubuntu1.1
``` ```

View File

@ -20,7 +20,7 @@ class IpAddr;
// Free function to avoid dependence on class // Free function to avoid dependence on class
// and avoid the option to free another objects // and avoid the option to free another objects
// shm by mistake // shm by mistake
void freeSharedMemory(int detectorIndex, int moduleIndex = -1); void freeSharedMemory(const int detectorIndex = 0, const int moduleIndex = -1);
/** /**
* \class Detector * \class Detector
@ -46,9 +46,13 @@ class Detector {
Detector(int shm_id = 0); Detector(int shm_id = 0);
~Detector(); ~Detector();
/** Free the shared memory of this detector and all modules // Disable copy since SharedMemory object is unique in DetectorImpl
belonging to it */ Detector(const Detector &other) = delete;
void freeSharedMemory(); Detector &operator=(const Detector &other) = delete;
// Move constructor and assignment operator
Detector(Detector &&other) noexcept;
Detector &operator=(Detector &&other) noexcept;
/** Frees shared memory before loading configuration file. Set up once /** Frees shared memory before loading configuration file. Set up once
normally */ normally */

View File

@ -23,7 +23,7 @@
namespace sls { namespace sls {
void freeSharedMemory(int detectorIndex, int moduleIndex) { void freeSharedMemory(const int detectorIndex, const int moduleIndex) {
// single module // single module
if (moduleIndex >= 0) { if (moduleIndex >= 0) {
@ -34,10 +34,10 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) {
return; return;
} }
// detector - multi module - get number of detectors from shm
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numDetectors = 0; int numDetectors = 0;
// detector - multi module - get number of detectors from shm
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
if (detectorShm.exists()) { if (detectorShm.exists()) {
detectorShm.openSharedMemory(false); detectorShm.openSharedMemory(false);
numDetectors = detectorShm()->totalNumberOfModules; numDetectors = detectorShm()->totalNumberOfModules;
@ -58,15 +58,19 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) {
using defs = slsDetectorDefs; using defs = slsDetectorDefs;
Detector::Detector(int shm_id) : pimpl(make_unique<DetectorImpl>(shm_id)) {} Detector::Detector(int shm_id) : pimpl(make_unique<DetectorImpl>(shm_id)) {}
Detector::~Detector() = default; Detector::~Detector() = default;
// Move constructor
Detector::Detector(Detector &&other) noexcept = default;
// Move assignment operator
Detector &Detector::operator=(Detector &&other) noexcept = default;
// Configuration // Configuration
void Detector::freeSharedMemory() { pimpl->freeSharedMemory(); }
void Detector::loadConfig(const std::string &fname) { void Detector::loadConfig(const std::string &fname) {
int shm_id = getShmId(); int shm_id = getShmId();
freeSharedMemory(); freeSharedMemory(shm_id);
pimpl = make_unique<DetectorImpl>(shm_id); pimpl = make_unique<DetectorImpl>(shm_id);
LOG(logINFO) << "Loading configuration file: " << fname; LOG(logINFO) << "Loading configuration file: " << fname;
loadParameters(fname); loadParameters(fname);
@ -105,13 +109,30 @@ Result<std::string> Detector::getHostname(Positions pos) const {
} }
void Detector::setHostname(const std::vector<std::string> &hostname) { void Detector::setHostname(const std::vector<std::string> &hostname) {
if (pimpl->hasModulesInSharedMemory()) {
LOG(logWARNING) << "There are already module(s) in shared memory."
"Freeing Shared memory now.";
auto numChannels = getDetectorSize();
auto initialChecks = getInitialChecks();
freeSharedMemory(getShmId());
pimpl = make_unique<DetectorImpl>(getShmId());
setDetectorSize(numChannels);
setInitialChecks(initialChecks);
}
pimpl->setHostname(hostname); pimpl->setHostname(hostname);
} }
void Detector::setVirtualDetectorServers(int numServers, void Detector::setVirtualDetectorServers(int numServers,
uint16_t startingPort) { uint16_t startingPort) {
validatePortRange(startingPort, numServers * 2); validatePortRange(startingPort, numServers * 2);
pimpl->setVirtualDetectorServers(numServers, startingPort);
std::vector<std::string> hostnames;
for (int i = 0; i < numServers; ++i) {
// * 2 is for control and stop port
hostnames.push_back(std::string("localhost:") +
std::to_string(startingPort + i * 2));
}
setHostname(hostnames);
} }
int Detector::getShmId() const { return pimpl->getDetectorIndex(); } int Detector::getShmId() const { return pimpl->getDetectorIndex(); }

View File

@ -37,8 +37,6 @@ DetectorImpl::DetectorImpl(int detector_index, bool verify, bool update)
setupDetector(verify, update); setupDetector(verify, update);
} }
DetectorImpl::~DetectorImpl() = default;
void DetectorImpl::setupDetector(bool verify, bool update) { void DetectorImpl::setupDetector(bool verify, bool update) {
initSharedMemory(verify); initSharedMemory(verify);
initializeMembers(verify); initializeMembers(verify);
@ -59,51 +57,6 @@ void DetectorImpl::setAcquiringFlag(bool flag) { shm()->acquiringFlag = flag; }
int DetectorImpl::getDetectorIndex() const { return detectorIndex; } int DetectorImpl::getDetectorIndex() const { return detectorIndex; }
void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
// single
if (detPos >= 0) {
SharedMemory<sharedModule> moduleShm(detectorIndex, detPos);
if (moduleShm.exists()) {
moduleShm.removeSharedMemory();
}
return;
}
// multi - get number of modules from shm
SharedMemory<sharedDetector> detectorShm(detectorIndex, -1);
int numModules = 0;
if (detectorShm.exists()) {
detectorShm.openSharedMemory(false);
numModules = detectorShm()->totalNumberOfModules;
detectorShm.removeSharedMemory();
}
for (int i = 0; i < numModules; ++i) {
SharedMemory<sharedModule> moduleShm(detectorIndex, i);
moduleShm.removeSharedMemory();
}
SharedMemory<CtbConfig> ctbShm(detectorIndex, -1, CtbConfig::shm_tag());
if (ctbShm.exists())
ctbShm.removeSharedMemory();
}
void DetectorImpl::freeSharedMemory() {
zmqSocket.clear();
for (auto &module : modules) {
module->freeSharedMemory();
}
modules.clear();
// clear detector shm
shm.removeSharedMemory();
client_downstream = false;
if (ctb_shm.exists())
ctb_shm.removeSharedMemory();
}
std::string DetectorImpl::getUserDetails() { std::string DetectorImpl::getUserDetails() {
if (modules.empty()) { if (modules.empty()) {
return std::string("none"); return std::string("none");
@ -242,24 +195,11 @@ std::string DetectorImpl::exec(const char *cmd) {
return result; return result;
} }
void DetectorImpl::setVirtualDetectorServers(const int numdet, bool DetectorImpl::hasModulesInSharedMemory() {
const uint16_t port) { return (shm.exists() && shm()->totalNumberOfModules > 0);
std::vector<std::string> hostnames;
for (int i = 0; i < numdet; ++i) {
// * 2 is for control and stop port
hostnames.push_back(std::string("localhost:") +
std::to_string(port + i * 2));
}
setHostname(hostnames);
} }
void DetectorImpl::setHostname(const std::vector<std::string> &name) { void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// do not free always to allow the previous detsize/ initialchecks command
if (shm.exists() && shm()->totalNumberOfModules != 0) {
LOG(logWARNING) << "There are already module(s) in shared memory."
"Freeing Shared memory now.";
freeSharedMemory();
}
// could be called after freeing shm from API // could be called after freeing shm from API
if (!shm.exists()) { if (!shm.exists()) {
setupDetector(); setupDetector();
@ -292,8 +232,8 @@ void DetectorImpl::addModule(const std::string &name) {
// gotthard cannot have more than 2 modules (50um=1, 25um=2 // gotthard cannot have more than 2 modules (50um=1, 25um=2
if ((type == GOTTHARD || type == GOTTHARD2) && modules.size() > 2) { if ((type == GOTTHARD || type == GOTTHARD2) && modules.size() > 2) {
freeSharedMemory(); throw RuntimeError("Gotthard cannot have more than 2 modules. Please "
throw RuntimeError("Gotthard cannot have more than 2 modules"); "free the shared memory and start again.");
} }
auto pos = modules.size(); auto pos = modules.size();

View File

@ -5,6 +5,7 @@
#include "CtbConfig.h" #include "CtbConfig.h"
#include "SharedMemory.h" #include "SharedMemory.h"
#include "sls/Result.h" #include "sls/Result.h"
#include "sls/ZmqSocket.h"
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
@ -19,7 +20,6 @@
namespace sls { namespace sls {
class ZmqSocket;
class detectorData; class detectorData;
class Module; class Module;
@ -79,11 +79,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
explicit DetectorImpl(int detector_index = 0, bool verify = true, explicit DetectorImpl(int detector_index = 0, bool verify = true,
bool update = true); bool update = true);
/**
* Destructor
*/
virtual ~DetectorImpl();
template <class CT> struct NonDeduced { using type = CT; }; template <class CT> struct NonDeduced { using type = CT; };
template <typename RT, typename... CT> template <typename RT, typename... CT>
Result<RT> Parallel(RT (Module::*somefunc)(CT...), Result<RT> Parallel(RT (Module::*somefunc)(CT...),
@ -198,14 +193,6 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** return detector index in shared memory */ /** return detector index in shared memory */
int getDetectorIndex() const; int getDetectorIndex() const;
/** Free specific shared memory from the command line without creating
* object */
static void freeSharedMemory(int detectorIndex, int detPos = -1);
/** Free all modules from current multi Id shared memory and delete members
*/
void freeSharedMemory();
/** Get user details of shared memory */ /** Get user details of shared memory */
std::string getUserDetails(); std::string getUserDetails();
@ -215,12 +202,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* default enabled */ * default enabled */
void setInitialChecks(const bool value); void setInitialChecks(const bool value);
/** bool hasModulesInSharedMemory();
* Connect to Virtual Detector Servers at local host
* @param numdet number of modules
* @param port starting port number
*/
void setVirtualDetectorServers(const int numdet, const uint16_t port);
/** Sets the hostname of all sls modules in shared memory and updates /** Sets the hostname of all sls modules in shared memory and updates
* local cache */ * local cache */

View File

@ -53,14 +53,6 @@ Module::Module(int det_id, int module_index, bool verify)
initSharedMemory(type, det_id, verify); initSharedMemory(type, det_id, verify);
} }
Module::~Module() = default;
void Module::freeSharedMemory() {
if (shm.exists()) {
shm.removeSharedMemory();
}
}
bool Module::isFixedPatternSharedMemoryCompatible() const { bool Module::isFixedPatternSharedMemoryCompatible() const {
return (shm()->shmversion >= MODULE_SHMAPIVERSION); return (shm()->shmversion >= MODULE_SHMAPIVERSION);
} }

View File

@ -75,12 +75,6 @@ class Module : public virtual slsDetectorDefs {
verify is if shared memory version matches existing one */ verify is if shared memory version matches existing one */
explicit Module(int det_id = 0, int module_index = 0, bool verify = true); explicit Module(int det_id = 0, int module_index = 0, bool verify = true);
virtual ~Module();
/** Frees shared memory and deletes shared memory structure
Safe to call only if detector shm also deleted or its numberOfModules is
updated */
void freeSharedMemory();
bool isFixedPatternSharedMemoryCompatible() const; bool isFixedPatternSharedMemoryCompatible() const;
std::string getHostname() const; std::string getHostname() const;

View File

@ -33,6 +33,7 @@ target_sources(tests PRIVATE
target_include_directories(tests target_include_directories(tests
PUBLIC PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>" "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>"
"$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include/sls>"
PRIVATE PRIVATE
${SLS_INTERNAL_RAPIDJSON_DIR} ${SLS_INTERNAL_RAPIDJSON_DIR}
) )

View File

@ -1,5 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-or-other // SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package // Copyright (C) 2021 Contributors to the SLS Detector Package
#include "Detector.h"
#include "Module.h" #include "Module.h"
#include "SharedMemory.h" #include "SharedMemory.h"
#include "catch.hpp" #include "catch.hpp"
@ -10,7 +11,9 @@ using dt = slsDetectorDefs::detectorType;
TEST_CASE("Construction with a defined detector type") { TEST_CASE("Construction with a defined detector type") {
Module m(dt::EIGER); Module m(dt::EIGER);
REQUIRE(m.getDetectorType() == dt::EIGER); REQUIRE(m.getDetectorType() == dt::EIGER);
m.freeSharedMemory(); // clean up freeSharedMemory(0, 0); // clean up
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
TEST_CASE("Read back detector type from shm") { TEST_CASE("Read back detector type from shm") {
@ -23,7 +26,9 @@ TEST_CASE("Read back detector type from shm") {
// Now both objects point to the same shm so we can only // Now both objects point to the same shm so we can only
// free one! // free one!
m2.freeSharedMemory(); freeSharedMemory(0, 0);
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
TEST_CASE("Is shm fixed pattern shm compatible") { TEST_CASE("Is shm fixed pattern shm compatible") {
@ -41,25 +46,33 @@ TEST_CASE("Is shm fixed pattern shm compatible") {
// Should fail since version is set to 0 // Should fail since version is set to 0
REQUIRE(m.isFixedPatternSharedMemoryCompatible() == false); REQUIRE(m.isFixedPatternSharedMemoryCompatible() == false);
m.freeSharedMemory(); freeSharedMemory(0, 0);
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
TEST_CASE("Get default control port") { TEST_CASE("Get default control port") {
Module m(dt::MYTHEN3); Module m(dt::MYTHEN3);
REQUIRE(m.getControlPort() == 1952); REQUIRE(m.getControlPort() == 1952);
m.freeSharedMemory(); freeSharedMemory(0, 0);
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
TEST_CASE("Get default stop port") { TEST_CASE("Get default stop port") {
Module m(dt::GOTTHARD2); Module m(dt::GOTTHARD2);
REQUIRE(m.getStopPort() == 1953); REQUIRE(m.getStopPort() == 1953);
m.freeSharedMemory(); freeSharedMemory(0, 0);
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
TEST_CASE("Get default receiver TCP port") { TEST_CASE("Get default receiver TCP port") {
Module m(dt::MYTHEN3); Module m(dt::MYTHEN3);
REQUIRE(m.getReceiverPort() == 1954); REQUIRE(m.getReceiverPort() == 1954);
m.freeSharedMemory(); freeSharedMemory(0, 0);
SharedMemory<sharedModule> moduleShm(0, 0);
REQUIRE(moduleShm.exists() == false);
} }
} // namespace sls } // namespace sls

View File

@ -10,5 +10,5 @@
#define APIMYTHEN3 "developer 0x241001" #define APIMYTHEN3 "developer 0x241001"
#define APIJUNGFRAU "developer 0x241001" #define APIJUNGFRAU "developer 0x241001"
#define APIGOTTHARD2 "developer 0x241007" #define APIGOTTHARD2 "developer 0x241007"
#define APILIB "developer 0x241014"
#define APIRECEIVER "developer 0x241014" #define APIRECEIVER "developer 0x241014"
#define APILIB "developer 0x241021"