xo-facet: runtime facet lookup [PROTO]
This commit is contained in:
parent
b1ec26a9fd
commit
fe4fc4a28d
5 changed files with 86 additions and 3 deletions
|
|
@ -10,6 +10,8 @@ Library dependency tower for *xo-facet*:
|
||||||
+-----------------+
|
+-----------------+
|
||||||
| xo_facet |
|
| xo_facet |
|
||||||
+-----------------+
|
+-----------------+
|
||||||
|
| xo_arena |
|
||||||
|
+-----------------+
|
||||||
| xo_cmake |
|
| xo_cmake |
|
||||||
+-----------------+
|
+-----------------+
|
||||||
|
|
||||||
|
|
@ -18,6 +20,8 @@ Abstraction tower for *xo-facet* components.
|
||||||
.. ditaa::
|
.. ditaa::
|
||||||
:--scale: 0.85
|
:--scale: 0.85
|
||||||
|
|
||||||
|
+--------------------------------+
|
||||||
|
| FacetRegistry |
|
||||||
+--------------------------------+
|
+--------------------------------+
|
||||||
| obj(A,D) |
|
| obj(A,D) |
|
||||||
+--------------------------------+
|
+--------------------------------+
|
||||||
|
|
@ -37,9 +41,12 @@ Abstraction tower for *xo-facet* components.
|
||||||
* - Component
|
* - Component
|
||||||
- Use
|
- Use
|
||||||
- Description
|
- Description
|
||||||
|
* - ``FacetRegistry``
|
||||||
|
- ``FacetRegistry::convert_to<ATo>(obj<AFrom>)``
|
||||||
|
- polymorphic conversion between facets
|
||||||
* - ``obj<A,D>``
|
* - ``obj<A,D>``
|
||||||
- ``x.foo()``
|
- ``x.foo()``
|
||||||
- convenience wrapper with interface A, with state D*
|
- convenience wrapper for interface A, with state D*
|
||||||
* - ``RRouter<A,D>``
|
* - ``RRouter<A,D>``
|
||||||
- ``x.foo()``
|
- ``x.foo()``
|
||||||
- auto injects data pointer
|
- auto injects data pointer
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@ This gives us several benefits:
|
||||||
simpler that the pathway for a data pointer. This increases scope for
|
simpler that the pathway for a data pointer. This increases scope for
|
||||||
devirtualization.
|
devirtualization.
|
||||||
|
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
:caption: xo-facet contents
|
:caption: xo-facet contents
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "facet_implementation.hpp"
|
#include "facet_implementation.hpp"
|
||||||
#include "typeseq.hpp"
|
#include "typeseq.hpp"
|
||||||
|
#include "obj.hpp"
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
@ -88,7 +89,8 @@ namespace xo {
|
||||||
bool contains(typeseq facet_id,
|
bool contains(typeseq facet_id,
|
||||||
typeseq repr_id) const
|
typeseq repr_id) const
|
||||||
{
|
{
|
||||||
return registry_.find(key_type(facet_id, repr_id)) != registry_.end();
|
return (registry_.find(key_type(facet_id, repr_id))
|
||||||
|
!= registry_.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Type-safe lookup
|
/** Type-safe lookup
|
||||||
|
|
@ -99,7 +101,37 @@ namespace xo {
|
||||||
**/
|
**/
|
||||||
template <typename AFacet>
|
template <typename AFacet>
|
||||||
const AFacet * lookup(typeseq repr_id) const {
|
const AFacet * lookup(typeseq repr_id) const {
|
||||||
return static_cast<const AFacet *>(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
return static_cast<const AFacet *>
|
||||||
|
(this->_lookup(typeseq::id<AFacet>(), repr_id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Runtime polymorphism:
|
||||||
|
* Switch @param from from interface @tp AFrom to interface @tp ATo.
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* obj<AFoo> foo
|
||||||
|
* = ...; // Foo instance with variant impl
|
||||||
|
* obj<ABar> bar
|
||||||
|
* = FacetRegistry::variant<ABar,AFoo>(foo);
|
||||||
|
**/
|
||||||
|
template <typename ATo, typename AFrom>
|
||||||
|
obj<ATo> variant(obj<AFrom> from) {
|
||||||
|
return variant<ATo>(from._typeseq(), from.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Runtime polymorphism:
|
||||||
|
* Create variant from representation @p data
|
||||||
|
* with actual type @p repr_id.
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* obj<AFoo> foo = ...; // Foo instance with variant impl
|
||||||
|
* obj<ABar> bar
|
||||||
|
* = FacetRegistry::variant<ABar>(foo._typeseq(), foo.opaque_data());
|
||||||
|
**/
|
||||||
|
template <typename AFacet>
|
||||||
|
obj<AFacet> variant(typeseq repr_id, void * data) {
|
||||||
|
const AFacet * iface = this->lookup<AFacet>(repr_id);
|
||||||
|
return obj<AFacet>::variant(iface, data);;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
@ -134,6 +166,7 @@ namespace xo {
|
||||||
private:
|
private:
|
||||||
FacetRegistry() = default;
|
FacetRegistry() = default;
|
||||||
|
|
||||||
|
/** runtime lookup table (AFacet,DRepr) -> impl **/
|
||||||
std::unordered_map<key_type, const void *, KeyHash> registry_;
|
std::unordered_map<key_type, const void *, KeyHash> registry_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,22 @@ namespace xo {
|
||||||
memcpy(&(iface_[0]), (void*)&tmp, sizeof(ISpecific));
|
memcpy(&(iface_[0]), (void*)&tmp, sizeof(ISpecific));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Runtime polymorphism:
|
||||||
|
* Create variant for specific interface @p impl
|
||||||
|
* with type-erased data @p data.
|
||||||
|
*
|
||||||
|
* Implements
|
||||||
|
* obj<AFacet>::variant(iface, data)
|
||||||
|
**/
|
||||||
|
OObject(const AFacet * impl, void * data)
|
||||||
|
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||||
|
: data_{reinterpret_cast<DVariantPlaceholder*>(data)}
|
||||||
|
{
|
||||||
|
static_assert(sizeof(ISpecific) == sizeof(impl));
|
||||||
|
memcpy(&(iface_[0]), (void*)impl, sizeof(ISpecific));
|
||||||
|
}
|
||||||
|
|
||||||
OObject(const OObject & oother) {
|
OObject(const OObject & oother) {
|
||||||
_launder_from(oother);
|
_launder_from(oother);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,18 @@ namespace xo {
|
||||||
|
|
||||||
obj(const obj & rhs) = default;
|
obj(const obj & rhs) = default;
|
||||||
|
|
||||||
|
/** Runtime polymorphism:
|
||||||
|
* assemble variant from specific interface @p iface
|
||||||
|
* and type-erased representation @p data.
|
||||||
|
*
|
||||||
|
* Implements
|
||||||
|
* obj<AFacet>::variant(iface, data)
|
||||||
|
**/
|
||||||
|
obj(const AFacet * iface, void * data)
|
||||||
|
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||||
|
: Super(iface, data)
|
||||||
|
{}
|
||||||
|
|
||||||
/** pseudo copy constructor
|
/** pseudo copy constructor
|
||||||
*
|
*
|
||||||
* Intended for use cases:
|
* Intended for use cases:
|
||||||
|
|
@ -96,6 +108,20 @@ namespace xo {
|
||||||
return obj(other.template downcast<DRepr>());
|
return obj(other.template downcast<DRepr>());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Runtime polymorphism.
|
||||||
|
* Create variant given interface @p iface,
|
||||||
|
* type-erased represention @p data
|
||||||
|
*
|
||||||
|
* Use:
|
||||||
|
* AFoo * impl = ....;
|
||||||
|
* auto x = obj<AFoo>::variant(impl, data)
|
||||||
|
**/
|
||||||
|
static obj variant(const AFacet * iface, void * data)
|
||||||
|
requires std::is_same_v<DRepr, DVariantPlaceholder>
|
||||||
|
{
|
||||||
|
return obj(iface, data);
|
||||||
|
}
|
||||||
|
|
||||||
/** enabled when RRouter<AFacet> provides _preincrement.
|
/** enabled when RRouter<AFacet> provides _preincrement.
|
||||||
* Note we don't need this trick for comparison operators,
|
* Note we don't need this trick for comparison operators,
|
||||||
* since return type is fixed.
|
* since return type is fixed.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue