Skip to content

Commit d1c80a3

Browse files
committed
introducing rtl::detail::lambda_table
1 parent 153f699 commit d1c80a3

12 files changed

Lines changed: 332 additions & 179 deletions

File tree

ReflectionTemplateLib/access/inc/Function.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,8 @@ namespace rtl {
6767

6868
const std::size_t hasSignatureId(const std::size_t pSignatureId) const;
6969

70+
const detail::FunctorId* hasFunctorId(const std::size_t pSignatureId) const;
71+
7072
GETTER(detail::methodQ, Qualifier, m_qualifier);
7173

7274
GETTER_REF(std::vector<detail::FunctorId>, FunctorIds, m_functorIds)

ReflectionTemplateLib/access/inc/Function.hpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,4 +63,16 @@ namespace rtl
6363
}
6464
return rtl::index_none;
6565
}
66+
67+
68+
FORCE_INLINE const detail::FunctorId* Function::hasFunctorId(const std::size_t pSignatureId) const
69+
{
70+
//simple linear-search, efficient for small set of elements.
71+
for (const auto& functorId : m_functorIds) {
72+
if (functorId.getSignatureId() == pSignatureId) [[likely]] {
73+
return &functorId;
74+
}
75+
}
76+
return nullptr;
77+
}
6678
}

ReflectionTemplateLib/detail/inc/CallReflector.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <optional>
1515
#include "RObject.h"
1616
#include "Constants.h"
17+
#include "FunctorId.h"
1718

1819
namespace rtl::detail {
1920

@@ -30,10 +31,14 @@ namespace rtl::detail {
3031
* gets the lambda vector from '_derivedType' and calls the lambda at given index with '_args'.
3132
* this 'forwardCall' is for calling lambda containing non-member-function and static-member-function functors.
3233
*/ template<class ..._params>
33-
FORCE_INLINE static Return forwardCall(std::size_t pFunctorIndex, _params&&..._args)
34+
FORCE_INLINE static Return forwardCall(const detail::FunctorId& pFunctorId, _params&&..._args)
3435
{
36+
// static_cast to derived type, gaurateed safe by design.
37+
//auto lambdaTable = static_cast<_derivedType::lambda_t*>(pFunctorId.m_lambdaTable);
38+
//return lambdaTable->get()[pFunctorId.m_index](std::forward<_params>(_args)...);
39+
3540
//'getFunctors()' must be implemented by _derivedType (FunctorContainer).
36-
return _derivedType::getFunctors()[pFunctorIndex](std::forward<_params>(_args)...);
41+
return _derivedType::getFunctors()[pFunctorId.m_index](std::forward<_params>(_args)...);
3742
}
3843

3944

ReflectionTemplateLib/detail/inc/FunctionCaller.hpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@ namespace rtl::detail
2626
FunctorContainer<std::remove_reference_t<_args>...>,
2727
FunctorContainer<_signature...>>;
2828

29-
std::size_t index = m_function->hasSignatureId(Container::getContainerId());
30-
if (index != rtl::index_none) [[likely]] {
31-
return Container::template forwardCall<_args...>(index, std::forward<_args>(params)...);
29+
//auto containerId = Container::getContainerId();
30+
//const detail::FunctorId* functorId = m_function->hasFunctorId(containerId);
31+
//return { error::None, RObject{} };
32+
33+
const detail::FunctorId* functorId = m_function->hasFunctorId(Container::getContainerId());
34+
if (functorId != nullptr) [[likely]] {
35+
return Container::template forwardCall<_args...>(*functorId, std::forward<_args>(params)...);
3236
}
3337
return { error::SignatureMismatch, RObject{} };
3438
}

ReflectionTemplateLib/detail/inc/FunctorContainer.h

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <vector>
1616
#include <functional>
1717

18+
#include "LambdaTable.h"
1819
#include "Constants.h"
1920
#include "CallReflector.h"
2021
#include "SetupFunction.h"
@@ -27,10 +28,10 @@ namespace rtl {
2728
//forward decl
2829
class ReflectionBuilder;
2930

30-
/* @class: FunctorContainer
31-
@param: '_signature...' (combination of any types)
32-
* container class for holding lambda's wrapping functor, constructor calls of same signatures.
33-
* maintains a std::vector<std::function> with static lifetime.
31+
/* @class: FunctorContainer
32+
@param: '_signature...' (combination of any types)
33+
* container class for holding lambda's wrapping functor, constructor calls of same signatures.
34+
* maintains a std::vector<std::function> with static lifetime.
3435
*/ template<class ..._signature>
3536
class FunctorContainer : public SetupFunction<FunctorContainer<_signature...>>,
3637
public SetupConstructor<FunctorContainer<_signature...>>,
@@ -39,6 +40,8 @@ namespace rtl {
3940
using FunctionLambda = std::function < Return(_signature...) >;
4041
public:
4142

43+
using lambda_t = detail::functors<_signature...>;
44+
4245
//every FunctorContainer<...> will have a unique-id.
4346
FORCE_INLINE static std::size_t getContainerId() {
4447
static const std::size_t containerId = generate_unique_id();
@@ -67,26 +70,37 @@ namespace rtl {
6770
return functorTable;
6871
}
6972

73+
static lambda_t& lambdaCache()
74+
{
75+
static lambda_t functorsCache;
76+
return functorsCache;
77+
}
78+
7079
/* @method: pushBack
7180
@params: pFunctor (lambda containing functor or constructor call)
72-
pGetIndex (lambda providing index if the functor is already registered)
73-
pUpdate (lambda updating the already registered functors/ctor/d'tor set)
81+
pGetIndex (lambda providing index if the functor is already registered)
82+
pUpdate (lambda updating the already registered functors/ctor/d'tor set)
7483
@return: index of newly added or already existing lambda in vector 'm_functors'.
75-
*/ static std::size_t pushBack(const FunctionLambda& pFunctor,
76-
std::function<const std::size_t()> pGetIndex,
77-
std::function<void(const std::size_t&)> pUpdate)
84+
*/ static std::pair<std::size_t, detail::lambda_table*> pushBack(const FunctionLambda& pFunctor,
85+
std::function<const std::size_t()> pGetIndex,
86+
std::function<void(const std::size_t&)> pUpdate)
7887
{
7988
//critical section, thread safe.
8089
static std::mutex mtx;
8190
std::lock_guard<std::mutex> lock(mtx);
8291

8392
std::size_t index = pGetIndex();
84-
if (index == rtl::index_none) {
85-
index = getFunctorTable().size();
86-
pUpdate(index);
93+
if (index == rtl::index_none)
94+
{
95+
index = lambdaCache().get().size();
96+
97+
lambdaCache().pushBack(pFunctor);
98+
8799
getFunctorTable().push_back(pFunctor);
100+
101+
pUpdate(index);
88102
}
89-
return index;
103+
return { index, &lambdaCache() };
90104
}
91105

92106
//friends :)

ReflectionTemplateLib/detail/inc/FunctorId.h

Lines changed: 52 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,64 +14,65 @@
1414
#include "TypeId.h"
1515
#include "Constants.h"
1616

17-
namespace rtl
17+
namespace rtl::detail
1818
{
19-
namespace detail
19+
class lambda_table;
20+
21+
/* @class: FunctorId
22+
* 'FunctorId' object is generated for every functor (member/non-member function pointer) registered.
23+
* acts as a hash-key to lookup a particular functor in the functor-table.
24+
* first, using 'm_containerId', the functor-table container is found.
25+
* once table is found, the functor is accessed at index 'm_index', (never fails, noexcept)
26+
* 'FunctorId' generated for a each functor is unique, even for overloaded functions.
27+
* multiple registartion of same functor will generate same duplicate 'FunctorId'.
28+
*/ struct FunctorId
2029
{
21-
/* @class: FunctorId
22-
* 'FunctorId' object is generated for every functor (member/non-member function pointer) registered.
23-
* acts as a hash-key to lookup a particular functor in the functor-table.
24-
* first, using 'm_containerId', the functor-table container is found.
25-
* once table is found, the functor is accessed at index 'm_index', (never fails, noexcept)
26-
* 'FunctorId' generated for a each functor is unique, even for overloaded functions.
27-
* multiple registartion of same functor will generate same duplicate 'FunctorId'.
28-
*/ struct FunctorId
29-
{
30-
//index of the functor in the functor-table.
31-
std::size_t m_index;
30+
//index of the functor in the functor-table.
31+
std::size_t m_index;
3232

33-
//return type-id of the functor registered.
34-
std::size_t m_returnId;
33+
//return type-id of the functor registered.
34+
std::size_t m_returnId;
3535

36-
//if functor is a member-function, type id of class/struct it belongs to.
37-
std::size_t m_recordId;
36+
//if functor is a member-function, type id of class/struct it belongs to.
37+
std::size_t m_recordId;
3838

39-
//containerId of the functor-table.
40-
std::size_t m_containerId;
39+
//containerId of the functor-table.
40+
std::size_t m_containerId;
4141

42-
//signature of functor as string. platform dependent, may not be very much readable format.
43-
std::string m_signature;
42+
//signature of functor as string. platform dependent, may not be very much readable format.
43+
std::string m_signature;
4444

45-
GETTER(std::size_t, Index, m_index)
46-
GETTER(std::size_t, ReturnId, m_returnId);
47-
GETTER(std::size_t, RecordId, m_recordId);
48-
GETTER(std::size_t, SignatureId, m_containerId)
49-
GETTER(std::string, SignatureStr, m_signature)
45+
lambda_table* m_lambdaTable = nullptr;
5046

51-
/* @method: getHashCode()
52-
@return: std::size_t (a unique hash-code for a functor)
53-
* 'm_containerId' will be same for functors(non-member) with same signatures.
54-
* for member functions, a functor will have three atrributes
55-
- signature
56-
- whether it is const or non-const
57-
- class/struct type
58-
'm_containerId' will be same for functors with same above attributes.
59-
* every functor will have a distinct index in the functor-wrapped-lambda-table.
60-
* so, combination of m_containerId & m_index is unique for every functor.
61-
*/ std::size_t getHashCode() const
62-
{
63-
return std::stoull(std::to_string(m_containerId) +
64-
std::to_string(m_index) +
65-
std::to_string(m_recordId) +
66-
std::to_string(m_returnId));
67-
}
47+
GETTER(std::size_t, Index, m_index)
48+
GETTER(std::size_t, ReturnId, m_returnId);
49+
GETTER(std::size_t, RecordId, m_recordId);
50+
GETTER(std::size_t, SignatureId, m_containerId)
51+
GETTER(std::string, SignatureStr, m_signature)
6852

69-
const bool operator==(const FunctorId& pOther) const
70-
{
71-
return (m_index == pOther.m_index && m_returnId == pOther.m_returnId &&
72-
m_recordId == pOther.m_recordId && m_containerId == pOther.m_containerId &&
73-
m_signature == pOther.m_signature);
74-
}
75-
};
76-
}
53+
/* @method: getHashCode()
54+
@return: std::size_t (a unique hash-code for a functor)
55+
* 'm_containerId' will be same for functors(non-member) with same signatures.
56+
* for member functions, a functor will have three atrributes
57+
- signature
58+
- whether it is const or non-const
59+
- class/struct type
60+
'm_containerId' will be same for functors with same above attributes.
61+
* every functor will have a distinct index in the functor-wrapped-lambda-table.
62+
* so, combination of m_containerId & m_index is unique for every functor.
63+
*/ std::size_t getHashCode() const
64+
{
65+
return std::stoull(std::to_string(m_containerId) +
66+
std::to_string(m_index) +
67+
std::to_string(m_recordId) +
68+
std::to_string(m_returnId));
69+
}
70+
71+
const bool operator==(const FunctorId& pOther) const
72+
{
73+
return (m_index == pOther.m_index && m_returnId == pOther.m_returnId &&
74+
m_recordId == pOther.m_recordId && m_containerId == pOther.m_containerId &&
75+
m_signature == pOther.m_signature);
76+
}
77+
};
7778
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*************************************************************************
2+
* *
3+
* Reflection Template Library (RTL) - Modern C++ Reflection Framework *
4+
* https://github.com/ReflectCxx/ReflectionTemplateLibrary-CPP *
5+
* *
6+
* Copyright (c) 2025 Neeraj Singh <reflectcxx@outlook.com> *
7+
* SPDX-License-Identifier: MIT *
8+
* *
9+
*************************************************************************/
10+
11+
12+
#pragma once
13+
14+
#include <vector>
15+
#include <functional>
16+
17+
#include "Constants.h"
18+
19+
namespace rtl {
20+
21+
class RObject;
22+
struct Return;
23+
}
24+
25+
namespace rtl::detail
26+
{
27+
class lambda_table { };
28+
}
29+
30+
31+
namespace rtl::detail
32+
{
33+
template<class ...signature_ts>
34+
class functors : public lambda_table
35+
{
36+
using lambda_t = std::function <Return(signature_ts...)>;
37+
38+
std::vector<lambda_t> m_lambdaTable;
39+
40+
public:
41+
42+
GETTER_CREF(std::vector<lambda_t>, , m_lambdaTable)
43+
44+
void pushBack(const lambda_t& pLambda) {
45+
m_lambdaTable.push_back(pLambda);
46+
}
47+
};
48+
49+
50+
template<class ...signature_ts>
51+
class const_functors : public lambda_table
52+
{
53+
using lambda_t = std::function <Return(const RObject&, signature_ts...)>;
54+
55+
std::vector<lambda_t> m_lambdaTable;
56+
57+
public:
58+
59+
GETTER_CREF(std::vector<lambda_t>, , m_lambdaTable)
60+
61+
void pushBack(const lambda_t& pLambda) {
62+
m_lambdaTable.push_back(pLambda);
63+
}
64+
};
65+
66+
67+
template<class ...signature_ts>
68+
class nonconst_functors : public lambda_table
69+
{
70+
using lambda_t = std::function <Return(const RObject&, signature_ts...)>;
71+
72+
std::vector<lambda_t> m_lambdaTable;
73+
74+
public:
75+
76+
GETTER_CREF(std::vector<lambda_t>, , m_lambdaTable)
77+
78+
void pushBack(const lambda_t& pLambda) {
79+
m_lambdaTable.push_back(pLambda);
80+
}
81+
};
82+
}

0 commit comments

Comments
 (0)