Skip to content

Commit

Permalink
Remove type map
Browse files Browse the repository at this point in the history
  • Loading branch information
barche committed Jun 8, 2024
1 parent 93768c1 commit e3c31f3
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 141 deletions.
4 changes: 2 additions & 2 deletions include/jlcxx/jlcxx_config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
#endif

#define JLCXX_VERSION_MAJOR 0
#define JLCXX_VERSION_MINOR 12
#define JLCXX_VERSION_PATCH 5
#define JLCXX_VERSION_MINOR 13
#define JLCXX_VERSION_PATCH 0

// From https://stackoverflow.com/questions/5459868/concatenate-int-to-string-using-c-preprocessor
#define __JLCXX_STR_HELPER(x) #x
Expand Down
27 changes: 22 additions & 5 deletions include/jlcxx/smart_pointers.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,30 @@ struct SmartPtrMethods<PtrT<PointeeT, ExtraArgs...>, OtherPtrT>

}

JLCXX_API void set_smartpointer_type(const type_hash_t& hash, TypeWrapper1* new_wrapper);
JLCXX_API TypeWrapper1* get_smartpointer_type(const type_hash_t& hash);
template<typename T>
std::shared_ptr<TypeWrapper1>& stored_smartpointer_type()
{
static std::shared_ptr<TypeWrapper1> m_ptr;
return m_ptr;
}

template<typename T>
void set_smartpointer_type(TypeWrapper1* new_wrapper)
{
assert(stored_smartpointer_type<T>().get() == nullptr);
stored_smartpointer_type<T>().reset(new_wrapper);
}

template<typename T>
TypeWrapper1* get_smartpointer_type()
{
return stored_smartpointer_type<T>().get();
}

template<template<typename...> class T>
TypeWrapper1 smart_ptr_wrapper(Module& module)
{
static TypeWrapper1* stored_wrapper = get_smartpointer_type(type_hash<T<int>>());
static TypeWrapper1* stored_wrapper = get_smartpointer_type<T<int>>();
if(stored_wrapper == nullptr)
{
std::cerr << "Smart pointer type has no wrapper" << std::endl;
Expand Down Expand Up @@ -220,7 +237,7 @@ template<template<typename...> class T>
TypeWrapper1& add_smart_pointer(Module& mod, const std::string& name)
{
TypeWrapper1* tw = new TypeWrapper1(mod.add_type<Parametric<TypeVar<1>>>(name, julia_type("SmartPointer", get_cxxwrap_module())));
smartptr::set_smartpointer_type(type_hash<T<int>>(), tw);
smartptr::set_smartpointer_type<T<int>>(tw);
return *tw;
}

Expand Down Expand Up @@ -284,7 +301,7 @@ struct julia_type_factory<T, CxxWrappedTrait<SmartPointerTrait>>
detail::apply_smart_ptr_type<ConstMappedT>()(curmod);
smartptr::detail::SmartPtrMethods<NonConstMappedT, typename ConstructorPointerType<NonConstMappedT>::type>::apply(curmod);
assert(has_julia_type<T>());
return JuliaTypeCache<T>::julia_type();
return stored_type<T>().get_dt();
}
};

Expand Down
2 changes: 1 addition & 1 deletion include/jlcxx/stl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ struct julia_type_factory<std::vector<T>>
Module& curmod = registry().current_module();
stl::apply_stl<T>(curmod);
assert(has_julia_type<MappedT>());
return JuliaTypeCache<MappedT>::julia_type();
return stored_type<MappedT>().get_dt();
}
};

Expand Down
118 changes: 17 additions & 101 deletions include/jlcxx/type_conversion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -348,112 +348,24 @@ struct CachedDatatype
jl_datatype_t* m_dt = nullptr;
};

// Work around the fact that references aren't part of the typeid result
using type_hash_t = std::pair<std::type_index, std::size_t>;

} // namespace jlcxx

namespace std {

// Hash implementation from https://en.cppreference.com/w/cpp/utility/hash
template<>
struct hash<jlcxx::type_hash_t>
template<typename CppT>
CachedDatatype& stored_type()
{
std::size_t operator()(const jlcxx::type_hash_t& h) const noexcept
{
std::size_t h1 = std::hash<std::type_index>{}(h.first);
std::size_t h2 = std::hash<std::size_t>{}(h.second);
return h1 ^ (h2 << 1);
}
};

static CachedDatatype m_dt;
return m_dt;
}

namespace jlcxx
{

namespace detail
{

template<typename T>
struct TypeHash
{
static inline type_hash_t value()
{
return std::make_pair(std::type_index(typeid(T)), std::size_t(0));
}
};

template<typename T>
struct TypeHash<T&>
{
static inline type_hash_t value()
{
return std::make_pair(std::type_index(typeid(T)), std::size_t(1));
}
};

template<typename T>
struct TypeHash<const T&>
{
static inline type_hash_t value()
{
return std::make_pair(std::type_index(typeid(T)), std::size_t(2));
}
};

}

template<typename T>
inline type_hash_t type_hash()
{
return detail::TypeHash<T>::value();
}

JLCXX_API std::unordered_map<type_hash_t, CachedDatatype>& jlcxx_type_map();

/// Store the Julia datatype linked to SourceT
template<typename SourceT>
class JuliaTypeCache
void set_julia_type(jl_datatype_t* dt, bool protect = true)
{
public:

static inline jl_datatype_t* julia_type()
{
const auto result = jlcxx_type_map().find(type_hash<SourceT>());
if(result == jlcxx_type_map().end())
{
throw std::runtime_error("Type " + std::string(typeid(SourceT).name()) + " has no Julia wrapper");
}
return result->second.get_dt();
}

static inline void set_julia_type(jl_datatype_t* dt, bool protect = true)
{
type_hash_t new_hash = type_hash<SourceT>();
const auto [inserted_it, insert_success] = jlcxx_type_map().insert(std::make_pair(new_hash, CachedDatatype(dt, protect)));
if(!insert_success)
{
type_hash_t old_hash = inserted_it->first;
std::cout << "Warning: Type " << new_hash.first.name() << " already had a mapped type set as "
<< julia_type_name(inserted_it->second.get_dt()) << " and const-ref indicator " << old_hash.second << " and C++ type name " << old_hash.first.name()
<< ". Hash comparison: old(" << old_hash.first.hash_code() << "," << old_hash.second << ") == new(" << old_hash.first.hash_code() << "," << old_hash.second << ") == "
<< std::boolalpha << (old_hash == new_hash) << std::endl;
return;
}
}

static inline bool has_julia_type()
using nonconst_t = typename std::remove_const<T>::type;
CachedDatatype& cache = stored_type<nonconst_t>();
if(cache.get_dt() != nullptr)
{
const std::size_t nb_hits = jlcxx_type_map().count(type_hash<SourceT>());
return nb_hits != 0;
std::cout << "Warning: Type " << typeid(T).name() << " already had a mapped type set as " << julia_type_name(cache.get_dt()) << std::endl;
return;
}
};

template<typename T>
void set_julia_type(jl_datatype_t* dt, bool protect = true)
{
JuliaTypeCache<typename std::remove_const<T>::type>::set_julia_type(dt, protect);
cache.set_dt(dt, protect);
}

/// Store the Julia datatype linked to SourceT
Expand All @@ -473,7 +385,11 @@ template<typename T>
inline jl_datatype_t* julia_type()
{
using nonconst_t = typename std::remove_const<T>::type;
static jl_datatype_t* dt = JuliaTypeCache<nonconst_t>::julia_type();
jl_datatype_t* dt = stored_type<nonconst_t>().get_dt();
if(dt == nullptr)
{
throw std::runtime_error("Type " + std::string(typeid(nonconst_t).name()) + " has no Julia wrapper");
}
return dt;
}

Expand All @@ -482,7 +398,7 @@ template <typename T>
bool has_julia_type()
{
using nonconst_t = typename std::remove_const<T>::type;
return JuliaTypeCache<nonconst_t>::has_julia_type();
return stored_type<nonconst_t>().get_dt() != nullptr;
}

/// Create the julia type associated with the given C++ type
Expand Down
32 changes: 0 additions & 32 deletions src/jlcxx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -341,38 +341,6 @@ namespace detail
};
}

JLCXX_API std::unordered_map<type_hash_t, CachedDatatype>& jlcxx_type_map()
{
static std::unordered_map<type_hash_t, CachedDatatype> m_map;
return m_map;
}

namespace smartptr
{

std::map<type_hash_t, std::shared_ptr<TypeWrapper1>>& jlcxx_smartpointer_types()
{
static std::map<type_hash_t, std::shared_ptr<TypeWrapper1>> m_map;
return m_map;
}

JLCXX_API void set_smartpointer_type(const type_hash_t& hash, TypeWrapper1* new_wrapper)
{
jlcxx_smartpointer_types()[hash] = std::shared_ptr<TypeWrapper1>(new_wrapper);
}

JLCXX_API TypeWrapper1* get_smartpointer_type(const type_hash_t& hash)
{
auto result = jlcxx_smartpointer_types().find(hash);
if(result == jlcxx_smartpointer_types().end())
{
return nullptr;
}
return result->second.get();
}

}

JLCXX_API void register_core_types()
{
if(jl_base_module == nullptr)
Expand Down

0 comments on commit e3c31f3

Please sign in to comment.