You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
311 lines
12 KiB
311 lines
12 KiB
/*
|
|
Using C++ template functions and recursion to initialize a function pointer pool,
|
|
combined with lambda expressions, this implementation manages function pointers,
|
|
achieving acquisition and release of pointers.All wrappers are used to convert
|
|
and map C++ functions to C functions, and with the use of indexed locking,
|
|
a thread-safe function pointer pool is implemented.For example, the wrapping
|
|
functions essentially map C++ functions to C functions. When a C function callback is triggered,
|
|
the function pointer pool, initialized through template recursion, locates the corresponding C++ function and invokes it.
|
|
*/
|
|
|
|
#define MAX_NUM_OF_CB_S 10
|
|
#define MAX_NUM_OF_CB_I_S 10
|
|
#define MAX_NUM_OF_CB_S_I_S_S 10
|
|
#define MAX_NUM_OF_CB_S_I_S_S_I 10
|
|
#define SLEEP_TIME_FOR_GET_INDEX 100 //ms
|
|
|
|
// use recursive template to generate enough function pointer array
|
|
// and define c type function interface
|
|
// and define manager class to manage function pool
|
|
namespace {
|
|
CB_S* _fps_cb_s=new CB_S[MAX_NUM_OF_CB_S];
|
|
CB_I_S* _fps_cb_i_s=new CB_I_S[MAX_NUM_OF_CB_I_S];
|
|
CB_S_I_S_S* _fps_cb_s_i_s_s=new CB_S_I_S_S[MAX_NUM_OF_CB_S_I_S_S];
|
|
CB_S_I_S_S_I* _fps_cb_s_i_s_s_i=new CB_S_I_S_S_I[MAX_NUM_OF_CB_S_I_S_S_I];
|
|
// c type func interface call cpp function
|
|
std::function<void(const std::string&)>* _cpp_function_cb_s=new std::function<void(const std::string&)>[MAX_NUM_OF_CB_S];
|
|
std::function<void(int,const std::string&)>* _cpp_function_cb_i_s=new std::function<void(int,const std::string&)>[MAX_NUM_OF_CB_I_S];
|
|
std::function<void(const std::string&,int,const std::string&,const std::string&)>* _cpp_function_cb_s_i_s_s=new std::function<void(const std::string&,int,const std::string&,const std::string&)>[MAX_NUM_OF_CB_S_I_S_S];
|
|
std::function<void(const std::string&,int,const std::string&,const std::string&,int)>* _cpp_function_cb_s_i_s_s_i=new std::function<void(const std::string&,int,const std::string&,const std::string&,int)>[MAX_NUM_OF_CB_S_I_S_S_I];
|
|
|
|
template<int N>
|
|
void _generate_cb_s(){
|
|
_fps_cb_s[N]=[](char* c_str){
|
|
_cpp_function_cb_s[N](std::string(c_str));
|
|
};
|
|
_generate_cb_s<N-1>();
|
|
}
|
|
template<>
|
|
void _generate_cb_s<0>(){
|
|
_fps_cb_s[0]=[](char* c_str){
|
|
_cpp_function_cb_s[0](std::string(c_str));
|
|
};
|
|
}
|
|
|
|
template<int N>
|
|
void _generate_cb_i_s(){
|
|
_fps_cb_i_s[N]=[](int code,char* c_str){
|
|
_cpp_function_cb_i_s[N](code,std::string(c_str));
|
|
};
|
|
_generate_cb_i_s<N-1>();
|
|
}
|
|
template<>
|
|
void _generate_cb_i_s<0>(){
|
|
_fps_cb_i_s[0]=[](int code,char* c_str){
|
|
_cpp_function_cb_i_s[0](code,std::string(c_str));
|
|
};
|
|
}
|
|
template<int N>
|
|
void _generate_cb_s_i_s_s(){
|
|
_fps_cb_s_i_s_s[N]=[](char* operationID,int code,char* c_str,char* c_str2){
|
|
_cpp_function_cb_s_i_s_s[N](std::string(operationID),code,std::string(c_str),std::string(c_str2));
|
|
};
|
|
_generate_cb_s_i_s_s<N-1>();
|
|
}
|
|
template<>
|
|
void _generate_cb_s_i_s_s<0>(){
|
|
_fps_cb_s_i_s_s[0]=[](char* operationID,int code,char* c_str,char* c_str2){
|
|
_cpp_function_cb_s_i_s_s[0](std::string(operationID),code,std::string(c_str),std::string(c_str2));
|
|
};
|
|
}
|
|
template<int N>
|
|
void _generate_cb_s_i_s_s_i(){
|
|
_fps_cb_s_i_s_s_i[N]=[](char* operationID,int code,char* c_str,char* c_str2,int c_int){
|
|
_cpp_function_cb_s_i_s_s_i[N](std::string(operationID),code,std::string(c_str),std::string(c_str2),c_int);
|
|
};
|
|
_generate_cb_s_i_s_s_i<N-1>();
|
|
}
|
|
template<>
|
|
void _generate_cb_s_i_s_s_i<0>(){
|
|
_fps_cb_s_i_s_s_i[0]=[](char* operationID,int code,char* c_str,char* c_str2,int c_int){
|
|
_cpp_function_cb_s_i_s_s_i[0](std::string(operationID),code,std::string(c_str),std::string(c_str2),c_int);
|
|
};
|
|
}
|
|
|
|
// init global function pointer array
|
|
void init(){
|
|
_generate_cb_s<MAX_NUM_OF_CB_S-1>();
|
|
_generate_cb_i_s<MAX_NUM_OF_CB_I_S-1>();
|
|
_generate_cb_s_i_s_s<MAX_NUM_OF_CB_S_I_S_S-1>();
|
|
_generate_cb_s_i_s_s_i<MAX_NUM_OF_CB_S_I_S_S_I-1>();
|
|
}
|
|
// define sigle instance class to manage function pool
|
|
class FuncPoolManager{
|
|
private:
|
|
// define a global bitmap, and support atomic operation, to manage cb_s pool
|
|
std::bitset<MAX_NUM_OF_CB_S> _cb_s_bitmap;
|
|
std::bitset<MAX_NUM_OF_CB_I_S> _cb_i_s_bitmap;
|
|
std::bitset<MAX_NUM_OF_CB_S_I_S_S> _cb_s_i_s_s_bitmap;
|
|
std::bitset<MAX_NUM_OF_CB_S_I_S_S_I> _cb_s_i_s_s_i_bitmap;
|
|
std::mutex _cb_s_mutex;
|
|
std::mutex _cb_i_s_mutex;
|
|
std::mutex _cb_s_i_s_s_mutex;
|
|
std::mutex _cb_s_i_s_s_i_mutex;
|
|
FuncPoolManager(){
|
|
init();
|
|
}
|
|
FuncPoolManager(const FuncPoolManager&){}
|
|
public:
|
|
static FuncPoolManager& get_instance(){
|
|
static FuncPoolManager instance;
|
|
return instance;
|
|
}
|
|
// get a available cb_s function index
|
|
int get_cb_s_index(){
|
|
std::lock_guard<std::mutex> lock(_cb_s_mutex);
|
|
int index=-1;
|
|
for(int i=0;i<_cb_s_bitmap.size();i++){
|
|
if(_cb_s_bitmap[i]==0){
|
|
_cb_s_bitmap[i]=1;
|
|
index=i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
// get a available cb_i_s function index
|
|
int get_cb_i_s_index(){
|
|
std::lock_guard<std::mutex> lock(_cb_i_s_mutex);
|
|
int index=-1;
|
|
for(int i=0;i<_cb_i_s_bitmap.size();i++){
|
|
if(_cb_i_s_bitmap[i]==0){
|
|
_cb_i_s_bitmap[i]=1;
|
|
index=i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
// get a available cb_s_i_s_s function index
|
|
int get_cb_s_i_s_s_index(){
|
|
std::lock_guard<std::mutex> lock(_cb_s_i_s_s_mutex);
|
|
int index=-1;
|
|
for(int i=0;i<_cb_s_i_s_s_bitmap.size();i++){
|
|
if(_cb_s_i_s_s_bitmap[i]==0){
|
|
_cb_s_i_s_s_bitmap[i]=1;
|
|
index=i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
// get a available cb_s_i_s_s_i function index
|
|
int get_cb_s_i_s_s_i_index(){
|
|
std::lock_guard<std::mutex> lock(_cb_s_i_s_s_i_mutex);
|
|
int index=-1;
|
|
for(int i=0;i<_cb_s_i_s_s_i_bitmap.size();i++){
|
|
if(_cb_s_i_s_s_i_bitmap[i]==0){
|
|
_cb_s_i_s_s_i_bitmap[i]=1;
|
|
index=i;
|
|
break;
|
|
}
|
|
}
|
|
return index;
|
|
}
|
|
// release a available cb_s function index
|
|
int release_cb_s_index(int index){
|
|
std::lock_guard<std::mutex> lock(_cb_s_mutex);
|
|
if(index<0||index>=_cb_s_bitmap.size()){
|
|
return -1;
|
|
}
|
|
_cpp_function_cb_s[index]=nullptr;
|
|
_cb_s_bitmap[index]=0;
|
|
return 0;
|
|
}
|
|
// release a available cb_i_s function index
|
|
int release_cb_i_s_index(int index){
|
|
std::lock_guard<std::mutex> lock(_cb_i_s_mutex);
|
|
if(index<0||index>=_cb_i_s_bitmap.size()){
|
|
return -1;
|
|
}
|
|
_cpp_function_cb_i_s[index]=nullptr;
|
|
_cb_i_s_bitmap[index]=0;
|
|
return 0;
|
|
}
|
|
// release a available cb_s_i_s_s function index
|
|
int release_cb_s_i_s_s_index(int index){
|
|
std::lock_guard<std::mutex> lock(_cb_s_i_s_s_mutex);
|
|
if(index<0||index>=_cb_s_i_s_s_bitmap.size()){
|
|
return -1;
|
|
}
|
|
_cpp_function_cb_s_i_s_s[index]=nullptr;
|
|
_cb_s_i_s_s_bitmap[index]=0;
|
|
return 0;
|
|
}
|
|
// release a available cb_s_i_s_s_i function index
|
|
int release_cb_s_i_s_s_i_index(int index){
|
|
std::lock_guard<std::mutex> lock(_cb_s_i_s_s_i_mutex);
|
|
if(index<0||index>=_cb_s_i_s_s_i_bitmap.size()){
|
|
return -1;
|
|
}
|
|
_cpp_function_cb_s_i_s_s_i[index]=nullptr;
|
|
_cb_s_i_s_s_i_bitmap[index]=0;
|
|
return 0;
|
|
}
|
|
};
|
|
FuncPoolManager& instance=FuncPoolManager::get_instance();
|
|
|
|
// wrapper persistent function
|
|
// wrapp CB_S,if function pool is full,return nullptr
|
|
CB_S _wrapper_cpp_function(const std::function<void(const std::string&)>& cpp_function) {
|
|
int index=FuncPoolManager::get_instance().get_cb_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_index();
|
|
}
|
|
_cpp_function_cb_s[index]=cpp_function;
|
|
return _fps_cb_s[index];
|
|
}
|
|
// wrapp CB_I_S
|
|
CB_I_S _wrapper_cpp_function(const std::function<void(int,const std::string&)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_i_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_i_s_index();
|
|
}
|
|
_cpp_function_cb_i_s[index]=cpp_function;
|
|
return _fps_cb_i_s[index];
|
|
}
|
|
// wrapp CB_S_I_S_S
|
|
CB_S_I_S_S _wrapper_cpp_function(const std::function<void(const std::string&,int,const std::string&,const std::string&)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_s_i_s_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_i_s_s_index();
|
|
}
|
|
_cpp_function_cb_s_i_s_s[index]=cpp_function;
|
|
return _fps_cb_s_i_s_s[index];
|
|
}
|
|
// wrapp CB_S_I_S_S_I
|
|
CB_S_I_S_S_I _wrapper_cpp_function(const std::function<void(const std::string&,int,const std::string&,const std::string&,int)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_s_i_s_s_i_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_i_s_s_i_index();
|
|
}
|
|
_cpp_function_cb_s_i_s_s_i[index]=cpp_function;
|
|
return _fps_cb_s_i_s_s_i[index];
|
|
}
|
|
|
|
// wrapp function to onetime function
|
|
CB_S _wrapper_callonce_cpp_function(const std::function<void(const std::string&)>& cpp_function) {
|
|
int index=FuncPoolManager::get_instance().get_cb_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_index();
|
|
}
|
|
_cpp_function_cb_s[index]=[cpp_function,index](const std::string& str)->void {
|
|
cpp_function(str);
|
|
FuncPoolManager::get_instance().release_cb_s_index(index);
|
|
};
|
|
return _fps_cb_s[index];
|
|
}
|
|
|
|
CB_I_S _wrapper_callonce_cpp_function(const std::function<void(int,const std::string&)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_i_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_i_s_index();
|
|
}
|
|
_cpp_function_cb_i_s[index]=[cpp_function,index](int code,const std::string& str)->void {
|
|
cpp_function(code,str);
|
|
FuncPoolManager::get_instance().release_cb_i_s_index(index);
|
|
};
|
|
return _fps_cb_i_s[index];
|
|
}
|
|
|
|
CB_S_I_S_S _wrapper_callonce_cpp_function(const std::function<void(const std::string&,int,const std::string&,const std::string&)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_s_i_s_s_index();
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_i_s_s_index();
|
|
}
|
|
_cpp_function_cb_s_i_s_s[index]=[cpp_function,index](const std::string& operationID,int code,const std::string& str,const std::string& str2)->void {
|
|
cpp_function(operationID,code,str,str2);
|
|
FuncPoolManager::get_instance().release_cb_s_i_s_s_index(index);
|
|
};
|
|
return _fps_cb_s_i_s_s[index];
|
|
}
|
|
|
|
CB_S_I_S_S_I _wrapper_callonce_cpp_function(const std::function<void(const std::string&,int,const std::string&,const std::string&,int)>& cpp_function)
|
|
{
|
|
int index=FuncPoolManager::get_instance().get_cb_s_i_s_s_i_index();
|
|
// while loop util get a available index
|
|
while(index<0){
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(SLEEP_TIME_FOR_GET_INDEX));
|
|
index=FuncPoolManager::get_instance().get_cb_s_i_s_s_i_index();
|
|
}
|
|
_cpp_function_cb_s_i_s_s_i[index]=[cpp_function,index](const std::string& operationID,int code,const std::string& str,const std::string& str2,int c_int)->void {
|
|
cpp_function(operationID,code,str,str2,c_int);
|
|
FuncPoolManager::get_instance().release_cb_s_i_s_s_i_index(index);
|
|
};
|
|
return _fps_cb_s_i_s_s_i[index];
|
|
}
|
|
|
|
}
|
|
|
|
|