Skip to content

Commit

Permalink
Connection: Add a new object to handle the iio_context and CommandQueue.
Browse files Browse the repository at this point in the history
The open() and close() calls are done through a singleton
ConnectionProvider while the reference count is handled inside the
Connection object.

This should replace the existing ContextProvider.

Signed-off-by: AlexandraTrifan <[email protected]>
  • Loading branch information
AlexandraTrifan committed Oct 19, 2023
1 parent 16b4aec commit 045f606
Show file tree
Hide file tree
Showing 6 changed files with 471 additions and 0 deletions.
65 changes: 65 additions & 0 deletions iioutil/include/iioutil/connection.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#ifndef CONNECTION_H
#define CONNECTION_H
#include "scopy-iioutil_export.h"
#include "commandqueue.h"
#include <iio.h>
#include <QObject>

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
39 changes: 39 additions & 0 deletions iioutil/include/iioutil/connectionprovider.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
#ifndef CONNECTIONPROVIDER_H
#define CONNECTIONPROVIDER_H

#include "scopy-iioutil_export.h"
#include "connection.h"

#include <QObject>
#include <QMap>
#include <mutex>

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<QString, Connection *> map;
};
} // namespace scopy

#endif // CONNECTIONPROVIDER_H
64 changes: 64 additions & 0 deletions iioutil/src/connection.cpp
Original file line number Diff line number Diff line change
@@ -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"
93 changes: 93 additions & 0 deletions iioutil/src/connectionprovider.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "connectionprovider.h"
#include <QLoggingCategory>
#include <QApplication>

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<std::mutex> 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<std::mutex> 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<std::mutex> lock(mutex_);
if(map.contains(uri)) {
map.value(uri)->closeAll();
}
_closeAndRemove(uri);
}

void ConnectionProvider::_close(QString uri)
{
std::lock_guard<std::mutex> 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"
1 change: 1 addition & 0 deletions iioutil/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ cmake_minimum_required(VERSION 3.5)
include(ScopyTest)

setup_scopy_tests(iiocommandqueue)
setup_scopy_tests(connectionprovider)
Loading

0 comments on commit 045f606

Please sign in to comment.