Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Device: added makeShared(), returns auto-unmaking device shared_ptrs #418

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 52 additions & 1 deletion include/SoapySDR/Device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
/// \copyright
/// Copyright (c) 2014-2019 Josh Blum
/// Copyright (c) 2016-2016 Bastille Networks
/// 2021 Nicholas Corgan
/// 2021-2023 Nicholas Corgan
/// SPDX-License-Identifier: BSL-1.0
///

Expand All @@ -19,6 +19,7 @@
#include <string>
#include <complex>
#include <cstddef> //size_t
#include <memory>

namespace SoapySDR
{
Expand All @@ -33,6 +34,8 @@ class SOAPY_SDR_API Device
{
public:

using SPtr = std::shared_ptr<Device>;

//! virtual destructor for inheritance
virtual ~Device(void);

Expand Down Expand Up @@ -73,6 +76,30 @@ class SOAPY_SDR_API Device
*/
static Device *make(const std::string &args);

/*!
* Make a new Device object given device construction args.
* The device pointer will be stored in a table so subsequent calls
* with the same arguments will produce the same device.
* On destruction of the shared_ptr, unmake() will automatically be
* called.
*
* \param args a markup string of key/value arguments
* \return a shared pointer to a new Device object
*/
static SPtr makeShared(const Kwargs &args = Kwargs());

/*!
* Make a new Device object given device construction args.
* The device pointer will be stored in a table so subsequent calls
* with the same arguments will produce the same device.
* On destruction of the shared_ptr, unmake() will automatically be
* called.
*
* \param args a markup string of key/value arguments
* \return a shared pointer to a new Device object
*/
static SPtr makeShared(const std::string &args);

/*!
* Unmake or release a device object handle.
*
Expand Down Expand Up @@ -104,6 +131,30 @@ class SOAPY_SDR_API Device
*/
static std::vector<Device *> make(const std::vector<std::string> &argsList);

/*!
* Create a list of devices from a list of construction arguments.
* This is a convenience call to parallelize device construction,
* and is fundamentally a parallel for loop of makeShared(Kwargs).
* On destruction of the vector, unmake() will automatically be
* called for each device.
*
* \param argsList a list of device arguments per each device
* \return a list of shared device pointers per each specified argument
*/
static std::vector<SPtr> makeShared(const KwargsList &argsList);

/*!
* Create a list of devices from a list of construction arguments.
* This is a convenience call to parallelize device construction,
* and is fundamentally a parallel for loop of makeShared(Kwargs).
* On destruction of the vector, unmake() will automatically be
* called for each device.
*
* \param argsList a list of device arguments per each device
* \return a list of shared device pointers per each specified argument
*/
static std::vector<SPtr> makeShared(const std::vector<std::string> &argsList);

/*!
* Unmake or release a list of device handles.
* This is a convenience call to parallelize device destruction,
Expand Down
6 changes: 5 additions & 1 deletion include/SoapySDR/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
* And <i>extra</i> is empty for releases but set on development branches.
* The ABI should remain constant across patch releases of the library.
*/
#define SOAPY_SDR_ABI_VERSION "0.8-3"
#define SOAPY_SDR_ABI_VERSION "0.8-4"

/*!
* Compatibility define for GPIO access API with masks
Expand Down Expand Up @@ -173,6 +173,10 @@
*/
#define SOAPY_SDR_API_HAS_GET_LOG_LEVEL

/*!
* Compatibility define for shared_ptr factory functions
*/

#ifdef __cplusplus
extern "C" {
#endif
Expand Down
67 changes: 67 additions & 0 deletions lib/Factory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,16 @@ static DeviceCounts &getDeviceCounts(void)
return table;
}

using Deleter = void(*)(SoapySDR::Device *);

static inline Deleter getDeviceDeleter(void)
{
return [](SoapySDR::Device *device)
{
SoapySDR::Device::unmake(device);
};
}

void automaticLoadModules(void);

SoapySDR::KwargsList SoapySDR::Device::enumerate(const Kwargs &args)
Expand Down Expand Up @@ -204,6 +214,29 @@ SoapySDR::Device *SoapySDR::Device::make(const std::string &args)
return make(KwargsFromString(args));
}

//
// makeShared
//

template <typename Args>
static inline SoapySDR::Device::SPtr makeSharedCommon(const Args &args)
{
return SoapySDR::Device::SPtr(
SoapySDR::Device::make(args),
getDeviceDeleter()
);
}

SoapySDR::Device::SPtr SoapySDR::Device::makeShared(const Kwargs &args)
{
return makeSharedCommon(args);
}

SoapySDR::Device::SPtr SoapySDR::Device::makeShared(const std::string &args)
{
return makeSharedCommon(args);
}

void SoapySDR::Device::unmake(Device *device)
{
if (device == nullptr) return; //safe to unmake a null device
Expand Down Expand Up @@ -280,6 +313,40 @@ std::vector<SoapySDR::Device *> SoapySDR::Device::make(const std::vector<std::st
return make(kwargsList);
}

//
// Parallel makeShared
//

template <typename Args>
static inline std::vector<SoapySDR::Device::SPtr> makeSharedParallelCommon(const std::vector<Args> &argsList)
{
auto rawPtrs = SoapySDR::Device::make(argsList);
std::vector<SoapySDR::Device::SPtr> sharedPtrs;
std::transform(
rawPtrs.begin(),
rawPtrs.end(),
std::back_inserter(sharedPtrs),
[](SoapySDR::Device *device)
{
return SoapySDR::Device::SPtr(
device,
getDeviceDeleter()
);
});

return sharedPtrs;
}

std::vector<SoapySDR::Device::SPtr> SoapySDR::Device::makeShared(const KwargsList &argsList)
{
return makeSharedParallelCommon(argsList);
}

std::vector<SoapySDR::Device::SPtr> SoapySDR::Device::makeShared(const std::vector<std::string> &argsList)
{
return makeSharedParallelCommon(argsList);
}

void SoapySDR::Device::unmake(const std::vector<Device *> &devices)
{
std::vector<std::future<void>> futures;
Expand Down
5 changes: 4 additions & 1 deletion swig/soapy_common.i
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2021-2022 Nicholas Corgan
// Copyright (c) 2021-2023 Nicholas Corgan
// SPDX-License-Identifier: BSL-1.0

////////////////////////////////////////////////////////////////////////
Expand All @@ -18,6 +18,9 @@
// Common ignores
////////////////////////////////////////////////////////////////////////

// SoapySDR/Device.hpp
%ignore SoapySDR::Device::makeShared;

// SoapySDR/Errors.h
%ignore SoapySDR_errToStr;

Expand Down