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

Runtime provider additions #508

Open
wants to merge 2 commits into
base: cpp14
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
511 changes: 497 additions & 14 deletions extension/include/boost/di/extension/providers/runtime_provider.hpp

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once
// DWK for this entire file

#include <cassert>
#include <functional>
#include <memory>
#include <type_traits>
#include <typeindex>
#include <unordered_map>
#include <utility>

#include "boost/di.hpp"
#include "boost/di/extension/scopes/shared.hpp"

#include "boost/di/extension/providers/runtime_provider_additions_any_of.h"
#include "boost/di/extension/providers/runtime_provider_additions_di_core_array.h"
//#include "boost/di/extension/providers/runtime_provider
#include "boost/di/extension/providers/runtime_provider_generator_saver.h"
#include "boost/di/extension/providers/runtime_provider_additions_is_singleton.h"


BOOST_DI_NAMESPACE_BEGIN
namespace extension {


// ---------------------------------------------------------------------------
// dependency_any_to_type_index_vec
template <typename T>
typename std::enable_if<!dwk_is_di_core_dep_any_v<T>, std::array<std::type_index, 0> >::type
constexpr dependency_any_to_type_index_vec() // std::vector<std::type_index> & /*type_index_vec*/)
{
// TODO, assert?? is there really nothing to add to the vector
return std::array<std::type_index, 0>();
}



template <typename T>
typename std::enable_if<dwk_is_di_core_dep_any_v<T>, typename dwk_is_di_core_dep<T>::array_t >::type
constexpr dependency_any_to_type_index_vec()
{
// std::cout << "----------------------------\n";
// std::cout << "dwk_get_binding_typeids di_Core template\n";
// std::cout << "SCOPE>>> " << typeid(typename dwk_is_di_core_dep<T>::scope_t).name() << std::endl;
// std::cout << "BINDINGS>>> " << typeid(typename dwk_is_di_core_dep<T>::bindings_t).name() << std::endl;
// std::cout << "BOUND>>> " << typeid(typename dwk_is_di_core_dep<T>::bound_t).name() << std::endl;
// std::cout << "W>>> " << typeid(typename dwk_is_di_core_dep<T>::W_t).name() << std::endl;
// std::cout << "X>>> " << typeid(typename dwk_is_di_core_dep<T>::X_t).name() << std::endl;
// std::cout << "----------------------------\n";

// TODO, link up dwk_is_di_core_dep and this method get_type_index_array insead of them just happening to have the same return type '1' currently
const auto res = get_type_index_array<typename dwk_is_di_core_dep<T>::bindings_t>();
return res;
}


#if 0
// TODO, or maybe just delete all of this?
// ---------------------------------------------------------------------------
// TODO, this needs some cleanup
template <typename T, typename DATA_T, typename MADE_T>
//typename std::enable_if<dwk_is_core_any_v<T>, void>::type
void
dwk_add_to_data2(const bool is_singleton, DATA_T & data, const std::vector<std::type_index> & type_index_vec, MADE_T m)
{
if(!is_singleton)
{
std::cout << "Skipping adding non-singleton " << typeid(T).name() << std::endl;
return;
}
// std::cout << "ADD TO DATA2 CRAZY MULTI INHERITANCE " << typeid(T).name() << "\n";
// only create this shared_ptr once and stuff it everywhere it has been bound to
std::shared_ptr<typename std::remove_pointer<MADE_T>::type> made_shared_ptr{m};
std::shared_ptr<void> void_shared_ptr = made_shared_ptr;

// TODO, don't need to pass in the type index vec cause we can just get it from the dwk_is_core_any<T>::??
for(auto & type_idx : type_index_vec)
{
std::cout << " ADDING to data: " << typeid(MADE_T).name() << " as a " << type_idx.name() << ", " << type_idx.hash_code() << "\n";
data[type_idx].push_back(void_shared_ptr);
std::cout << "data[type_idx].size() == " << data[type_idx].size() << std::endl;
// std::cout << " ADDING after size = " << data[type_idx].size() << "\n";
// std::cout << std::endl;
}
}

template <typename T, typename DATA_T, typename MADE_T>
typename std::enable_if<!dwk_is_di_core_dep_any_v<T>, void>::type
dwk_add_to_data(const bool /*is_singleton*/, DATA_T & /*data*/, const std::vector<std::type_index> & /*type_index_vec*/, MADE_T /*m*/)
{
// TODO, believe this is done with double, int, etc.
std::cout << "dwk_add_to_data nada" << std::endl;
}

template <typename T, typename DATA_T, typename MADE_T>
// DWK, TODO make this also ensure that T::given is a pointer and not an instance
typename std::enable_if<dwk_is_di_core_dep_any_v<T>, void>::type
dwk_add_to_data(const bool is_singleton, DATA_T & data, const std::vector<std::type_index> & type_index_vec, MADE_T m)
{
typedef typename dwk_is_di_core_dep<T>::bindings_t bindings_t;
dwk_add_to_data2<bindings_t, DATA_T>(is_singleton, data, type_index_vec, m);
}

#endif

} // namespace extension
BOOST_DI_NAMESPACE_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#pragma once

//
// Created by Dave on 9/20/20.
//

#include <array>

#include "boost/di.hpp"


BOOST_DI_NAMESPACE_BEGIN
namespace extension {

// ---------------------------------------------------------------------------
// Takes variadic template pack from concepts::any_of<Ts..>> and gives you an array of std::type_index
template<typename T> struct is_any_of : std::false_type {};
template<typename... Ts> struct is_any_of<boost::ext::di::v1_2_0::concepts::any_of<Ts...>> : std::true_type
{
static constexpr size_t size() { return sizeof...(Ts); }
static constexpr std::array<std::type_index, sizeof...(Ts)> var_args_to_array_ids()
{
const std::array<std::type_index, sizeof...(Ts)> res {typeid(Ts)...};
return res;
}
};
template<typename T> constexpr bool is_any_of_v = is_any_of<T>::value;

// ---------------------------------------------------------------------------
// Specialization function for any_of<Ts...> to array
template<typename T>
typename std::enable_if<is_any_of_v<T>, std::array<std::type_index, is_any_of<T>::size() > >::type
get_type_index_array()
{
return is_any_of<T>::var_args_to_array_ids();
}

// Specialization function for just a type
template<typename T>
typename std::enable_if<!is_any_of_v<T> /*&& std::is_integral<T>()*/, std::array<std::type_index, 1> >::type
get_type_index_array()
{
return std::array<std::type_index, 1>{ typeid(T) };
}

// ---------------------------------------------------------------------------
// Specialization function for any_of<Ts...> to array
template<typename T>
typename std::enable_if<is_any_of_v<T>, size_t >::type
constexpr get_size_index_array()
{
return is_any_of<T>::size();
}

// Specialization function for just a type
template<typename T>
typename std::enable_if<!is_any_of_v<T> /*&& std::is_integral<T>()*/, size_t >::type
constexpr get_size_index_array()
{
return 1;
}




} // namespace extension
BOOST_DI_NAMESPACE_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once
//
// Created by Dave on 9/20/20.
//
#include <array>
#include "boost/di/extension/providers/runtime_provider_additions_any_of.h"

// ---------------------------------------------------------------------------
// di core dep any
template<typename, typename = void, typename = void, typename = void>
struct dwk_is_di_core_dep : std::false_type {};
template <typename SCOPE, typename BINDINGS, typename BOUND, typename W, typename X>
struct dwk_is_di_core_dep<boost::ext::di::v1_2_0::core::dependency<SCOPE, BINDINGS, BOUND, W, X>> : std::true_type
{
typedef SCOPE scope_t; // scope: singleton?
typedef BINDINGS bindings_t;
typedef BOUND bound_t;
typedef W W_t;
typedef X X_t;

static constexpr size_t size() { return boost::di::extension::get_size_index_array<bindings_t>(); }
typedef std::array<std::type_index, size()> array_t;
};
template <typename T>
static constexpr bool dwk_is_di_core_dep_any_v = dwk_is_di_core_dep<T>::value;
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#pragma once
// DWK for this entire file

#include "boost/di.hpp"
#include "boost/di/extension/scopes/shared.hpp"

BOOST_DI_NAMESPACE_BEGIN
namespace extension {

// ---------------------------------------------------------------------------
// This specialization detects when we're trying to create an std::vector<std::shared_ptr<interface_t>>
// it's not just a vector, it's some weird boost di wrapper core array with a vector inside that
// template<typename T>
// struct is_vector : public std::false_type {};
// template<typename T>
// struct is_vector<std::vector<T>> : public std::true_type {};

template <typename T>
struct is_di_core_array : public std::false_type {};
template <typename T> // N5boost3ext2di6v1_2_04core5arrayIFNSt3__16vectorINS5_10shared_ptrI2i1EENS5_9allocatorIS9_EEEEvEJEEE
struct is_di_core_array<boost::ext::di::v1_2_0::core::array<std::__1::vector<T*, std::__1::allocator<T*> > ()> > : public std::true_type
{
typedef T subtype;
typedef T* raw_ptr_t;
typedef T* ptr_t;
};
// but then shared_ptr<T> is a possibility too - why don't we just tie into the other get<T> creation methods?
template <typename T>
struct is_di_core_array<boost::ext::di::v1_2_0::core::array<std::__1::vector<std::shared_ptr<T>, std::__1::allocator<std::shared_ptr<T>> > ()> > : public std::true_type
{
typedef T subtype;
typedef T* raw_ptr_t;
typedef std::shared_ptr<T> ptr_t;
};


// ----------------------------------------------------------------------------
template <typename T>
struct is_di_core_array_list : public std::false_type {};
template <typename T> // boost::ext::di::v1_2_0::cores::successful::any_type_ref<std::__1::list, boost::ext::di::v1_2_0::core::injector>
//get<T> NSt3__14listINS_10shared_ptrI2i1EENS_9allocatorIS3_EEEE
struct is_di_core_array_list<std::__1::list<T*, std::__1::allocator<T*> > > : public std::true_type
{
typedef T subtype;
typedef T* raw_ptr_t;
typedef T* ptr_t;
};
// but then shared_ptr<T> is a possibility too - why don't we just tie into the other get<T> creation methods?
template <typename T>
struct is_di_core_array_list<std::__1::list<std::shared_ptr<T>, std::__1::allocator<std::shared_ptr<T>> > > : public std::true_type
{
typedef T subtype;
typedef T* raw_ptr_t;
typedef std::shared_ptr<T> ptr_t;
};



} // namespace extension
BOOST_DI_NAMESPACE_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
#pragma once
// DWK for this entire file

#include "boost/di.hpp"
#include "boost/di/extension/providers/runtime_provider_additions_core_dep_any.h"

BOOST_DI_NAMESPACE_BEGIN
namespace extension {

// ---------------------------------------------------------------------------
// scope_is_singleton
template<typename T>
typename std::enable_if<!std::is_same<boost::ext::di::v1_2_0::scopes::singleton, T>::value, bool>::type
scope_is_singleton() { return false; }

template<typename T>
typename std::enable_if<std::is_same<boost::ext::di::v1_2_0::scopes::singleton, T>::value, bool>::type
scope_is_singleton() { return true; }

// ---------------------------------------------------------------------------
// dependency_is_singleton_scope
template <typename T>
typename std::enable_if<!dwk_is_di_core_dep_any_v<T>, bool>::type
dependency_is_singleton_scope()
{
return false; // Unknown really
}
template <typename T>
typename std::enable_if<dwk_is_di_core_dep_any_v<T>, bool>::type
dependency_is_singleton_scope()
{
typedef typename dwk_is_di_core_dep<T>::scope_t scope_t;
return scope_is_singleton<scope_t>();
}


} // namespace extension
BOOST_DI_NAMESPACE_END
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once
// DWK for this entire file

// TODO, namespace?!
template <typename T>
class generator_saver
{
public:
explicit generator_saver
( const int gs_num
, std::function<void*()> fn)
: m_gs_num(gs_num)
, m_fn(fn)
{}

generator_saver(generator_saver const &) = delete;
generator_saver(generator_saver &&) = delete;

~generator_saver()
{}

// TODO?
// ~generator_saver()
// {
// if(m_saved)
// {
// delete m_saved;
// m_saved = nullptr;
// }
// }

void* do_it()
{
if(!m_saved)
{
if(!m_fn)
return nullptr;
m_saved = m_fn();
// Created type
}
else
{
// Using previoulsy saved type
}
return m_saved;
}
private:
int m_gs_num {0};
std::function<void*()> m_fn { [](){return nullptr;} };
void* m_saved {nullptr};

};
13 changes: 12 additions & 1 deletion extension/include/boost/di/extension/scopes/shared.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,22 @@ class shared {
std::lock_guard<std::mutex> lock(mutex_);
if (!object)
#endif
object = std::shared_ptr<T>{provider.get()};
{
auto raw_ptr_from_get = provider.get();

// Check one last time and use that instead so that the shared_ptr comes from the right place
if(object)
{
return wrappers::shared<shared, T>{std::static_pointer_cast<T>(object)};
}

object = std::shared_ptr<T>{raw_ptr_from_get};
}
}
return wrappers::shared<shared, T>{std::static_pointer_cast<T>(object)};
}


private:
#if !defined(BOOST_DI_NOT_THREAD_SAFE)
std::mutex mutex_;
Expand Down
1 change: 1 addition & 0 deletions extension/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ test(policies/uml_dumper)
test(providers/heap)
test(providers/mocks_provider)
test(providers/runtime_provider)
test(providers/runtime_provider_additions)
test(scopes/scoped)
test(scopes/session)
test(scopes/shared)
Expand Down
Loading