Skip to content

Commit

Permalink
Switch to std::shared_ptr from boost::shared_ptr and provide a BOOST_…
Browse files Browse the repository at this point in the history
…… (#90)

…DLL_USE_BOOST_SHARED_PTR compatibility macro to restore the old behavior

Fixes boostorg#75
  • Loading branch information
apolukhin authored Jan 30, 2025
1 parent 841e188 commit 013633d
Show file tree
Hide file tree
Showing 11 changed files with 121 additions and 86 deletions.
28 changes: 15 additions & 13 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,42 @@ on:

env:
UBSAN_OPTIONS: print_stacktrace=1
# ASAN complains:
# ==5457==ERROR: AddressSanitizer: odr-violation (0x7f6112f03b00):
# [1] size=8 'rvalue_reference_to_internal_integer' test/test_library.cpp:122:7 in bin.v2/libs/dll/test/gcc-14/debug/x86_64/cxxstd-17-iso/threading-multi/visibility-hidden/libtest_library.so
# [2] size=8 'rvalue_reference_to_internal_integer' test/test_library.cpp:122:7 in bin.v2/libs/dll/test/gcc-14/debug/x86_64/cxxstd-17-iso/threading-multi/visibility-hidden/libtest_library.so.1.88.0
ASAN_OPTIONS: detect_odr_violation=0

jobs:
posix:
strategy:
fail-fast: false
matrix:
include:
- toolset: gcc-12
- toolset: gcc-14
cxxstd: "11,14,17,2a"
os: ubuntu-22.04
os: ubuntu-24.04
# UBSAN complains on vtables and fails. No ',undefined -fno-sanitize-recover=undefined' flags!
cxxflags: "cxxflags=--coverage -fsanitize=address,leak -DBOOST_TRAVISCI_BUILD"
linkflags: "linkflags=--coverage -lasan"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8"
gcov_tool: "gcov-12"
gcov_tool: "gcov-14"
ignore_coverage: "*/detail/pe_info.hpp */detail/macho_info.hpp */filesystem/src/*"
- toolset: gcc-12
- toolset: gcc-14
cxxstd: "17,2a"
os: ubuntu-22.04
os: ubuntu-24.04
# UBSAN complains on vtables and fails. No ',undefined -fno-sanitize-recover=undefined' flags!
cxxflags: "cxxflags=--coverage -fsanitize=address,leak -DBOOST_DLL_USE_STD_FS -DBOOST_TRAVISCI_BUILD"
linkflags: "linkflags=--coverage -lasan"
launcher: "testing.launcher=LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.8"
gcov_tool: "gcov-12"
gcov_tool: "gcov-14"
ignore_coverage: "*/detail/pe_info.hpp */detail/macho_info.hpp */filesystem/src/*"
- toolset: clang
compiler: clang++-10
cxxstd: "11,14,17,2a"
os: ubuntu-20.04
os: ubuntu-22.04
- toolset: clang-18
cxxstd: "11,14,17,2a"
os: ubuntu-24.04
#- toolset: clang
# cxxstd: "11,14,17,2a"
# os: macos-10.15
Expand Down Expand Up @@ -85,11 +92,6 @@ jobs:
./b2 -d0 headers
./b2 -j4 variant=debug tools/inspect/build
- name: Create user-config.jam
if: matrix.compiler
run: |
echo "using ${{matrix.toolset}} : : ${{matrix.compiler}} ;" > ~/user-config.jam
- name: Run tests
run: |
cd ../boost-root
Expand Down
1 change: 0 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ target_link_libraries(boost_dll
Boost::core
Boost::filesystem
Boost::predef
Boost::smart_ptr
Boost::system
Boost::throw_exception
Boost::type_index
Expand Down
1 change: 0 additions & 1 deletion build.jam
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ constant boost_dependencies :
/boost/core//boost_core
/boost/filesystem//boost_filesystem
/boost/predef//boost_predef
/boost/smart_ptr//boost_smart_ptr
/boost/system//boost_system
/boost/throw_exception//boost_throw_exception
/boost/type_index//boost_type_index
Expand Down
4 changes: 2 additions & 2 deletions example/getting_started.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ int main(int argc, char* argv[]) {

//[getting_started_imports_c_variable
// Importing pure C variable
shared_ptr<int> c_var = dll::import_symbol<int>(
std::shared_ptr<int> c_var = dll::import_symbol<int>(
path_to_shared_library, "c_variable_name"
);
//]
Expand Down Expand Up @@ -64,7 +64,7 @@ int main(int argc, char* argv[]) {

//[getting_started_imports_cpp_variable
// Importing variable.
shared_ptr<std::string> cpp_var = dll::import_symbol<std::string>(
std::shared_ptr<std::string> cpp_var = dll::import_symbol<std::string>(
path_to_shared_library, "cpp_variable_name"
);
//]
Expand Down
1 change: 0 additions & 1 deletion example/tutorial5/load_all.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
#include "../tutorial4/static_plugin.hpp"
#include <boost/dll/runtime_symbol_info.hpp> // for program_location()
#include <boost/dll/shared_library.hpp>
#include <boost/make_shared.hpp>
#include <boost/filesystem.hpp>

#include <map>
Expand Down
27 changes: 27 additions & 0 deletions include/boost/dll/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@
/// Define this macro to make Boost.DLL use C++17's std::filesystem::path and std::system_error.
#define BOOST_DLL_USE_STD_FS BOOST_DLL_USE_STD_FS

/// Define this macro to make Boost.DLL use boost::shared_ptr instead of std::shared_ptr. This macro will be removed
/// after a few releases, consider migrating to std::shared_ptr.
#define BOOST_DLL_USE_BOOST_SHARED_PTR BOOST_DLL_USE_BOOST_SHARED_PTR

/// This namespace contains aliases to the Boost or C++17 classes. Aliases are configured using BOOST_DLL_USE_STD_FS macro.
namespace boost { namespace dll { namespace fs {

Expand Down Expand Up @@ -69,5 +73,28 @@ using boost::system::system_error;

#endif // BOOST_DLL_USE_STD_FS


#ifdef BOOST_DLL_USE_BOOST_SHARED_PTR

#include <boost/make_shared.hpp>

namespace boost { namespace dll { namespace detail {
template <class T>
using shared_ptr = boost::shared_ptr<T>;
using boost::make_shared;
}}}

#else // BOOST_DLL_USE_STD_FS

#include <memory>

namespace boost { namespace dll { namespace detail {
template <class T>
using shared_ptr = std::shared_ptr<T>;
using std::make_shared;
}}}

#endif // BOOST_DLL_USE_STD_FS

#endif // BOOST_DLL_DETAIL_PUSH_OPTIONS_HPP

51 changes: 29 additions & 22 deletions include/boost/dll/import.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
#define BOOST_DLL_IMPORT_HPP

#include <boost/dll/config.hpp>
#include <boost/make_shared.hpp>
#include <boost/dll/shared_library.hpp>

#include <memory> // std::addressof
Expand All @@ -32,10 +31,10 @@ namespace detail {
template <class T>
class library_function {
// Copying of `boost::dll::shared_library` is very expensive, so we use a `shared_ptr` to make it faster.
boost::shared_ptr<T> f_;
boost::dll::detail::shared_ptr<T> f_;

public:
inline library_function(const boost::shared_ptr<shared_library>& lib, T* func_ptr) noexcept
inline library_function(const boost::dll::detail::shared_ptr<shared_library>& lib, T* func_ptr) noexcept
: f_(lib, func_ptr)
{}

Expand All @@ -55,11 +54,10 @@ namespace detail {
}
};


template <class T>
using import_type = typename std::conditional<
std::is_object<T>::value,
boost::shared_ptr<T>,
boost::dll::detail::shared_ptr<T>,
boost::dll::detail::library_function<T>
>::type;
} // namespace detail
Expand All @@ -71,7 +69,8 @@ namespace detail {


/*!
* Returns callable object or boost::shared_ptr<T> that holds the symbol imported
* Returns callable object or std::shared_ptr<T> (boost::shared_ptr<T> if
* BOOST_DLL_USE_BOOST_SHARED_PTR is defined) that holds the symbol imported
* from the loaded library. Returned value refcounts usage
* of the loaded shared library, so that it won't get unload until all copies of return value
* are not destroyed.
Expand All @@ -90,7 +89,7 @@ namespace detail {
* \endcode
*
* \code
* boost::shared_ptr<int> i = import_symbol<int>("test_lib.so", "integer_name");
* std::shared_ptr<int> i = import_symbol<int>("test_lib.so", "integer_name");
* \endcode
*
* \b Template \b parameter \b T: Type of the symbol that we are going to import. Must be explicitly specified.
Expand All @@ -99,7 +98,8 @@ namespace detail {
* \param name Null-terminated C or C++ mangled name of the function to import. Can handle std::string, char*, const char*.
* \param mode An mode that will be used on library load.
*
* \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type.
* \return callable object if T is a function type, or std::shared_ptr<T> (boost::shared_ptr<T> if
* BOOST_DLL_USE_BOOST_SHARED_PTR is defined) if T is an object type.
*
* \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded.
* Overload that accepts path also throws std::bad_alloc in case of insufficient memory.
Expand All @@ -110,8 +110,9 @@ BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(const boost::dll::fs::path& lib, cons
{
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(lib, mode);
return type(p, std::addressof(p->get<T>(name)));
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(lib, mode);
auto* addr = std::addressof(p->get<T>(name));
return type(std::move(p), addr);
}

//! \overload boost::dll::import_symbol(const boost::dll::fs::path& lib, const char* name, load_mode::type mode)
Expand All @@ -127,7 +128,7 @@ template <class T>
BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(const shared_library& lib, const char* name) {
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(lib);
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(lib);
return type(p, std::addressof(p->get<T>(name)));
}

Expand All @@ -142,10 +143,11 @@ template <class T>
BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(shared_library&& lib, const char* name) {
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(
std::move(lib)
);
return type(p, std::addressof(p->get<T>(name)));
auto* addr = std::addressof(p->get<T>(name));
return type(std::move(p), addr);
}

//! \overload boost::dll::import_symbol(const boost::dll::fs::path& lib, const char* name, load_mode::type mode)
Expand All @@ -158,7 +160,8 @@ BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(shared_library&& lib, const std::stri


/*!
* Returns callable object or boost::shared_ptr<T> that holds the symbol imported
* Returns callable object or std::shared_ptr<T> (boost::shared_ptr<T> if
* BOOST_DLL_USE_BOOST_SHARED_PTR is defined) that holds the symbol imported
* from the loaded library. Returned value refcounts usage
* of the loaded shared library, so that it won't get unload until all copies of return value
* are not destroyed.
Expand All @@ -177,7 +180,7 @@ BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(shared_library&& lib, const std::stri
* \endcode
*
* \code
* boost::shared_ptr<int> i = import_alias<int>("test_lib.so", "integer_alias_name");
* std::shared_ptr<int> i = import_alias<int>("test_lib.so", "integer_alias_name");
* \endcode
*
* \code
Expand All @@ -189,7 +192,8 @@ BOOST_DLL_IMPORT_RESULT_TYPE import_symbol(shared_library&& lib, const std::stri
* \param name Null-terminated C or C++ mangled name of the function or variable to import. Can handle std::string, char*, const char*.
* \param mode An mode that will be used on library load.
*
* \return callable object if T is a function type, or boost::shared_ptr<T> if T is an object type.
* \return callable object if T is a function type, or std::shared_ptr<T> (boost::shared_ptr<T> if
* BOOST_DLL_USE_BOOST_SHARED_PTR is defined) if T is an object type.
*
* \throw \forcedlinkfs{system_error} if symbol does not exist or if the DLL/DSO was not loaded.
* Overload that accepts path also throws std::bad_alloc in case of insufficient memory.
Expand All @@ -200,8 +204,9 @@ BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const boost::dll::fs::path& lib, const
{
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(lib, mode);
return type(p, p->get<T*>(name));
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(lib, mode);
auto* addr = p->get<T*>(name);
return type(std::move(p), addr);
}

//! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode)
Expand All @@ -217,8 +222,9 @@ template <class T>
BOOST_DLL_IMPORT_RESULT_TYPE import_alias(const shared_library& lib, const char* name) {
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(lib);
return type(p, p->get<T*>(name));
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(lib);
auto* addr = p->get<T*>(name);
return type(std::move(p), addr);
}

//! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode)
Expand All @@ -232,10 +238,11 @@ template <class T>
BOOST_DLL_IMPORT_RESULT_TYPE import_alias(shared_library&& lib, const char* name) {
using type = boost::dll::detail::import_type<T>;

auto p = boost::make_shared<boost::dll::shared_library>(
auto p = boost::dll::detail::make_shared<boost::dll::shared_library>(
std::move(lib)
);
return type(p, p->get<T*>(name));
auto* addr = p->get<T*>(name);
return type(std::move(p), addr);
}

//! \overload boost::dll::import_alias(const boost::dll::fs::path& lib, const char* name, load_mode::type mode)
Expand Down
Loading

0 comments on commit 013633d

Please sign in to comment.