7.0.3.rc: jf sync: stopping master gives idle (#822)

* jf sync mode master could return idle when stopped and so not all modules return the same value and must check for 'stopped or idle', Also must throw if any of the module gives an error ( not jungfrau, but eiger could)

* added contains_only to sls::Result (#827)

* added variadic template for checking if a result contains only specified values

* fix for gcc4.8

* renamed to Result::contains_only

* stop on only the positions

---------

Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com>
This commit is contained in:
maliakal_d 2023-10-13 12:27:43 +02:00 committed by GitHub
parent 1484d038de
commit 37ce3d6f59
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 68 additions and 10 deletions

View File

@ -16,6 +16,7 @@
#include <vector> #include <vector>
#include "sls/ToString.h" #include "sls/ToString.h"
#include "sls/TypeTraits.h"
#include "sls/container_utils.h" #include "sls/container_utils.h"
namespace sls { namespace sls {
@ -128,6 +129,25 @@ template <class T, class Allocator = std::allocator<T>> class Result {
/** Test whether all elements of the result are equal */ /** Test whether all elements of the result are equal */
bool equal() const noexcept { return allEqual(vec); } bool equal() const noexcept { return allEqual(vec); }
/** Test whether any element of the result are equal to a value */
bool any(const T &value) const noexcept { return anyEqualTo(vec, value); }
template <typename V, typename... Args, typename = AllSame<V, Args...>>
typename std::enable_if<std::is_same<V, T>::value, bool>::type
contains_only(const V &a, const Args &...args) const noexcept {
auto values = {a, args...};
for (const auto &element : vec) {
int found = 0;
for (const auto &value : values) {
if (value == element)
found++;
}
if (!found)
return false;
}
return true;
}
/** Convert Result<T> to std::vector<T> */ /** Convert Result<T> to std::vector<T> */
operator std::vector<T>() { return vec; } operator std::vector<T>() { return vec; }
}; };

View File

@ -18,6 +18,7 @@
#include <chrono> #include <chrono>
#include <fstream> #include <fstream>
#include <set>
#include <thread> #include <thread>
namespace sls { namespace sls {
@ -848,18 +849,25 @@ void Detector::startDetectorReadout() {
void Detector::stopDetector(Positions pos) { void Detector::stopDetector(Positions pos) {
// stop and check status X times
int retries{0}; int retries{0};
// avoid default construction of runStatus::IDLE on squash auto status = getDetectorStatus(pos);
auto status = getDetectorStatus().squash(defs::runStatus::RUNNING);
while (status != defs::runStatus::IDLE && // jf sync fix: status [stopped or idle] = [stopped]
status != defs::runStatus::STOPPED) { // sync issue: (master idle sometimes, slaves stopped)
if (status == defs::runStatus::ERROR) {
throw RuntimeError( // eiger fix: stop multiple times from multi client till all modules stopped
"Could not stop detector. Returned error status."); // issue: asynchronous start and stop scripts with a module being started
// (stop before) and waiting for the other to be done. So a module that was
// idle before stopping will return running (after async start script) when
// getting status after, which will then be stopped again.
while (!status.contains_only(defs::runStatus::IDLE, defs::runStatus::STOPPED)){
if (status.any(defs::runStatus::ERROR)) {
throw RuntimeError("Could not stop detector. At least one module "
"returned error status.");
} }
pimpl->stopDetector(pos); pimpl->stopDetector(pos);
status = getDetectorStatus().squash(defs::runStatus::RUNNING); status = getDetectorStatus(pos);
++retries; ++retries;
if (retries == 10) if (retries == 10)
@ -878,7 +886,7 @@ void Detector::stopDetector(Positions pos) {
for (auto it : res) { for (auto it : res) {
maxVal = std::max(maxVal, it); maxVal = std::max(maxVal, it);
} }
setNextFrameNumber(maxVal + 1); setNextFrameNumber(maxVal + 1, pos);
} }
} break; } break;
default: default:

View File

@ -196,4 +196,24 @@ TEST_CASE("String conversions") {
"[{one: 1}, {one: 1, three: 3, two: 2}, {one: 1}]"); "[{one: 1}, {one: 1, three: 3, two: 2}, {one: 1}]");
} }
TEST_CASE("Any element is equal"){
Result<int> r{1,2,3,4,5};
REQUIRE(r.any(3));
REQUIRE_FALSE(r.any(9));
}
TEST_CASE("Result contains only the specified elements"){
Result<int> r{1,1,1};
REQUIRE(r.contains_only(1));
REQUIRE(r.contains_only(1,1));
}
TEST_CASE("Only with multiple values"){
Result<int> r{1,1,2,1,2,1,1};
REQUIRE_FALSE(r.contains_only(1));
REQUIRE_FALSE(r.contains_only(2));
REQUIRE(r.contains_only(1,2));
REQUIRE(r.contains_only(2,1));
}
} // namespace sls } // namespace sls

View File

@ -103,4 +103,14 @@ template <typename T> struct is_vector : public std::false_type {};
template <typename T> template <typename T>
struct is_vector<std::vector<T>> : public std::true_type {}; struct is_vector<std::vector<T>> : public std::true_type {};
template<class...> struct Conjunction : std::true_type {};
template<class B1> struct Conjunction<B1> : B1 {};
template<class B1, class... Bn>
struct Conjunction<B1, Bn...>
: std::conditional<bool(B1::value), Conjunction<Bn...>, B1>::type {};
template<typename T, typename... Ts>
using AllSame = typename std::enable_if<Conjunction<std::is_same<T, Ts>...>::value>::type;
} // namespace sls } // namespace sls