diff --git a/iioutil/include/iioutil/commandqueue.h b/iioutil/include/iioutil/commandqueue.h index 06867575e..912049114 100644 --- a/iioutil/include/iioutil/commandqueue.h +++ b/iioutil/include/iioutil/commandqueue.h @@ -18,29 +18,21 @@ class SCOPY_IIOUTIL_EXPORT CommandQueue : public QObject * @param numberOfThreads * @param parent */ - explicit CommandQueue(int numberOfThreads = 1, QObject *parent = nullptr); + explicit CommandQueue(QObject *parent = nullptr); ~CommandQueue(); void enqueue(Command *newCmd); void start(); void wait(); void requestStop(); -Q_SIGNALS: - void started(scopy::Command *); - void finished(scopy::Command *); + void runCmd(); private Q_SLOTS: - void work(); - void cmdStarted(scopy::Command *cmd); - void cmdFinished(scopy::Command *cmd); + void resolveNext(scopy::Command *cmd); private: - Command *m_currentCommand; std::deque m_commandQueue; std::mutex m_commandMutex; std::atomic m_running; QThreadPool m_commandExecThreadPool; - int m_nbThreads; - bool m_async; - bool m_workNewThread; }; } // namespace scopy #endif // IIOCOMMANDQUEUE_H diff --git a/iioutil/include/iioutil/connection.h b/iioutil/include/iioutil/connection.h new file mode 100644 index 000000000..c6d868816 --- /dev/null +++ b/iioutil/include/iioutil/connection.h @@ -0,0 +1,65 @@ +#ifndef CONNECTION_H +#define CONNECTION_H +#include "scopy-iioutil_export.h" +#include "commandqueue.h" +#include +#include + +namespace scopy { +class SCOPY_IIOUTIL_EXPORT Connection : public QObject +{ + Q_OBJECT +public: + Connection(QString uri); + + const QString &uri() const; + CommandQueue *commandQueue() const; + struct iio_context *context() const; + int refCount() const; + +protected: + ~Connection(); + + /** + * @brief open + * Initialize the connection if not previously opened. + * If previously opened, increase the internal refCount. + */ + void open(); + + /** + * @brief close + * Decrement the internal refCount. + * Emit the aboutToBeDestroyed() signal if refCount is zero. + */ + void close(); + + /** + * @brief closeAll + * Reset the internal refCount to zero. + * Force close the Connection. + * Emit the aboutToBeDestroyed() signal. + */ + void closeAll(); + +Q_SIGNALS: + /** + * @brief aboutToBeDestroyed + * Connection clients should handle deinitialization + * of their iio_context/CommandQueue related operations + * in a slot connected to this signal. + * After the signal is emitted, the Connection object + * will no longer be valid. + */ + void aboutToBeDestroyed(); + +private: + friend class ConnectionProvider; + QString m_uri; + CommandQueue *m_commandQueue; + struct iio_context *m_context; + int m_refCount = 0; +}; +} // namespace scopy + +#endif // CONNECTION_H diff --git a/iioutil/include/iioutil/connectionprovider.h b/iioutil/include/iioutil/connectionprovider.h new file mode 100644 index 000000000..024002d3f --- /dev/null +++ b/iioutil/include/iioutil/connectionprovider.h @@ -0,0 +1,39 @@ +#ifndef CONNECTIONPROVIDER_H +#define CONNECTIONPROVIDER_H + +#include "scopy-iioutil_export.h" +#include "connection.h" + +#include +#include +#include + +namespace scopy { +class SCOPY_IIOUTIL_EXPORT ConnectionProvider : public QObject +{ + Q_OBJECT +protected: + ConnectionProvider(QObject *parent = nullptr); + ~ConnectionProvider(); + +public: + ConnectionProvider(ConnectionProvider &other) = delete; + void operator=(const ConnectionProvider &) = delete; + + static ConnectionProvider *GetInstance(); + static Connection *open(QString uri); + static void close(QString uri); + static void closeAll(QString uri); + +private: + Connection *_open(QString uri); + void _close(QString uri); + void _closeAll(QString uri); + void _closeAndRemove(QString uri); + static ConnectionProvider *pinstance_; + static std::mutex mutex_; + QMap map; +}; +} // namespace scopy + +#endif // CONNECTIONPROVIDER_H diff --git a/iioutil/src/commandqueue.cpp b/iioutil/src/commandqueue.cpp index ee160d334..30885cd81 100644 --- a/iioutil/src/commandqueue.cpp +++ b/iioutil/src/commandqueue.cpp @@ -10,22 +10,14 @@ using namespace scopy; Q_LOGGING_CATEGORY(CAT_COMMANDQUEUE, "CommandQueue"); -CommandQueue::CommandQueue(int numberOfThreads, QObject *parent) +CommandQueue::CommandQueue(QObject *parent) : QObject(parent) , m_running(false) - , m_nbThreads(numberOfThreads) - , m_async(m_nbThreads > 1) - , m_workNewThread(m_nbThreads != 0) - , m_currentCommand(nullptr) -{ - m_commandExecThreadPool.setMaxThreadCount(std::min(m_nbThreads, QThread::idealThreadCount())); -} +{} CommandQueue::~CommandQueue() { requestStop(); - wait(); - for(auto c : m_commandQueue) { delete c; } @@ -34,96 +26,58 @@ CommandQueue::~CommandQueue() void CommandQueue::enqueue(Command *command) { - std::lock_guard lock(m_commandMutex); - start(); - connect(command, &Command::started, this, &CommandQueue::cmdStarted, - static_cast(Qt::QueuedConnection | Qt::UniqueConnection)); - connect(command, &Command::finished, this, &CommandQueue::cmdFinished, - static_cast(Qt::QueuedConnection | Qt::UniqueConnection)); m_commandQueue.push_back(command); -} + qDebug(CAT_COMMANDQUEUE) << "enqueued " << command << " " << m_commandQueue.size(); -void CommandQueue::start() -{ if(!m_running) { - qDebug(CAT_COMMANDQUEUE) << "CommandQueue set running to true (start)"; - m_running = true; - if(m_workNewThread) { - m_commandExecThreadPool.start(std::bind(&CommandQueue::work, this)); - } else { - // trigger work on Main Thread - QMetaObject::invokeMethod(this, "work", Qt::QueuedConnection); - } + start(); } } -void CommandQueue::requestStop() +void CommandQueue::start() { - if(m_running) { - qDebug(CAT_COMMANDQUEUE) << "CommandQueue set running to false (stop)"; - m_running = false; - if(m_workNewThread) { - std::unique_lock lock(m_commandMutex); - m_commandQueue.clear(); - } - } + m_running = true; + runCmd(); } -void CommandQueue::wait() +void CommandQueue::resolveNext(scopy::Command *cmd) { - if(m_running) { - qDebug(CAT_COMMANDQUEUE) << "CommandQueue set running to true (wait)"; + m_commandQueue.pop_front(); // also delete/disconnect + qDebug(CAT_COMMANDQUEUE) << "delete " << cmd; + disconnect(cmd, &Command::finished, this, &CommandQueue::resolveNext); + cmd->deleteLater(); + + if(m_commandQueue.size() == 0) { m_running = false; - } - if(m_workNewThread) { - m_commandExecThreadPool.waitForDone(); + } else { + runCmd(); } } -void CommandQueue::work() +void CommandQueue::runCmd() { - while(m_running) { - std::unique_lock lock(m_commandMutex); - if(m_commandQueue.empty()) { - m_running = false; - break; - } - - m_currentCommand = m_commandQueue.front(); - if(m_async) { - QtConcurrent::run(&m_commandExecThreadPool, std::bind([=]() { m_currentCommand->execute(); })); - } else { - int size = m_commandQueue.size(); - lock.unlock(); - qDebug(CAT_COMMANDQUEUE) - << "CommandQueue executing " << m_currentCommand << " cmdq size: " << size; - m_currentCommand->execute(); - m_currentCommand->deleteLater(); - m_currentCommand = nullptr; - lock.lock(); - } - m_commandQueue.pop_front(); + std::lock_guard lock(m_commandMutex); + qDebug(CAT_COMMANDQUEUE) << "run cmd " << m_commandQueue.at(0); + if(m_running) { + connect(m_commandQueue.at(0), &Command::finished, this, &CommandQueue::resolveNext); + QtConcurrent::run(QThreadPool::globalInstance(), std::bind([=]() { + std::unique_lock lock(m_commandMutex); + qDebug(CAT_COMMANDQUEUE) << "execute start " << m_commandQueue.at(0); + m_commandQueue.at(0)->execute(); + qDebug(CAT_COMMANDQUEUE) << "execute stop " << m_commandQueue.at(0); + })); } } -void CommandQueue::cmdFinished(scopy::Command *cmd) +void CommandQueue::requestStop() { - if(!cmd) { - cmd = dynamic_cast(QObject::sender()); - } - if(cmd) { - Q_EMIT finished(cmd); + std::lock_guard lock(m_commandMutex); + qDebug(CAT_COMMANDQUEUE) << "request stop " << m_commandQueue.size(); + if(m_running) { + m_running = false; } } -void CommandQueue::cmdStarted(scopy::Command *cmd) -{ - if(!cmd) { - cmd = dynamic_cast(QObject::sender()); - } - if(cmd) { - Q_EMIT started(cmd); - } -} +void CommandQueue::wait() { QThreadPool::globalInstance()->waitForDone(); } #include "moc_commandqueue.cpp" diff --git a/iioutil/src/commandqueueprovider.cpp b/iioutil/src/commandqueueprovider.cpp index 327663b9b..7fb19aa58 100644 --- a/iioutil/src/commandqueueprovider.cpp +++ b/iioutil/src/commandqueueprovider.cpp @@ -12,7 +12,7 @@ CommandQueueRefCounter::CommandQueueRefCounter(struct iio_context *ctx) this->ctx = ctx; this->refcnt++; // TBD: automatically check the iio_context to see if multiple threads are possible (iiod vs tinyiiod) - this->cmdQueue = new CommandQueue(1); + this->cmdQueue = new CommandQueue(); } CommandQueueRefCounter::~CommandQueueRefCounter() diff --git a/iioutil/src/connection.cpp b/iioutil/src/connection.cpp new file mode 100644 index 000000000..7c1275763 --- /dev/null +++ b/iioutil/src/connection.cpp @@ -0,0 +1,64 @@ +#include "connection.h" + +using namespace scopy; + +Connection::Connection(QString uri) +{ + this->m_uri = uri; + this->m_context = nullptr; + this->m_commandQueue = nullptr; + this->m_refCount = 0; +} + +Connection::~Connection() +{ + if(this->m_commandQueue) { + delete this->m_commandQueue; + this->m_commandQueue = nullptr; + } + if(this->m_context) { + iio_context_destroy(this->m_context); + this->m_context = nullptr; + } +} + +const QString &Connection::uri() const { return m_uri; } + +CommandQueue *Connection::commandQueue() const { return m_commandQueue; } + +iio_context *Connection::context() const { return m_context; } + +int Connection::refCount() const { return m_refCount; } + +void Connection::open() +{ + if(!this->m_context) { + this->m_context = iio_create_context_from_uri(this->m_uri.toStdString().c_str()); + if(this->m_context) { + this->m_commandQueue = new CommandQueue(); + this->m_refCount++; + } + } else { + this->m_refCount++; + } +} + +void Connection::closeAll() +{ + this->m_refCount = 0; + close(); +} + +void Connection::close() +{ + this->m_refCount--; + if(this->m_refCount <= 0) { + /* If the open() and close() number of calls done by a client + * is mismatched, all the remaining clients should be notified of the + * destruction. */ + this->m_refCount = 0; + Q_EMIT aboutToBeDestroyed(); + } +} + +#include "moc_connection.cpp" diff --git a/iioutil/src/connectionprovider.cpp b/iioutil/src/connectionprovider.cpp new file mode 100644 index 000000000..416e588c3 --- /dev/null +++ b/iioutil/src/connectionprovider.cpp @@ -0,0 +1,93 @@ +#include "connectionprovider.h" +#include +#include + +Q_LOGGING_CATEGORY(CAT_CONNECTIONMGR, "ConnectionProvider") + +using namespace scopy; + +ConnectionProvider *ConnectionProvider::pinstance_{nullptr}; +std::mutex ConnectionProvider::mutex_; + +scopy::ConnectionProvider::ConnectionProvider(QObject *parent) + : QObject(parent) +{ + qDebug(CAT_CONNECTIONMGR) << "ConnectionProvider object ctor"; +} + +scopy::ConnectionProvider::~ConnectionProvider() { qDebug(CAT_CONNECTIONMGR) << "ConnectionProvider object dtor"; } + +ConnectionProvider *ConnectionProvider::GetInstance() +{ + std::lock_guard lock(mutex_); + if(pinstance_ == nullptr) { + pinstance_ = new ConnectionProvider(QApplication::instance()); // singleton has the app as parent + } else { + qDebug(CAT_CONNECTIONMGR) << "ConnectionProvider: Got instance from singleton"; + } + return pinstance_; +} + +Connection *ConnectionProvider::open(QString uri) { return ConnectionProvider::GetInstance()->_open(uri); } + +Connection *ConnectionProvider::_open(QString uri) +{ + std::lock_guard lock(mutex_); + Connection *connectionObject = nullptr; + if(!map.contains(uri)) { + connectionObject = new Connection(uri); + map.insert(uri, connectionObject); + qDebug(CAT_CONNECTIONMGR) << uri << " created in map "; + } else { + connectionObject = map.value(uri); + qDebug(CAT_CONNECTIONMGR) << uri << " found in map "; + } + connectionObject->open(); + if(connectionObject->refCount() == 0) { + qDebug(CAT_CONNECTIONMGR) << uri << " Connection: failed to open, removed from map."; + map.remove(uri); + delete connectionObject; + return nullptr; + } + qDebug(CAT_CONNECTIONMGR) << uri << " Connection: open, refcount++ = " << connectionObject->refCount(); + return connectionObject; +} + +void ConnectionProvider::closeAll(QString uri) { return ConnectionProvider::GetInstance()->_closeAll(uri); } + +void ConnectionProvider::close(QString uri) { return ConnectionProvider::GetInstance()->_close(uri); } + +void ConnectionProvider::_closeAll(QString uri) +{ + std::lock_guard lock(mutex_); + if(map.contains(uri)) { + map.value(uri)->closeAll(); + } + _closeAndRemove(uri); +} + +void ConnectionProvider::_close(QString uri) +{ + std::lock_guard lock(mutex_); + if(map.contains(uri)) { + map.value(uri)->close(); + } + _closeAndRemove(uri); +} + +void ConnectionProvider::_closeAndRemove(QString uri) +{ + if(map.contains(uri)) { + qDebug(CAT_CONNECTIONMGR) + << uri << " Connection: closing - found in map - refcnt-- = " << map.value(uri)->refCount(); + if(map.value(uri)->refCount() == 0) { + delete map[uri]; + map.remove(uri); + qDebug(CAT_CONNECTIONMGR) << uri << " Connection: destroyed, removed from map"; + } + } else { + qInfo(CAT_CONNECTIONMGR) << uri << " Connection: not found in map. nop"; + } +} + +#include "moc_connectionprovider.cpp" diff --git a/iioutil/test/CMakeLists.txt b/iioutil/test/CMakeLists.txt index dada5cfc2..f38f34e5b 100644 --- a/iioutil/test/CMakeLists.txt +++ b/iioutil/test/CMakeLists.txt @@ -3,3 +3,4 @@ cmake_minimum_required(VERSION 3.5) include(ScopyTest) setup_scopy_tests(iiocommandqueue) +setup_scopy_tests(connectionprovider) diff --git a/iioutil/test/tst_connectionprovider.cpp b/iioutil/test/tst_connectionprovider.cpp new file mode 100644 index 000000000..55c5a103c --- /dev/null +++ b/iioutil/test/tst_connectionprovider.cpp @@ -0,0 +1,224 @@ +#include +#include + +#include + +using namespace scopy; + +class TestCommandAdd : public Command +{ + Q_OBJECT +public: + explicit TestCommandAdd(int a, int b, QObject *parent) + : m_a(a) + , m_b(b) + { + this->setParent(parent); + m_cmdResult = new CommandResult(); + } + + virtual ~TestCommandAdd() { qDebug() << "TestCommand deleted"; } + + virtual void execute() override + { + Q_EMIT started(this); + m_cmdResult->errorCode = m_a + m_b; + Q_EMIT finished(this); + } + +private: + int m_a, m_b; +}; + +class Plugin1 : public QObject +{ + Q_OBJECT +public: + explicit Plugin1(QString boarduri) + { + uri = boarduri; + conn = ConnectionProvider::open(uri); + if(conn) { + connect(conn, &Connection::aboutToBeDestroyed, this, &Plugin1::handleClose); + commandQueue = conn->commandQueue(); + ctx = conn->context(); + } else { + conn = nullptr; + commandQueue = nullptr; + uri = nullptr; + } + } + + virtual ~Plugin1() { ConnectionProvider::close(uri); } + + void close() + { + qInfo() << "Plugin1 close connection"; + ConnectionProvider::close(uri); + } + + void closeAll() { ConnectionProvider::closeAll(uri); } + + const QString &getUri() const { return uri; } + + Connection *getConn() const { return conn; } + + CommandQueue *getCommandQueue() const { return commandQueue; } + + iio_context *getCtx() const { return ctx; } + +public Q_SLOTS: + void handleClose() + { + // notify any thread that might be using command queue or ctx + qInfo() << "Plugin1 handle close on aboutToBeDestroyed() signal"; + conn = nullptr; + commandQueue = nullptr; + uri = nullptr; + } + +private: + QString uri; + Connection *conn; + CommandQueue *commandQueue; + struct iio_context *ctx; +}; + +class TST_ConnectionProvider : public QObject +{ + Q_OBJECT +private Q_SLOTS: + void testReferenceCount(); + void testMismatchedOpenClose(); + void testSignalAboutToBeDestroyed(); + void testForceClose(); + void testConnectionCmdQ(); + +private: + int TEST_A = 100; + int TEST_B = 20; +}; + +void TST_ConnectionProvider::testReferenceCount() +{ + QString uri = "ip:192.168.2.1"; + Plugin1 *p1 = new Plugin1(uri); + if(!p1->getConn()) { + QSKIP("No context. Skipping"); + } + QVERIFY2(p1->getConn()->refCount() == 1, "P1 object connection not opened"); + + Plugin1 *p2 = new Plugin1(uri); + QVERIFY2(p1->getConn()->refCount() == 2, "P2 object connection not opened"); + + Plugin1 *p3 = new Plugin1(uri); + QVERIFY2(p1->getConn()->refCount() == 3, "P3 object connection not opened"); + + p1->close(); + QVERIFY2(p1->getConn()->refCount() == 2, "P1 object connection not closed"); + p2->close(); + QVERIFY2(p2->getConn()->refCount() == 1, "P2 object connection not closed"); + p3->close(); + QVERIFY2(p3->getConn() == nullptr, "P3 object connection not closed"); +} + +void TST_ConnectionProvider::testMismatchedOpenClose() +{ + QString uri = "ip:192.168.2.1"; + Plugin1 *p1 = new Plugin1(uri); + Plugin1 *p2 = new Plugin1(uri); + if(!p1->getConn()) { + QSKIP("No context. Skipping"); + } + + QVERIFY2(p1->getConn()->refCount() == 2, "P1 object connection not opened"); + + p1->close(); + p1->close(); + QVERIFY2(p1->getConn() == nullptr, "P1 object connection not closed"); + p2->close(); +} + +void TST_ConnectionProvider::testSignalAboutToBeDestroyed() +{ + QString uri = "ip:192.168.2.1"; + Plugin1 *p1 = new Plugin1(uri); + Plugin1 *p2 = new Plugin1(uri); + Plugin1 *p3 = new Plugin1(uri); + if(!p1->getConn()) { + QSKIP("No context. Skipping"); + } + + QVERIFY2(p1->getConn() != nullptr, "P1 object connection not opened"); + QVERIFY2(p2->getConn() != nullptr, "P2 object connection not opened"); + QVERIFY2(p3->getConn() != nullptr, "P3 object connection not opened"); + + p1->close(); + p2->close(); + p3->close(); + QVERIFY2(p1->getConn() == nullptr, "P1 object connection not closed"); + QVERIFY2(p2->getConn() == nullptr, "P2 object connection not closed"); + QVERIFY2(p3->getConn() == nullptr, "P3 object connection not closed"); +} + +void TST_ConnectionProvider::testForceClose() +{ + QString uri = "ip:192.168.2.1"; + Plugin1 *p1 = new Plugin1(uri); + Plugin1 *p2 = new Plugin1(uri); + Plugin1 *p3 = new Plugin1(uri); + if(!p1->getConn()) { + QSKIP("No context. Skipping"); + } + + QVERIFY2(p1->getConn() != nullptr, "P1 object connection not opened"); + QVERIFY2(p2->getConn() != nullptr, "P2 object connection not opened"); + QVERIFY2(p3->getConn() != nullptr, "P3 object connection not opened"); + + p3->closeAll(); + QVERIFY2(p1->getConn() == nullptr, "P1 object connection not closed"); + QVERIFY2(p2->getConn() == nullptr, "P2 object connection not closed"); + QVERIFY2(p3->getConn() == nullptr, "P3 object connection not closed"); +} + +void TST_ConnectionProvider::testConnectionCmdQ() +{ + Command *cmd1 = new TestCommandAdd(TEST_A, TEST_B, nullptr); + QString uri = "ip:192.168.2.1"; + Plugin1 *p1 = new Plugin1(uri); + Plugin1 *p2 = new Plugin1(uri); + Plugin1 *p3 = new Plugin1(uri); + if(!p1->getConn()) { + QSKIP("No context. Skipping"); + } + + QVERIFY2(p1->getConn() != nullptr, "P1 object connection not opened"); + QVERIFY2(p2->getConn() != nullptr, "P2 object connection not opened"); + QVERIFY2(p3->getConn() != nullptr, "P3 object connection not opened"); + + connect( + cmd1, &scopy::Command::finished, this, + [=](scopy::Command *cmd) { + if(!cmd) { + cmd = dynamic_cast(QObject::sender()); + } + TestCommandAdd *tcmd = dynamic_cast(cmd); + QVERIFY2(tcmd != nullptr, "Capture command is null"); + QVERIFY2(tcmd == cmd1, "Captured command not the expected one"); + QVERIFY2(tcmd->getReturnCode() == (TEST_B + TEST_A), "TestCommandAdd did not execute"); + }, + Qt::QueuedConnection); + + p1->getCommandQueue()->enqueue(cmd1); + + QTest::qWait(100); + p3->close(); + p2->close(); + p1->close(); + QVERIFY2(p1->getConn() == nullptr, "P1 object connection not closed"); + QVERIFY2(p2->getConn() == nullptr, "P2 object connection not closed"); + QVERIFY2(p3->getConn() == nullptr, "P3 object connection not closed"); +} + +QTEST_MAIN(TST_ConnectionProvider) +#include "tst_connectionprovider.moc" diff --git a/iioutil/test/tst_iiocommandqueue.cpp b/iioutil/test/tst_iiocommandqueue.cpp index fa15e7ce7..d836dd087 100644 --- a/iioutil/test/tst_iiocommandqueue.cpp +++ b/iioutil/test/tst_iiocommandqueue.cpp @@ -138,7 +138,7 @@ private Q_SLOTS: void TST_IioCommandQueue::testResults() { - CommandQueue *cmdQ = new CommandQueue(1, nullptr); + CommandQueue *cmdQ = new CommandQueue(nullptr); Command *cmd1 = new TestCommandAdd(TEST_A, TEST_B, nullptr); Command *cmd2 = new TestCommandMultiply(TEST_A, TEST_B, nullptr); Command *cmd3 = new TestCommandMsg(TEST_A, "Test command 300", nullptr); @@ -196,7 +196,7 @@ void TST_IioCommandQueue::testResults() void TST_IioCommandQueue::testCommandOrder() { - CommandQueue *cmdQ = new CommandQueue(1, nullptr); + CommandQueue *cmdQ = new CommandQueue(nullptr); Command *cmd1 = new TestCommandAdd(TEST_A, TEST_B, nullptr); Command *cmd3 = new TestCommandMsg(TEST_A, "Test command 300", nullptr); diff --git a/plugins/swiot/include/swiot/swiotplugin.h b/plugins/swiot/include/swiot/swiotplugin.h index d015b0b35..5e7e70be7 100644 --- a/plugins/swiot/include/swiot/swiotplugin.h +++ b/plugins/swiot/include/swiot/swiotplugin.h @@ -34,7 +34,6 @@ #include "src/swiotinfopage.h" #include -#include #include #include #include diff --git a/plugins/swiot/src/config/swiotconfig.cpp b/plugins/swiot/src/config/swiotconfig.cpp index 2bc0a4f9c..33161d526 100644 --- a/plugins/swiot/src/config/swiotconfig.cpp +++ b/plugins/swiot/src/config/swiotconfig.cpp @@ -30,23 +30,25 @@ #include #include -#include +#include using namespace scopy::swiot; -SwiotConfig::SwiotConfig(struct iio_context *ctx, QWidget *parent) +SwiotConfig::SwiotConfig(QString uri, QWidget *parent) : QWidget(parent) - , m_context(ctx) + , m_uri(uri) , m_drawArea(nullptr) , m_scrollArea(nullptr) , m_toolView(nullptr) , m_mainView(new QWidget(this)) , m_statusLabel(new QLabel(this)) , m_statusContainer(new QWidget(this)) - , m_commandQueue(CommandQueueProvider::GetInstance()->open(ctx)) , ui(new Ui::ConfigMenu) { - m_swiotDevice = iio_context_find_device(ctx, "swiot"); + Connection *conn = ConnectionProvider::open(m_uri); + m_context = conn->context(); + m_commandQueue = conn->commandQueue(); + m_swiotDevice = iio_context_find_device(m_context, "swiot"); if(m_swiotDevice == nullptr) { qCritical(CAT_SWIOT_CONFIG) << "Critical error: the \"swiot\" device was not found."; } @@ -63,14 +65,7 @@ SwiotConfig::SwiotConfig(struct iio_context *ctx, QWidget *parent) QObject::connect(m_configBtn, &QPushButton::pressed, this, &SwiotConfig::onConfigBtnPressed); } -SwiotConfig::~SwiotConfig() -{ - if(m_commandQueue) { - CommandQueueProvider::GetInstance()->close(m_context); - m_commandQueue = nullptr; - m_context = nullptr; - } -} +SwiotConfig::~SwiotConfig() { ConnectionProvider::close(m_uri); } void SwiotConfig::init() { diff --git a/plugins/swiot/src/config/swiotconfig.h b/plugins/swiot/src/config/swiotconfig.h index d3f4f8309..b492c3e25 100644 --- a/plugins/swiot/src/config/swiotconfig.h +++ b/plugins/swiot/src/config/swiotconfig.h @@ -49,7 +49,7 @@ class SwiotConfig : public QWidget { Q_OBJECT public: - explicit SwiotConfig(struct iio_context *ctx, QWidget *parent = nullptr); + explicit SwiotConfig(QString uri, QWidget *parent = nullptr); ~SwiotConfig(); public Q_SLOTS: @@ -62,6 +62,7 @@ public Q_SLOTS: void configBtnPressed(); private: + QString m_uri; QMap m_iioDevices; struct iio_context *m_context; struct iio_device *m_swiotDevice; diff --git a/plugins/swiot/src/externalpsreaderthread.cpp b/plugins/swiot/src/externalpsreaderthread.cpp index 0fab230ad..3569a0836 100644 --- a/plugins/swiot/src/externalpsreaderthread.cpp +++ b/plugins/swiot/src/externalpsreaderthread.cpp @@ -21,9 +21,7 @@ #include "externalpsreaderthread.h" #include "src/swiot_logging_categories.h" - -#include -#include +#include #include #include @@ -33,25 +31,32 @@ ExternalPsReaderThread::ExternalPsReaderThread(QString uri, QString attr, QObjec : QThread(parent) , m_uri(uri) , m_attribute(attr) -{} +{ + m_conn = ConnectionProvider::open(m_uri); + if(!m_conn) { + qDebug(CAT_SWIOT) << "Error, no context available for the external ps task."; + } + connect(m_conn, &Connection::aboutToBeDestroyed, this, [=, this]() { m_conn = nullptr; }); +} + +ExternalPsReaderThread::~ExternalPsReaderThread() +{ + if(m_conn) { + m_conn = nullptr; + ConnectionProvider::close(m_uri); + } +} void ExternalPsReaderThread::run() { - iio_context *ctx = ContextProvider::GetInstance()->open(m_uri); - if(!ctx) { + if(!m_conn) { return; } if(isInterruptionRequested()) { - ContextProvider::GetInstance()->close(m_uri); - return; - } - CommandQueue *commandQueue = CommandQueueProvider::GetInstance()->open(ctx); - if(!commandQueue) { - ContextProvider::GetInstance()->close(m_uri); return; } - iio_device *swiotDevice = iio_context_find_device(ctx, "swiot"); + iio_device *swiotDevice = iio_context_find_device(m_conn->context(), "swiot"); if(swiotDevice) { IioDeviceAttributeRead *iioAttrRead = new IioDeviceAttributeRead(swiotDevice, m_attribute.toStdString().c_str(), nullptr, true); @@ -61,8 +66,6 @@ void ExternalPsReaderThread::run() [=, this](scopy::Command *cmd) { IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); return; } if(tcmd->getReturnCode() >= 0) { @@ -77,15 +80,10 @@ void ExternalPsReaderThread::run() "device, error code" << tcmd->getReturnCode(); } - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); }, Qt::QueuedConnection); - commandQueue->enqueue(iioAttrRead); - } else { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); + m_conn->commandQueue()->enqueue(iioAttrRead); } } diff --git a/plugins/swiot/src/externalpsreaderthread.h b/plugins/swiot/src/externalpsreaderthread.h index c2c44ec46..b1efe68cc 100644 --- a/plugins/swiot/src/externalpsreaderthread.h +++ b/plugins/swiot/src/externalpsreaderthread.h @@ -22,6 +22,7 @@ #define SCOPY_EXTERNALPSREADERTHREAD_H #include +#include namespace scopy::swiot { class ExternalPsReaderThread : public QThread @@ -29,14 +30,16 @@ class ExternalPsReaderThread : public QThread Q_OBJECT public: explicit ExternalPsReaderThread(QString uri, QString attr, QObject *parent = nullptr); - void run() override; + ~ExternalPsReaderThread(); + void run() override; Q_SIGNALS: void hasConnectedPowerSupply(bool ps); private: QString m_uri; QString m_attribute; + Connection *m_conn; }; } // namespace scopy::swiot diff --git a/plugins/swiot/src/runtime/ad74413r/ad74413r.cpp b/plugins/swiot/src/runtime/ad74413r/ad74413r.cpp index 8dccff092..5389937e4 100644 --- a/plugins/swiot/src/runtime/ad74413r/ad74413r.cpp +++ b/plugins/swiot/src/runtime/ad74413r/ad74413r.cpp @@ -28,23 +28,28 @@ #include #include -#include +#include using namespace scopy; using namespace scopy::swiot; -Ad74413r::Ad74413r(iio_context *ctx, ToolMenuEntry *tme, QWidget *parent) +Ad74413r::Ad74413r(QString uri, ToolMenuEntry *tme, QWidget *parent) : QWidget(parent) + , m_uri(uri) , m_tme(tme) , m_statusLabel(new QLabel(this)) , m_swiotAdLogic(nullptr) , m_widget(this) , m_readerThread(nullptr) , m_statusContainer(new QWidget(this)) - , m_ctx(ctx) - , m_cmdQueue(CommandQueueProvider::GetInstance()->open(ctx)) , m_currentChannelSelected(0) + , m_backBtnPressed(false) { + m_conn = ConnectionProvider::open(m_uri); + connect(m_conn, &Connection::aboutToBeDestroyed, this, &Ad74413r::handleConnectionDestroyed); + m_ctx = m_conn->context(); + m_cmdQueue = m_conn->commandQueue(); + createDevicesMap(m_ctx); if(m_iioDevicesMap.contains(AD_NAME) && m_iioDevicesMap.contains(SWIOT_DEVICE_NAME)) { char mode[64]; @@ -86,11 +91,15 @@ Ad74413r::~Ad74413r() if(m_controllers.size() > 0) { m_controllers.clear(); } - if(m_cmdQueue) { - CommandQueueProvider::GetInstance()->close(m_ctx); - m_cmdQueue = nullptr; - m_ctx = nullptr; - } + ConnectionProvider::close(m_uri); +} + +void Ad74413r::handleConnectionDestroyed() +{ + qDebug(CAT_SWIOT_AD74413R) << "Ad74413R connection destroyed slot"; + m_ctx = nullptr; + m_cmdQueue = nullptr; + m_conn = nullptr; } void Ad74413r::setupToolView(gui::GenericMenu *settingsMenu) @@ -137,6 +146,7 @@ void Ad74413r::setupToolView(gui::GenericMenu *settingsMenu) void Ad74413r::setupConnections() { + connect(m_conn, &Connection::aboutToBeDestroyed, m_readerThread, &ReaderThread::handleConnectionDestroyed); connect(m_backBtn, &QPushButton::pressed, this, &Ad74413r::onBackBtnPressed); connect(m_toolView->getRunBtn(), &QPushButton::toggled, this, &Ad74413r::onRunBtnPressed); connect(m_swiotAdLogic, &BufferLogic::chnlsChanged, m_readerThread, &ReaderThread::onChnlsChange); @@ -504,7 +514,15 @@ void Ad74413r::onDiagnosticFunctionUpdated() void Ad74413r::onBackBtnPressed() { - m_readerThread->forcedStop(); + bool runBtnChecked = m_toolView->getRunBtn()->isChecked(); + bool singleBtnChecked = m_toolView->getSingleBtn()->isChecked(); + + if(runBtnChecked) { + m_toolView->getRunBtn()->setChecked(false); + } + if(singleBtnChecked) { + m_toolView->getSingleBtn()->setChecked(false); + } Q_EMIT backBtnPressed(); } diff --git a/plugins/swiot/src/runtime/ad74413r/ad74413r.h b/plugins/swiot/src/runtime/ad74413r/ad74413r.h index 2645bc4a5..9af7bbcca 100644 --- a/plugins/swiot/src/runtime/ad74413r/ad74413r.h +++ b/plugins/swiot/src/runtime/ad74413r/ad74413r.h @@ -36,6 +36,7 @@ #include #include +#include #define MAX_CURVES_NUMBER 8 #define AD_NAME "ad74413r" #define SWIOT_DEVICE_NAME "swiot" @@ -57,7 +58,7 @@ class Ad74413r : public QWidget { Q_OBJECT public: - explicit Ad74413r(iio_context *ctx = nullptr, ToolMenuEntry *tme = 0, QWidget *parent = nullptr); + explicit Ad74413r(QString uri = "", ToolMenuEntry *tme = 0, QWidget *parent = nullptr); ~Ad74413r(); @@ -87,6 +88,7 @@ public Q_SLOTS: void onActivateRunBtns(bool activate); + void handleConnectionDestroyed(); Q_SIGNALS: void broadcastReadThreshold(QString value); void thresholdControlEnable(bool enable); @@ -117,6 +119,7 @@ private Q_SLOTS: QMap m_iioDevicesMap; int m_enabledChnlsNo = 0; int m_currentChannelSelected; + bool m_backBtnPressed; scopy::gui::ChannelManager *m_monitorChannelManager; scopy::gui::ToolView *m_toolView; @@ -141,6 +144,8 @@ private Q_SLOTS: ExportSettings *m_exportSettings; struct iio_context *m_ctx; + Connection *m_conn; + QString m_uri; }; } // namespace swiot } // namespace scopy diff --git a/plugins/swiot/src/runtime/faults/faults.cpp b/plugins/swiot/src/runtime/faults/faults.cpp index 90fd08580..05619d215 100644 --- a/plugins/swiot/src/runtime/faults/faults.cpp +++ b/plugins/swiot/src/runtime/faults/faults.cpp @@ -33,11 +33,11 @@ using namespace scopy::swiot; #define POLLING_INTERVAL 1000 -Faults::Faults(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent) +Faults::Faults(QString uri, ToolMenuEntry *tme, QWidget *parent) : QWidget(parent) - , ctx(ctx) + , m_uri(uri) , ui(new Ui::Faults) - , m_faultsPage(new FaultsPage(ctx, this)) + , m_faultsPage(new FaultsPage(m_uri, this)) , m_statusLabel(new QLabel(this)) , m_statusContainer(new QWidget(this)) , timer(new QTimer()) @@ -48,7 +48,6 @@ Faults::Faults(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent) , m_tme(tme) { qInfo(CAT_SWIOT_FAULTS) << "Initialising SWIOT faults page."; - ui->setupUi(this); this->setupDynamicUi(parent); diff --git a/plugins/swiot/src/runtime/faults/faults.h b/plugins/swiot/src/runtime/faults/faults.h index 635e1584b..19815937c 100644 --- a/plugins/swiot/src/runtime/faults/faults.h +++ b/plugins/swiot/src/runtime/faults/faults.h @@ -37,7 +37,7 @@ class Faults : public QWidget { Q_OBJECT public: - explicit Faults(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent = nullptr); + explicit Faults(QString uri, ToolMenuEntry *tme, QWidget *parent = nullptr); ~Faults(); void pollFaults(); @@ -60,7 +60,7 @@ private Q_SLOTS: void initTutorialProperties(); static QPushButton *createBackButton(); - struct iio_context *ctx; + QString m_uri; Ui::Faults *ui; QPushButton *m_backButton; diff --git a/plugins/swiot/src/runtime/faults/faultsdevice.cpp b/plugins/swiot/src/runtime/faults/faultsdevice.cpp index 1440f026c..a82ba8441 100644 --- a/plugins/swiot/src/runtime/faults/faultsdevice.cpp +++ b/plugins/swiot/src/runtime/faults/faultsdevice.cpp @@ -23,7 +23,7 @@ #include "faultsgroup.h" #include "src/swiot_logging_categories.h" -#include +#include #include #include #include @@ -34,25 +34,27 @@ using namespace scopy::swiot; -FaultsDevice::FaultsDevice(const QString &name, QString path, struct iio_device *device, struct iio_device *swiot, - struct iio_context *context, QVector ®isters, QWidget *parent) +FaultsDevice::FaultsDevice(const QString &name, QString path, QString uri, QVector ®isters, + QWidget *parent) : ui(new Ui::FaultsDevice) , QWidget(parent) + , m_uri(uri) , m_faults_explanation(new QWidget(this)) , m_subsectionSeparator(new scopy::gui::SubsectionSeparator("Faults Explanation", true, this)) , m_name(name.toUpper()) , m_path(std::move(path)) - , m_device(device) - , m_swiot(swiot) - , m_context(context) - , m_cmdQueue(nullptr) , m_faultNumeric(0) , m_registers(registers) { ui->setupUi(this); + Connection *conn = ConnectionProvider::open(m_uri); + m_context = conn->context(); + m_cmdQueue = conn->commandQueue(); + m_device = iio_context_find_device(m_context, name.toStdString().c_str()); + m_swiot = iio_context_find_device(m_context, "swiot"); + ui->reset_button->setProperty("blue_button", QVariant(true)); ui->clear_selection_button->setProperty("blue_button", QVariant(true)); - m_cmdQueue = CommandQueueProvider::GetInstance()->open(m_context); initSpecialFaults(); m_faultsGroup = new FaultsGroup(name, m_path, this); connect(this, &FaultsDevice::specialFaultsUpdated, m_faultsGroup, &FaultsGroup::specialFaultsUpdated); @@ -89,9 +91,7 @@ FaultsDevice::FaultsDevice(const QString &name, QString path, struct iio_device FaultsDevice::~FaultsDevice() { - if(m_cmdQueue) { - CommandQueueProvider::GetInstance()->close(m_context); - } + ConnectionProvider::close(m_uri); delete ui; } diff --git a/plugins/swiot/src/runtime/faults/faultsdevice.h b/plugins/swiot/src/runtime/faults/faultsdevice.h index d967659d9..e336496c7 100644 --- a/plugins/swiot/src/runtime/faults/faultsdevice.h +++ b/plugins/swiot/src/runtime/faults/faultsdevice.h @@ -40,8 +40,8 @@ class FaultsDevice : public QWidget { Q_OBJECT public: - explicit FaultsDevice(const QString &name, QString path, struct iio_device *device, struct iio_device *swiot, - struct iio_context *context, QVector ®isters, QWidget *parent = nullptr); + explicit FaultsDevice(const QString &name, QString path, QString uri, QVector ®isters, + QWidget *parent = nullptr); ~FaultsDevice(); void update(); @@ -70,12 +70,13 @@ private Q_SLOTS: void connectSignalsAndSlots(); void initSpecialFaults(); + QString m_uri; + CommandQueue *m_cmdQueue; + Ui::FaultsDevice *ui; QWidget *m_faults_explanation; scopy::gui::SubsectionSeparator *m_subsectionSeparator; - CommandQueue *m_cmdQueue; - FaultsGroup *m_faultsGroup; QVector m_faultExplanationWidgets; diff --git a/plugins/swiot/src/runtime/faults/faultspage.cpp b/plugins/swiot/src/runtime/faults/faultspage.cpp index fc4048990..300601436 100644 --- a/plugins/swiot/src/runtime/faults/faultspage.cpp +++ b/plugins/swiot/src/runtime/faults/faultspage.cpp @@ -19,21 +19,23 @@ */ #include "faultspage.h" - #include "src/swiot_logging_categories.h" - #include "ui_faultspage.h" +#include using namespace scopy::swiot; -FaultsPage::FaultsPage(struct iio_context *context, QWidget *parent) +FaultsPage::FaultsPage(QString uri, QWidget *parent) : QWidget(parent) - , m_context(context) + , m_uri(uri) , ui(new Ui::FaultsPage) , m_ad74413rFaultsDevice(nullptr) , m_max14906FaultsDevice(nullptr) { ui->setupUi(this); + Connection *conn = ConnectionProvider::open(m_uri); + + m_context = conn->context(); this->setupDevices(); // needed for subsection separator resize @@ -47,7 +49,11 @@ FaultsPage::FaultsPage(struct iio_context *context, QWidget *parent) this->ui->frame->setStyleSheet("QFrame#frame{background-color:#1C1C20;}"); } -FaultsPage::~FaultsPage() { delete ui; } +FaultsPage::~FaultsPage() +{ + delete ui; + ConnectionProvider::close(m_uri); +} void FaultsPage::update() { @@ -64,16 +70,16 @@ void FaultsPage::setupDevices() if(swiot) { if(ad74413r) { QVector faultRegistersAddr = {0x02e}; - m_ad74413rFaultsDevice = new FaultsDevice("ad74413r", ":/swiot/swiot_faults.json", ad74413r, - swiot, m_context, faultRegistersAddr, this); + m_ad74413rFaultsDevice = new FaultsDevice("ad74413r", ":/swiot/swiot_faults.json", m_uri, + faultRegistersAddr, this); } else { qCritical(CAT_SWIOT_FAULTS) << "Error: did not find ad74413r device."; } if(max14906) { QVector faultRegistersAddr = {0x04, 0x05, 0x06, 0x07}; - m_max14906FaultsDevice = new FaultsDevice("max14906", ":/swiot/swiot_faults.json", max14906, - swiot, m_context, faultRegistersAddr, this); + m_max14906FaultsDevice = new FaultsDevice("max14906", ":/swiot/swiot_faults.json", m_uri, + faultRegistersAddr, this); } else { qCritical(CAT_SWIOT_FAULTS) << "Error: did not find max14906 device."; } diff --git a/plugins/swiot/src/runtime/faults/faultspage.h b/plugins/swiot/src/runtime/faults/faultspage.h index 7a3013448..24bc70c86 100644 --- a/plugins/swiot/src/runtime/faults/faultspage.h +++ b/plugins/swiot/src/runtime/faults/faultspage.h @@ -41,12 +41,13 @@ class FaultsPage : public QWidget { Q_OBJECT public: - explicit FaultsPage(struct iio_context *context, QWidget *parent = nullptr); + explicit FaultsPage(QString uri, QWidget *parent = nullptr); ~FaultsPage(); void update(); private: + QString m_uri; struct iio_context *m_context; Ui::FaultsPage *ui; diff --git a/plugins/swiot/src/runtime/max14906/max14906.cpp b/plugins/swiot/src/runtime/max14906/max14906.cpp index 97ca23d8a..c87cb69c7 100644 --- a/plugins/swiot/src/runtime/max14906/max14906.cpp +++ b/plugins/swiot/src/runtime/max14906/max14906.cpp @@ -28,16 +28,16 @@ #include #include -#include +#include #define MAX14906_POLLING_TIME 1000 using namespace scopy::swiot; -Max14906::Max14906(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent) +Max14906::Max14906(QString uri, ToolMenuEntry *tme, QWidget *parent) : QWidget(parent) - , max14906ToolController(new DioController(ctx)) , ui(new Ui::Max14906) + , m_uri(uri) , m_backButton(Max14906::createBackButton()) , m_qTimer(new QTimer(this)) , m_toolView(nullptr) @@ -47,11 +47,15 @@ Max14906::Max14906(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent) , settingsWidgetSeparator() , m_statusLabel(new QLabel(this)) , m_statusContainer(new QWidget(this)) - , m_ctx(ctx) - , m_cmdQueue(CommandQueueProvider::GetInstance()->open(m_ctx)) - , m_readerThread(new ReaderThread(false, m_cmdQueue)) { this->ui->setupUi(this); + m_conn = ConnectionProvider::open(m_uri); + connect(m_conn, &Connection::aboutToBeDestroyed, this, &Max14906::handleConnectionDestroyed); + m_ctx = m_conn->context(); + m_cmdQueue = m_conn->commandQueue(); + max14906ToolController = new DioController(m_ctx); + m_readerThread = new ReaderThread(false, m_cmdQueue); + m_nbDioChannels = max14906ToolController->getChannelCount(); this->setupDynamicUi(this); @@ -131,6 +135,7 @@ scopy::gui::GenericMenu *Max14906::createGeneralSettings(const QString &title, Q void Max14906::connectSignalsAndSlots() { + connect(m_conn, &Connection::aboutToBeDestroyed, m_readerThread, &ReaderThread::handleConnectionDestroyed); connect(this->m_toolView->getRunBtn(), &QPushButton::toggled, this, &Max14906::runButtonToggled); // connect(this->m_toolView->getSingleBtn(), &QPushButton::clicked, this, &Max14906::singleButtonToggled); QObject::connect(m_backButton, &QPushButton::clicked, this, &Max14906::onBackBtnPressed); @@ -158,25 +163,31 @@ void Max14906::onBackBtnPressed() Max14906::~Max14906() { - if(this->m_toolView) { - if(this->m_toolView->getRunBtn()->isChecked()) { - this->m_toolView->getRunBtn()->setChecked(false); - } - if(this->m_readerThread->isRunning()) { - this->m_readerThread->forcedStop(); - this->m_readerThread->wait(); + if(m_conn) { + if(this->m_toolView) { + if(this->m_toolView->getRunBtn()->isChecked()) { + this->m_toolView->getRunBtn()->setChecked(false); + } + if(this->m_readerThread->isRunning()) { + this->m_readerThread->forcedStop(); + this->m_readerThread->wait(); + } + delete m_readerThread; } - delete m_readerThread; - } - if(m_cmdQueue) { - CommandQueueProvider::GetInstance()->close(m_ctx); - m_cmdQueue = nullptr; - m_ctx = nullptr; + ConnectionProvider::close(m_uri); } delete m_toolView; delete ui; } +void Max14906::handleConnectionDestroyed() +{ + qDebug(CAT_SWIOT_MAX14906) << "Max14906 connection destroyed slot"; + m_ctx = nullptr; + m_cmdQueue = nullptr; + m_conn = nullptr; +} + void Max14906::runButtonToggled() { qDebug(CAT_SWIOT_MAX14906) << "Run button clicked"; diff --git a/plugins/swiot/src/runtime/max14906/max14906.h b/plugins/swiot/src/runtime/max14906/max14906.h index dc072a6a2..85835af74 100644 --- a/plugins/swiot/src/runtime/max14906/max14906.h +++ b/plugins/swiot/src/runtime/max14906/max14906.h @@ -31,6 +31,7 @@ #include #include +#include namespace scopy::swiot { #define MAX_NAME "max14906" @@ -41,7 +42,7 @@ class Max14906 : public QWidget { Q_OBJECT public: - explicit Max14906(struct iio_context *ctx, ToolMenuEntry *tme, QWidget *parent = nullptr); + explicit Max14906(QString uri, ToolMenuEntry *tme, QWidget *parent = nullptr); ~Max14906() override; Q_SIGNALS: @@ -49,6 +50,7 @@ class Max14906 : public QWidget public Q_SLOTS: void externalPowerSupply(bool ps); + void handleConnectionDestroyed(); private Q_SLOTS: void runButtonToggled(); @@ -70,8 +72,6 @@ private Q_SLOTS: static QMainWindow *createDockableMainWindow(const QString &title, DioDigitalChannel *digitalChannel, QWidget *parent); - struct iio_context *m_ctx; - QPushButton *m_backButton; QWidget *m_statusContainer; QLabel *m_statusLabel; @@ -87,6 +87,9 @@ private Q_SLOTS: CommandQueue *m_cmdQueue; ReaderThread *m_readerThread; + Connection *m_conn; + struct iio_context *m_ctx; + QString m_uri; QMap m_channelControls; ToolMenuEntry *m_tme; diff --git a/plugins/swiot/src/runtime/readerthread.cpp b/plugins/swiot/src/runtime/readerthread.cpp index 860efa087..ebfdbe07b 100644 --- a/plugins/swiot/src/runtime/readerthread.cpp +++ b/plugins/swiot/src/runtime/readerthread.cpp @@ -45,9 +45,15 @@ ReaderThread::ReaderThread(bool isBuffered, CommandQueue *cmdQueue, QObject *par , bufferCounter(0) , m_running(false) , m_bufferInvalid(false) + , m_deinit(true) {} -ReaderThread::~ReaderThread() { forcedStop(); } +ReaderThread::~ReaderThread() +{ + if(m_deinit) { + forcedStop(); + } +} void ReaderThread::addDioChannel(int index, struct iio_channel *channel) { m_dioChannels.insert(index, channel); } @@ -364,3 +370,9 @@ void ReaderThread::forcedStop() } wait(); } + +void ReaderThread::handleConnectionDestroyed() +{ + m_deinit = false; + requestInterruption(); +} diff --git a/plugins/swiot/src/runtime/readerthread.h b/plugins/swiot/src/runtime/readerthread.h index 08ca6a747..a5a07352a 100644 --- a/plugins/swiot/src/runtime/readerthread.h +++ b/plugins/swiot/src/runtime/readerthread.h @@ -69,7 +69,7 @@ class ReaderThread : public QThread void requestStop(); void forcedStop(); public Q_SLOTS: - + void handleConnectionDestroyed(); void onChnlsChange(QMap chnlsInfo); void onSamplingFreqWritten(int samplingFreq); @@ -89,6 +89,7 @@ private Q_SLOTS: void run() override; bool isBuffered; + bool m_deinit; QMap m_dioChannels; int m_samplingFreq = 4800; diff --git a/plugins/swiot/src/runtime/swiotruntime.cpp b/plugins/swiot/src/runtime/swiotruntime.cpp index 5d70034af..490e6f331 100644 --- a/plugins/swiot/src/runtime/swiotruntime.cpp +++ b/plugins/swiot/src/runtime/swiotruntime.cpp @@ -22,31 +22,23 @@ #include "src/swiot_logging_categories.h" -#include +#include #include #include using namespace scopy::swiot; -SwiotRuntime::SwiotRuntime(struct iio_context *ctx, QObject *parent) +SwiotRuntime::SwiotRuntime(QString uri, QObject *parent) : QObject(parent) - , m_iioCtx(ctx) - , m_cmdQueue(nullptr) + , m_uri(uri) { - if(m_iioCtx) { - m_cmdQueue = CommandQueueProvider::GetInstance()->open(m_iioCtx); - } + Connection *conn = ConnectionProvider::open(m_uri); + m_iioCtx = conn->context(); + m_cmdQueue = conn->commandQueue(); createDevicesMap(); } -SwiotRuntime::~SwiotRuntime() -{ - if(m_cmdQueue) { - CommandQueueProvider::GetInstance()->close(m_iioCtx); - m_cmdQueue = nullptr; - m_iioCtx = nullptr; - } -} +SwiotRuntime::~SwiotRuntime() { ConnectionProvider::close(m_uri); } void SwiotRuntime::onIsRuntimeCtxChanged(bool isRuntimeCtx) { diff --git a/plugins/swiot/src/runtime/swiotruntime.h b/plugins/swiot/src/runtime/swiotruntime.h index 542438ea9..9524cd5f9 100644 --- a/plugins/swiot/src/runtime/swiotruntime.h +++ b/plugins/swiot/src/runtime/swiotruntime.h @@ -37,7 +37,7 @@ class SwiotRuntime : public QObject { Q_OBJECT public: - SwiotRuntime(struct iio_context *ctx, QObject *parent = nullptr); + SwiotRuntime(QString m_uri, QObject *parent = nullptr); ~SwiotRuntime(); public Q_SLOTS: @@ -55,6 +55,7 @@ private Q_SLOTS: void createDevicesMap(); private: + QString m_uri; iio_context *m_iioCtx; QMap m_iioDevices; CommandQueue *m_cmdQueue; diff --git a/plugins/swiot/src/swiotcontroller.cpp b/plugins/swiot/src/swiotcontroller.cpp index 19adeb8a0..0ccff3f44 100644 --- a/plugins/swiot/src/swiotcontroller.cpp +++ b/plugins/swiot/src/swiotcontroller.cpp @@ -22,7 +22,7 @@ #include "src/swiot_logging_categories.h" -#include +#include #include #include @@ -49,7 +49,7 @@ SwiotController::~SwiotController() {} void SwiotController::startPingTask() { - pingTask = new SwiotPingTask(m_iioCtx); + pingTask = new SwiotPingTask(m_conn); pingTimer = new CyclicalTask(pingTask); connect(pingTask, SIGNAL(pingSuccess()), this, SIGNAL(pingSuccess())); connect(pingTask, SIGNAL(pingFailed()), this, SIGNAL(pingFailed())); @@ -66,34 +66,33 @@ void SwiotController::stopPingTask() void SwiotController::startSwitchContextTask(bool isRuntime) { switchCtxTask = new SwiotSwitchCtxTask(uri, isRuntime); - switchCtxTimer = new CyclicalTask(switchCtxTask, this); connect(switchCtxTask, &SwiotSwitchCtxTask::contextSwitched, this, &SwiotController::contextSwitched); - switchCtxTimer->start(1000); + switchCtxTask->start(); } void SwiotController::stopSwitchContextTask() { - switchCtxTimer->stop(); switchCtxTask->requestInterruption(); disconnect(switchCtxTask, &SwiotSwitchCtxTask::contextSwitched, this, &SwiotController::contextSwitched); } -void SwiotController::connectSwiot(iio_context *ctx) +void SwiotController::connectSwiot() { - m_iioCtx = ctx; - if(m_iioCtx) { - m_cmdQueue = CommandQueueProvider::GetInstance()->open(m_iioCtx); - readModeAttribute(); - } + m_conn = ConnectionProvider::open(uri); + m_iioCtx = m_conn->context(); + m_cmdQueue = m_conn->commandQueue(); + readModeAttribute(); } void SwiotController::disconnectSwiot() { - if(m_cmdQueue) { - CommandQueueProvider::GetInstance()->close(m_iioCtx); - m_cmdQueue = nullptr; + if(!m_conn || !m_iioCtx || !m_cmdQueue) { + return; } + ConnectionProvider::close(uri); + m_conn = nullptr; m_iioCtx = nullptr; + m_cmdQueue = nullptr; } void SwiotController::startPowerSupplyTask(QString attribute) @@ -176,7 +175,7 @@ void SwiotController::writeModeCommandFinished(scopy::Command *cmd) } if(tcmd->getReturnCode() >= 0) { Q_EMIT modeAttributeChanged(tcmd->getAttributeValue()); - qInfo(CAT_SWIOT) << R"(Successfully changed the swiot mode)"; + qInfo(CAT_SWIOT) << R"(Successfully written swiot mode)"; } else { qDebug(CAT_SWIOT) << R"(Error, could not change swiot mode)" << tcmd->getReturnCode(); } diff --git a/plugins/swiot/src/swiotcontroller.h b/plugins/swiot/src/swiotcontroller.h index d5cbed9f1..7d11f0dc9 100644 --- a/plugins/swiot/src/swiotcontroller.h +++ b/plugins/swiot/src/swiotcontroller.h @@ -53,7 +53,7 @@ class SwiotController : public QObject void startTemperatureTask(); void stopTemperatureTask(); - void connectSwiot(iio_context *ctx); + void connectSwiot(); void disconnectSwiot(); public Q_SLOTS: @@ -83,12 +83,12 @@ private Q_SLOTS: SwiotReadTemperatureTask *temperatureTask; CommandQueue *m_cmdQueue; iio_context *m_iioCtx; + Connection *m_conn; QString uri; bool m_isRuntimeCtx; bool m_temperatureReadEn; CyclicalTask *pingTimer; - CyclicalTask *switchCtxTimer; CyclicalTask *powerSupplyTimer; CyclicalTask *temperatureTimer; }; diff --git a/plugins/swiot/src/swiotidentifytask.cpp b/plugins/swiot/src/swiotidentifytask.cpp index ccceb33d0..74c233d64 100644 --- a/plugins/swiot/src/swiotidentifytask.cpp +++ b/plugins/swiot/src/swiotidentifytask.cpp @@ -4,35 +4,40 @@ #include -#include -#include +#include #include using namespace scopy::swiot; SwiotIdentifyTask::SwiotIdentifyTask(QString uri, QObject *parent) : QThread(parent) , m_uri(uri) -{} + , m_conn(nullptr) +{ + m_conn = ConnectionProvider::open(m_uri); + if(!m_conn) { + qDebug(CAT_SWIOT) << "Error, no context available for the identify task."; + } + connect(m_conn, &Connection::aboutToBeDestroyed, this, [=, this]() { m_conn = nullptr; }); +} -SwiotIdentifyTask::~SwiotIdentifyTask() {} +SwiotIdentifyTask::~SwiotIdentifyTask() +{ + if(m_conn) { + m_conn = nullptr; + ConnectionProvider::close(m_uri); + } +} void SwiotIdentifyTask::run() { - iio_context *ctx = ContextProvider::GetInstance()->open(m_uri); - - if(!ctx) { + if(!m_conn) { return; } + if(isInterruptionRequested()) { - ContextProvider::GetInstance()->close(m_uri); - return; - } - CommandQueue *commandQueue = CommandQueueProvider::GetInstance()->open(ctx); - if(!commandQueue) { - ContextProvider::GetInstance()->close(m_uri); return; } - iio_device *swiotDevice = iio_context_find_device(ctx, "swiot"); + iio_device *swiotDevice = iio_context_find_device(m_conn->context(), "swiot"); if(swiotDevice) { IioDeviceAttributeWrite *iioAttrWrite = @@ -43,22 +48,15 @@ void SwiotIdentifyTask::run() [=, this](scopy::Command *cmd) { IioDeviceAttributeWrite *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); return; } if(tcmd->getReturnCode() < 0) { qCritical(CAT_SWIOT) << "Error, could not identify swiot, error code" << tcmd->getReturnCode(); } - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); }, Qt::QueuedConnection); - commandQueue->enqueue(iioAttrWrite); - } else { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); + m_conn->commandQueue()->enqueue(iioAttrWrite); } } diff --git a/plugins/swiot/src/swiotidentifytask.h b/plugins/swiot/src/swiotidentifytask.h index b94b6882a..720080b53 100644 --- a/plugins/swiot/src/swiotidentifytask.h +++ b/plugins/swiot/src/swiotidentifytask.h @@ -2,6 +2,8 @@ #define SWIOTIDENTIFYTASK_H #include +#include + namespace scopy::swiot { class SwiotIdentifyTask : public QThread { @@ -12,6 +14,7 @@ class SwiotIdentifyTask : public QThread private: QString m_uri; + Connection *m_conn; }; } // namespace scopy::swiot #endif // SWIOTIDENTIFYTASK_H diff --git a/plugins/swiot/src/swiotpingtask.cpp b/plugins/swiot/src/swiotpingtask.cpp index d59c76e93..34a5683e1 100644 --- a/plugins/swiot/src/swiotpingtask.cpp +++ b/plugins/swiot/src/swiotpingtask.cpp @@ -4,37 +4,34 @@ #include -#include +#include #include using namespace scopy; using namespace scopy::swiot; -SwiotPingTask::SwiotPingTask(iio_context *c, QObject *parent) +SwiotPingTask::SwiotPingTask(Connection *conn, QObject *parent) : QThread(parent) - , c(c) -{} +{ + c = conn; +} SwiotPingTask::~SwiotPingTask() {} void SwiotPingTask::run() { - enabled = true; - CommandQueue *commandQueue = CommandQueueProvider::GetInstance()->open(c); - if(!commandQueue || !c) { + if(!c) { Q_EMIT pingFailed(); return; } - auto dev = iio_context_find_device(c, "sw_trig"); + auto dev = iio_context_find_device(c->context(), "sw_trig"); if(dev) { Command *getTriggerCommand = new IioDeviceGetTrigger(dev, nullptr); connect(getTriggerCommand, &scopy::Command::finished, this, &SwiotPingTask::getTriggerCommandFinished, Qt::QueuedConnection); - commandQueue->enqueue(getTriggerCommand); - } else { - CommandQueueProvider::GetInstance()->close(c); + c->commandQueue()->enqueue(getTriggerCommand); } } @@ -42,7 +39,6 @@ void SwiotPingTask::getTriggerCommandFinished(scopy::Command *cmd) { IioDeviceGetTrigger *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(c); return; } int ret = tcmd->getReturnCode(); @@ -51,7 +47,6 @@ void SwiotPingTask::getTriggerCommandFinished(scopy::Command *cmd) } else { Q_EMIT pingFailed(); } - CommandQueueProvider::GetInstance()->close(c); } #include "moc_swiotpingtask.cpp" diff --git a/plugins/swiot/src/swiotpingtask.h b/plugins/swiot/src/swiotpingtask.h index 57ce920f0..17a4e2441 100644 --- a/plugins/swiot/src/swiotpingtask.h +++ b/plugins/swiot/src/swiotpingtask.h @@ -8,13 +8,14 @@ #include #include +#include namespace scopy::swiot { class SwiotPingTask : public QThread { Q_OBJECT public: - SwiotPingTask(iio_context *c, QObject *parent = nullptr); + SwiotPingTask(Connection *conn, QObject *parent = nullptr); ~SwiotPingTask(); virtual void run() override; Q_SIGNALS: @@ -22,7 +23,8 @@ class SwiotPingTask : public QThread void pingFailed(); protected: - iio_context *c; + QString m_uri; + Connection *c; bool enabled; private Q_SLOTS: diff --git a/plugins/swiot/src/swiotplugin.cpp b/plugins/swiot/src/swiotplugin.cpp index be44a56d3..75f7b272b 100644 --- a/plugins/swiot/src/swiotplugin.cpp +++ b/plugins/swiot/src/swiotplugin.cpp @@ -34,7 +34,7 @@ #include #include -#include +#include using namespace scopy::swiot; @@ -70,14 +70,13 @@ bool SWIOTPlugin::loadPage() }); connect(m_btnTutorial, &QPushButton::clicked, this, &SWIOTPlugin::startTutorial); - auto cp = ContextProvider::GetInstance(); - struct iio_context *context = cp->open(m_param); + Connection *conn = ConnectionProvider::open(m_param); - ssize_t attributeCount = iio_context_get_attrs_count(context); + ssize_t attributeCount = iio_context_get_attrs_count(conn->context()); for(int i = 0; i < attributeCount; ++i) { const char *name; const char *value; - int ret = iio_context_get_attr(context, i, &name, &value); + int ret = iio_context_get_attr(conn->context(), i, &name, &value); if(ret < 0) { qWarning(CAT_SWIOT) << "Could not read attribute with index:" << i; continue; @@ -86,7 +85,7 @@ bool SWIOTPlugin::loadPage() m_infoPage->update(name, value); } - cp->close(m_param); + ConnectionProvider::close(m_param); m_page->ensurePolished(); return true; @@ -141,30 +140,25 @@ bool SWIOTPlugin::compatible(QString m_param, QString category) { m_name = "SWIOT1L"; bool ret = false; - auto &&cp = ContextProvider::GetInstance(); + Connection *conn = ConnectionProvider::open(m_param); - iio_context *ctx = cp->open(m_param); - - if(!ctx) { + if(!conn) { qWarning(CAT_SWIOT) << "No context available for swiot"; return false; } - iio_device *swiotDevice = iio_context_find_device(ctx, "swiot"); + iio_device *swiotDevice = iio_context_find_device(conn->context(), "swiot"); if(swiotDevice) { ret = true; } - cp->close(m_param); + ConnectionProvider::close(m_param); return ret; } void SWIOTPlugin::setupToolList() { - auto &&cp = ContextProvider::GetInstance(); - iio_context *ctx = cp->open(m_param); - m_infoPage->enableTemperatureReadBtn(m_isRuntime); m_swiotController->startTemperatureTask(); @@ -191,11 +185,11 @@ void SWIOTPlugin::setupToolList() } if(m_isRuntime) { - ad74413rTme->setTool(new swiot::Ad74413r(ctx, ad74413rTme)); - max14906Tme->setTool(new swiot::Max14906(ctx, max14906Tme)); - faultsTme->setTool(new swiot::Faults(ctx, faultsTme)); + ad74413rTme->setTool(new swiot::Ad74413r(m_param, ad74413rTme)); + max14906Tme->setTool(new swiot::Max14906(m_param, max14906Tme)); + faultsTme->setTool(new swiot::Faults(m_param, faultsTme)); } else { - configTme->setTool(new swiot::SwiotConfig(ctx)); + configTme->setTool(new swiot::SwiotConfig(m_param)); } connect(dynamic_cast(configTme->tool()), &SwiotConfig::writeModeAttribute, m_swiotController, @@ -204,6 +198,7 @@ void SWIOTPlugin::setupToolList() dynamic_cast(configTme->tool()), &SwiotConfig::modeAttributeChanged); connect(dynamic_cast(configTme->tool()), &SwiotConfig::configBtnPressed, this, &SWIOTPlugin::startCtxSwitch); + connect(dynamic_cast(ad74413rTme->tool()), &Ad74413r::backBtnPressed, m_runtime, &SwiotRuntime::onBackBtnPressed); connect(dynamic_cast(max14906Tme->tool()), &Max14906::backBtnPressed, m_runtime, @@ -226,7 +221,6 @@ void SWIOTPlugin::setupToolList() } else { requestTool(ad74413rTme->id()); } - cp->close(m_param); } void SWIOTPlugin::onIsRuntimeCtxChanged(bool isRuntimeCtx) @@ -237,10 +231,12 @@ void SWIOTPlugin::onIsRuntimeCtxChanged(bool isRuntimeCtx) bool SWIOTPlugin::onConnect() { - auto &&cp = ContextProvider::GetInstance(); - iio_context *ctx = cp->open(m_param); + Connection *conn = ConnectionProvider::open(m_param); + if(!conn) { + return false; + } - m_runtime = new SwiotRuntime(ctx, this); + m_runtime = new SwiotRuntime(m_param, this); connect(m_runtime, &SwiotRuntime::writeModeAttribute, m_swiotController, &SwiotController::writeModeAttribute); connect(m_swiotController, &SwiotController::modeAttributeChanged, m_runtime, &SwiotRuntime::modeAttributeChanged); @@ -248,7 +244,7 @@ bool SWIOTPlugin::onConnect() connect(m_swiotController, &SwiotController::isRuntimeCtxChanged, m_runtime, &SwiotRuntime::onIsRuntimeCtxChanged); - m_swiotController->connectSwiot(ctx); + m_swiotController->connectSwiot(); m_swiotController->startPingTask(); m_swiotController->startPowerSupplyTask("ext_psu"); m_btnTutorial->setEnabled(true); @@ -316,8 +312,7 @@ bool SWIOTPlugin::onDisconnect() m_runtime = nullptr; } - ContextProvider *cp = ContextProvider::GetInstance(); - cp->close(m_param); + ConnectionProvider::close(m_param); return true; } diff --git a/plugins/swiot/src/swiotreadtemperaturetask.cpp b/plugins/swiot/src/swiotreadtemperaturetask.cpp index becef4116..2f98b976f 100644 --- a/plugins/swiot/src/swiotreadtemperaturetask.cpp +++ b/plugins/swiot/src/swiotreadtemperaturetask.cpp @@ -22,8 +22,7 @@ #include "src/swiot_logging_categories.h" -#include -#include +#include #include #include @@ -35,36 +34,24 @@ using namespace scopy::swiot; SwiotReadTemperatureTask::SwiotReadTemperatureTask(QString uri, QObject *parent) : QThread(parent) , m_uri(std::move(uri)) - , m_context(nullptr) , m_channel(nullptr) , m_device(nullptr) - , m_commandQueue(nullptr) + , m_conn(nullptr) , m_raw(0.0) , m_scale(0.0) , m_offset(0.0) { - m_context = ContextProvider::GetInstance()->open(m_uri); - - if(!m_context) { - qDebug(CAT_SWIOT) << "Error, empty context received by temperature task."; + m_conn = ConnectionProvider::open(m_uri); + if(!m_conn) { + qDebug(CAT_SWIOT) << "Error, no context available for the temperature task."; return; } + connect(m_conn, &Connection::aboutToBeDestroyed, this, [=, this]() { m_conn = nullptr; }); - m_device = iio_context_find_device(m_context, DEVICE_NAME); + m_device = iio_context_find_device(m_conn->context(), DEVICE_NAME); if(!m_device) { qDebug(CAT_SWIOT) << "Error, could not find" << DEVICE_NAME << "from the given context. Temperature not available."; - ContextProvider::GetInstance()->close(m_uri); - return; - } - - if(isInterruptionRequested()) { - return; - } - - m_commandQueue = CommandQueueProvider::GetInstance()->open(m_context); - if(!m_commandQueue) { - ContextProvider::GetInstance()->close(m_uri); return; } @@ -72,7 +59,6 @@ SwiotReadTemperatureTask::SwiotReadTemperatureTask(QString uri, QObject *parent) if(!m_channel) { qDebug(CAT_SWIOT) << "Error, could not find channel " << CHANNEL_NAME << "from device" << DEVICE_NAME << ". Temperature not available."; - ContextProvider::GetInstance()->close(m_uri); return; } Command *attrReadScale = new IioChannelAttributeRead(m_channel, "scale", nullptr, true); @@ -82,11 +68,17 @@ SwiotReadTemperatureTask::SwiotReadTemperatureTask(QString uri, QObject *parent) Qt::QueuedConnection); connect(attrReadOffset, &scopy::Command::finished, this, &SwiotReadTemperatureTask::readOffsetCommandFinished, Qt::QueuedConnection); - m_commandQueue->enqueue(attrReadScale); - m_commandQueue->enqueue(attrReadOffset); + m_conn->commandQueue()->enqueue(attrReadScale); + m_conn->commandQueue()->enqueue(attrReadOffset); } -SwiotReadTemperatureTask::~SwiotReadTemperatureTask() { m_commandQueue = nullptr; } +SwiotReadTemperatureTask::~SwiotReadTemperatureTask() +{ + if(m_conn) { + m_conn = nullptr; + ConnectionProvider::close(m_uri); + } +} void SwiotReadTemperatureTask::run() { @@ -98,19 +90,16 @@ void SwiotReadTemperatureTask::run() connect(attrReadRaw, &scopy::Command::finished, this, &SwiotReadTemperatureTask::readRawCommandFinished, Qt::QueuedConnection); - m_commandQueue->enqueue(attrReadRaw); + m_conn->commandQueue()->enqueue(attrReadRaw); } void SwiotReadTemperatureTask::readRawCommandFinished(Command *cmd) { if(isInterruptionRequested()) { - ContextProvider::GetInstance()->close(m_uri); return; } IioChannelAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); return; } if(tcmd->getReturnCode() >= 0) { @@ -126,8 +115,6 @@ void SwiotReadTemperatureTask::readRawCommandFinished(Command *cmd) } else { qDebug(CAT_SWIOT) << "Error, could not read \"raw\" attribute from " << DEVICE_NAME << ". Temperature not available."; - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); } } @@ -135,8 +122,6 @@ void SwiotReadTemperatureTask::readScaleCommandFinished(Command *cmd) { IioChannelAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); return; } if(tcmd->getReturnCode() >= 0) { @@ -149,8 +134,6 @@ void SwiotReadTemperatureTask::readScaleCommandFinished(Command *cmd) } else { qDebug(CAT_SWIOT) << "Error, could not read \"scale\" attribute from " << DEVICE_NAME << ". Temperature not available."; - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); } } @@ -158,8 +141,6 @@ void SwiotReadTemperatureTask::readOffsetCommandFinished(Command *cmd) { IioChannelAttributeRead *tcmd = dynamic_cast(cmd); if(!tcmd) { - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); return; } if(tcmd->getReturnCode() >= 0) { @@ -173,8 +154,6 @@ void SwiotReadTemperatureTask::readOffsetCommandFinished(Command *cmd) qDebug(CAT_SWIOT) << "Error, could not read \"offset\" attribute from " << DEVICE_NAME << ". Temperature not available."; } - CommandQueueProvider::GetInstance()->close(m_context); - ContextProvider::GetInstance()->close(m_uri); } #include "moc_swiotreadtemperaturetask.cpp" diff --git a/plugins/swiot/src/swiotreadtemperaturetask.h b/plugins/swiot/src/swiotreadtemperaturetask.h index 7cb44701e..1877e5a2d 100644 --- a/plugins/swiot/src/swiotreadtemperaturetask.h +++ b/plugins/swiot/src/swiotreadtemperaturetask.h @@ -26,7 +26,7 @@ #include #include -#include +#include namespace scopy::swiot { class SwiotReadTemperatureTask : public QThread @@ -47,10 +47,9 @@ private Q_SLOTS: private: QString m_uri; - struct iio_context *m_context; struct iio_channel *m_channel; struct iio_device *m_device; - CommandQueue *m_commandQueue; + Connection *m_conn; double m_raw, m_scale, m_offset; }; } // namespace scopy::swiot diff --git a/plugins/swiot/src/swiotswitchctxtask.cpp b/plugins/swiot/src/swiotswitchctxtask.cpp index 03599530e..3704115d5 100644 --- a/plugins/swiot/src/swiotswitchctxtask.cpp +++ b/plugins/swiot/src/swiotswitchctxtask.cpp @@ -22,8 +22,7 @@ #include "src/swiot_logging_categories.h" -#include -#include +#include #include using namespace scopy::swiot; @@ -32,54 +31,71 @@ SwiotSwitchCtxTask::SwiotSwitchCtxTask(QString uri, bool wasRuntime) : QThread() , m_uri(uri) , m_wasRuntime(wasRuntime) -{} + , m_conn(nullptr) +{ + connect(this, &SwiotSwitchCtxTask::contextSwitchFailed, this, [=, this]() { start(); }); +} + +SwiotSwitchCtxTask::~SwiotSwitchCtxTask() {} void SwiotSwitchCtxTask::run() { - iio_context *ctx = ContextProvider::GetInstance()->open(m_uri); - if(!ctx) { - return; - } - if(isInterruptionRequested()) { - ContextProvider::GetInstance()->close(m_uri); + m_conn = ConnectionProvider::open(m_uri); + if(!m_conn) { return; } + connect(m_conn, &Connection::aboutToBeDestroyed, this, [=, this]() { + if(m_conn) { + ConnectionProvider::close(m_uri); + m_conn = nullptr; + } + }); - CommandQueue *commandQueue = CommandQueueProvider::GetInstance()->open(ctx); - if(!commandQueue) { - ContextProvider::GetInstance()->close(m_uri); + if(isInterruptionRequested()) { + ConnectionProvider::close(m_uri); + m_conn = nullptr; return; } - iio_device *swiotDevice = iio_context_find_device(ctx, "swiot"); + iio_device *swiotDevice = iio_context_find_device(m_conn->context(), "swiot"); if(swiotDevice) { IioDeviceAttributeRead *iioAttrRead = new IioDeviceAttributeRead(swiotDevice, "mode", nullptr, true); - connect( - iioAttrRead, &scopy::Command::finished, this, - [=, this](scopy::Command *cmd) { - IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); - if(!tcmd) { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); - return; - } - char *readMode = tcmd->getResult(); - if(tcmd->getReturnCode() >= 0) { - if((m_wasRuntime && (strcmp(readMode, "config") == 0)) || - (!m_wasRuntime && (strcmp(readMode, "runtime") == 0))) { - qDebug(CAT_SWIOT) << "Context has been changed"; - Q_EMIT contextSwitched(); - } - } - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); - }, + connect(iioAttrRead, &scopy::Command::finished, this, &SwiotSwitchCtxTask::onReadModeFinished, Qt::QueuedConnection); + connect(m_conn, &scopy::Connection::aboutToBeDestroyed, this, [=, this]() { + disconnect(iioAttrRead, &scopy::Command::finished, this, + &SwiotSwitchCtxTask::onReadModeFinished); + }); - commandQueue->enqueue(iioAttrRead); + m_conn->commandQueue()->enqueue(iioAttrRead); } else { - CommandQueueProvider::GetInstance()->close(ctx); - ContextProvider::GetInstance()->close(m_uri); + ConnectionProvider::close(m_uri); + } +} + +void SwiotSwitchCtxTask::onReadModeFinished(scopy::Command *cmd) +{ + IioDeviceAttributeRead *tcmd = dynamic_cast(cmd); + if(!tcmd) { + Q_EMIT contextSwitchFailed(); + ConnectionProvider::close(m_uri); + return; + } + char *readMode = tcmd->getResult(); + if(tcmd->getReturnCode() >= 0) { + if((m_wasRuntime && (strcmp(readMode, "config") == 0)) || + (!m_wasRuntime && (strcmp(readMode, "runtime") == 0))) { + qDebug(CAT_SWIOT) << "Context has been changed"; + if(m_conn) { + m_conn = nullptr; + ConnectionProvider::close(m_uri); + } + Q_EMIT contextSwitched(); + } + } else if(m_conn) { + Q_EMIT contextSwitchFailed(); + m_conn = nullptr; + ConnectionProvider::close(m_uri); } } diff --git a/plugins/swiot/src/swiotswitchctxtask.h b/plugins/swiot/src/swiotswitchctxtask.h index 2885cc7a9..fd2da2e00 100644 --- a/plugins/swiot/src/swiotswitchctxtask.h +++ b/plugins/swiot/src/swiotswitchctxtask.h @@ -23,6 +23,7 @@ #include #include +#include namespace scopy::swiot { class SwiotSwitchCtxTask : public QThread @@ -30,14 +31,20 @@ class SwiotSwitchCtxTask : public QThread Q_OBJECT public: SwiotSwitchCtxTask(QString uri, bool wasRuntime); + ~SwiotSwitchCtxTask(); void run() override; Q_SIGNALS: void contextSwitched(); + void contextSwitchFailed(); + +private Q_SLOTS: + void onReadModeFinished(scopy::Command *cmd); private: QString m_uri; bool m_wasRuntime; + Connection *m_conn; }; } // namespace scopy::swiot