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 committed Oct 3, 2023
1 parent 7b31a3d commit 03943ba
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 14 deletions.
4 changes: 4 additions & 0 deletions include/libm2k/contextbuilder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,10 @@ 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 bool decrementReferenceCount(std::string uri);
static Context* searchInConnectedDevices(std::string uri);
};

/**
Expand Down
72 changes: 58 additions & 14 deletions src/contextbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,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 @@ -158,19 +159,50 @@ 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.count(uri) == 0) {
reference_count[uri] = 1;
} else {
reference_count[uri]++;
}
}

bool ContextBuilder::decrementReferenceCount(std::string uri)
{
reference_count[uri]--;
if(reference_count[uri] == 0) {
reference_count.erase(uri);
return true;
}
LIBM2K_LOG(INFO, "libm2k version: " + getVersion());
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 @@ -192,14 +224,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 @@ -220,21 +254,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 @@ -298,6 +333,15 @@ M2k *ContextBuilder::m2kOpen()

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

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

0 comments on commit 03943ba

Please sign in to comment.