Skip to content

Commit

Permalink
Implemented Session::close function.
Browse files Browse the repository at this point in the history
  • Loading branch information
pjarosik committed Oct 11, 2021
1 parent 39f728e commit 01bafb2
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 17 deletions.
10 changes: 10 additions & 0 deletions api/python/arrus/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,16 @@ def run(self):
"""
self._session_handle.run()

def close(self):
"""
Closes session.
This method disconnects with all the devices available during this session.
Sets the state of the session to closed, any subsequent call to the object
methods (e.g. upload, startScheme..) will result in exception.
"""
self._session_handle.close()

def get_device(self, path: str):
"""
Returns a device identified by a given id.
Expand Down
29 changes: 25 additions & 4 deletions arrus/common/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define ARRUS_COMMON_UTILS_H

#include <string>
#include <boost/preprocessor.hpp>

#include "arrus/common/asserts.h"
#include "arrus/common/format.h"
Expand All @@ -12,17 +13,37 @@ template<typename V, typename T>
V safeCast(const T &in, const std::string& paramName,
const std::string& requiredTypeName) {
ARRUS_REQUIRES_DATA_TYPE_E(
in, V, std::runtime_error(
::arrus::format("Data type mismatch: value '{}' cannot be "
"safely casted to type {}.",
paramName, requiredTypeName)));
in, V, std::runtime_error(::arrus::format("Data type mismatch: value '{}' cannot be safely casted to type {}.",
paramName, requiredTypeName)));

return static_cast<V>(in);
}

#define ARRUS_SAFE_CAST(value, dtype) \
::arrus::safeCast<dtype>((value), #value, #dtype)

// Based on the answer:
// https://stackoverflow.com/questions/5093460/how-to-convert-an-enum-type-variable-to-a-string#answer-5094430

#define ARRUS_DEFINE_ENUM_WITH_TO_STRING_CASE(r, data, elem) \
case data::elem : return BOOST_PP_STRINGIZE(elem);

#define ARRUS_DEFINE_ENUM_WITH_TO_STRING(name, enumerators) \
enum class name { \
BOOST_PP_SEQ_ENUM(enumerators) \
}; \
\
inline const char* toString(name v) { \
switch (v) { \
BOOST_PP_SEQ_FOR_EACH( \
ARRUS_DEFINE_ENUM_WITH_TO_STRING_CASE, \
name, \
enumerators \
) \
default: return "[Unknown " BOOST_PP_STRINGIZE(name) "]"; \
} \
}

}

#endif //ARRUS_COMMON_UTILS_H
9 changes: 9 additions & 0 deletions arrus/core/api/session/Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,15 @@ class Session {
*/
virtual void run() = 0;

/**
* Closes session.
*
* This method disconnects with all the devices available during this session.
* Sets the state of the session to closed, any subsequent call to the object methods (e.g. upload, startScheme..)
* will result in InvalidStateException.
*/
virtual void close() = 0;

virtual ~Session() = default;
};

Expand Down
50 changes: 41 additions & 9 deletions arrus/core/session/SessionImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,24 @@ namespace arrus::session {

using namespace arrus::devices;

#define ASSERT_STATE(expectedState) \
do { \
if(this->state != expectedState) { \
\
throw ::arrus::IllegalStateException(::arrus::format("Invalid session state, should be: {}", \
toString(expectedState))); \
} \
} while(0)

#define ASSERT_STATE_NOT(excludedState) \
do { \
if(this->state == excludedState) { \
\
throw ::arrus::IllegalStateException(::arrus::format("Invalid session state, should not be: {}", \
toString(excludedState))); \
} \
} while(0)

Session::Handle createSession(const SessionSettings &sessionSettings) {
return std::make_unique<SessionImpl>(
sessionSettings,
Expand All @@ -48,9 +66,8 @@ Session::Handle createSession(const std::string& filepath) {
SessionImpl::SessionImpl(const SessionSettings &sessionSettings,
Us4RFactory::Handle us4RFactory)
: us4rFactory(std::move(us4RFactory)) {
getDefaultLogger()->log(LogSeverity::DEBUG,
arrus::format("Configuring session: {}",
toString(sessionSettings)));
getDefaultLogger()->log(LogSeverity::DEBUG, arrus::format("Configuring session: {}",
::arrus::toString(sessionSettings)));
devices = configureDevices(sessionSettings);
}

Expand Down Expand Up @@ -100,16 +117,13 @@ SessionImpl::configureDevices(const SessionSettings &sessionSettings) {
}

SessionImpl::~SessionImpl() {
::arrus::getDefaultLogger()->log(LogSeverity::INFO, "Closing session.");
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->stop();
this->close();
}

UploadResult SessionImpl::upload(const ops::us4r::Scheme &scheme) {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
if(state == State::STARTED) {
throw IllegalStateException("Stop the scheme first, before uploading new scheme");
}
ASSERT_STATE(State::STOPPED);

auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
auto &outputBufferSpec = scheme.getOutputBuffer();
auto[buffer, fcm] = us4r->upload(scheme.getTxRxSequence(), scheme.getRxBufferSize(),
Expand All @@ -124,20 +138,24 @@ UploadResult SessionImpl::upload(const ops::us4r::Scheme &scheme) {

void SessionImpl::startScheme() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
ASSERT_STATE(State::STOPPED);
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->start();
state = State::STARTED;
}

void SessionImpl::stopScheme() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
ASSERT_STATE(State::STARTED);
auto us4r = (::arrus::devices::Us4R *) getDevice(DeviceId(DeviceType::Us4R, 0));
us4r->stop();
state = State::STOPPED;
}

void SessionImpl::run() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
ASSERT_STATE_NOT(State::CLOSED);

if(!currentScheme.has_value()) {
throw IllegalStateException("Upload scheme before running.");
}
Expand All @@ -154,4 +172,18 @@ void SessionImpl::run() {
}
}

void SessionImpl::close() {
std::lock_guard<std::recursive_mutex> guard(stateMutex);
if(this->state == State::CLOSED) {
getDefaultLogger()->log(LogSeverity::INFO, arrus::format("Session already closed."));
return;
}
if(this->state == State::STARTED) {
stopScheme();
}
getDefaultLogger()->log(LogSeverity::INFO, arrus::format("Closing session."));
this->devices.clear();
this->state = State::CLOSED;
}

}
16 changes: 12 additions & 4 deletions arrus/core/session/SessionImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "arrus/core/api/session/Session.h"
#include "arrus/core/common/hash.h"
#include "arrus/core/devices/DeviceId.h"
#include "arrus/common/utils.h"

namespace arrus::session {

Expand Down Expand Up @@ -40,12 +41,19 @@ class SessionImpl : public Session {
SessionImpl(SessionImpl const &&) = delete;

void operator=(SessionImpl const &&) = delete;
void close() override;

private:
enum class State {
STARTED,
STOPPED
};
ARRUS_DEFINE_ENUM_WITH_TO_STRING(
State,
// The connection with devices is established, but the input sources do not produce
// any new data right now.
(STOPPED)
// All the input sources are producing new data.
(STARTED)
// The connection with devices is closed.
(CLOSED)
);

using DeviceMap = std::unordered_map<
arrus::devices::DeviceId,
Expand Down

0 comments on commit 01bafb2

Please sign in to comment.