Skip to content

Commit

Permalink
ContextBuilder: solve context close bug using reference count
Browse files Browse the repository at this point in the history
- added reference count to ContextBuilder to keep track of how many
  external references to the M2k context are present. When the last
  reference is removed, the M2k context can be closed.
- contexts should be closed in the reverse order they were opened:
  contextClose() -> iio_context_destroy() to avoid dangling pointers.

Signed-off-by: Adrian Stanea <Adrian.Stanea@analog.com>
  • Loading branch information
Adrian-Stanea authored and AlexandraTrifan committed Jan 29, 2024
1 parent d34e102 commit da2ce29
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 14 deletions.
5 changes: 5 additions & 0 deletions include/libm2k/contextbuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ class LIBM2K_API ContextBuilder {
bool ownsContext = false);
static bool m_disable_logging;

static std::map<std::string, int> reference_count;
static void incrementReferenceCount(std::string uri);
static void decrementReferenceCount(std::string uri);
static bool checkLastReference(std::string uri);
static Context* searchInConnectedDevices(std::string uri);
};

/**
Expand Down
79 changes: 65 additions & 14 deletions src/contextbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ std::map<ContextTypes, std::string> ContextBuilder::m_dev_name_map = {
};

bool ContextBuilder::m_disable_logging = true;
std::map<std::string, int> ContextBuilder::reference_count = {};

ContextBuilder::ContextBuilder()
{
Expand Down Expand Up @@ -148,19 +149,55 @@ Context* ContextBuilder::buildContext(ContextTypes type, std::string uri,
}
}

Context* ContextBuilder::contextOpen(const char *uri)
void ContextBuilder::incrementReferenceCount(std::string uri)
{
if (m_disable_logging) {
enableLogging(false);
if (reference_count.find(uri) != reference_count.end()) {
reference_count[uri]++;
} else {
reference_count.emplace(uri, 1);
}
LIBM2K_LOG(INFO, "libm2k version: " + getVersion());
}

void ContextBuilder::decrementReferenceCount(std::string uri)
{
if (reference_count.find(uri) != reference_count.end()) {
reference_count[uri]--;
}
}

bool ContextBuilder::checkLastReference(std::string uri)
{
if (reference_count.find(uri) != reference_count.end()) {
return (reference_count[uri] == 0);
}
return false;
}

for (Context* dev : s_connectedDevices) {
if (dev->getUri() == std::string(uri)) {
Context* ContextBuilder::searchInConnectedDevices(std::string uri)
{
for (auto dev : s_connectedDevices) {
if (dev->getUri() == uri) {
return dev;
}
}
return nullptr;
}


Context* ContextBuilder::contextOpen(const char *uri)
{
Context* dev = nullptr;
if (m_disable_logging) {
enableLogging(false);
}
LIBM2K_LOG(INFO, "libm2k version: " + getVersion());
// use saved device is possible
dev = searchInConnectedDevices(uri);
if (dev) {
incrementReferenceCount(uri);
return dev;
}
// create and save device during first call
struct iio_context* ctx = iio_create_context_from_uri(uri);
if (!ctx) {
return nullptr;
Expand All @@ -182,14 +219,16 @@ Context* ContextBuilder::contextOpen(const char *uri)

ContextTypes dev_type = ContextBuilder::identifyContext(ctx);

Context* dev = buildContext(dev_type, std::string(uri), ctx, true, true);
dev = buildContext(dev_type, std::string(uri), ctx, true, true);
s_connectedDevices.push_back(dev);
incrementReferenceCount(uri);

return dev;
}

Context* ContextBuilder::contextOpen(struct iio_context* ctx, const char* uri)
{
Context* dev = nullptr;
if (m_disable_logging) {
enableLogging(false);
}
Expand All @@ -210,21 +249,22 @@ Context* ContextBuilder::contextOpen(struct iio_context* ctx, const char* uri)
if (hw_fw_version != nullptr) {
LIBM2K_LOG(INFO, "Firmware version: " + std::string(hw_fw_version));
}

for (Context* dev : s_connectedDevices) {
if (dev->getUri() == std::string(uri)) {
return dev;
}
// use saved device is possible
dev = searchInConnectedDevices(uri);
if (dev) {
incrementReferenceCount(uri);
return dev;
}

if (!ctx) {
return nullptr;
}

// create and save device during first call
ContextTypes dev_type = ContextBuilder::identifyContext(ctx);

Context* dev = buildContext(dev_type, std::string(uri), ctx, true);
dev = buildContext(dev_type, std::string(uri), ctx, true);
s_connectedDevices.push_back(dev);
incrementReferenceCount(uri);

return dev;
}
Expand Down Expand Up @@ -288,6 +328,17 @@ M2k *ContextBuilder::m2kOpen()

void ContextBuilder::contextClose(Context* device, bool deinit)
{
auto uri = device->getUri();
if (searchInConnectedDevices(uri) == nullptr) {
return;
}
decrementReferenceCount(uri);
bool isLastReference = checkLastReference(uri);
if (!isLastReference) {
return;
}

reference_count.erase(uri);
s_connectedDevices.erase(std::remove(s_connectedDevices.begin(),
s_connectedDevices.end(),
device), s_connectedDevices.end());
Expand Down

0 comments on commit da2ce29

Please sign in to comment.