The original question,對於如何執行非線程安全版本得到了很好的答案。使用C++類成員函數作爲c回調函數,線程安全版本
下面是代碼,我已經試過稍微修改去上班:
#include <stdio.h>
#include <functional>
#include <thread>
void register_with_library(int (*func)(int *k, int *e)) {
int x = 0, y = 1;
int o = func(&x, &y);
}
typedef int (*callback_t)(int*,int*);
class A {
template <typename T>
struct Callback;
template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
template <typename... Args>
thread_local static Ret callback(Args... args) {
func(args...);
}
thread_local static std::function<Ret(Params...)> func;
};
public:
A();
~A();
int e(int *k, int *j);
private:
callback_t func;
};
template <typename Ret, typename... Params>
thread_local std::function<Ret(Params...)> A::Callback<Ret(Params...)>::func;
A::A() {
Callback<int(int*,int*)>::func = std::bind(&A::e, this, std::placeholders::_1, std::placeholders::_2);
printf("1. C callback function ptr %p, C++ template function ptr %p Object ptr %p \n",func, Callback<int(int*,int*)>::func, this) ;
func = static_cast<callback_t>(Callback<int(int*,int*)>::callback);
printf("2. C callback function ptr %p\n",func) ;
register_with_library(func);
}
int A::e(int *k, int *j) {
return *k - *j;
}
A::~A() { }
int main() {
std::thread t1 = std::thread { [](){ A a;}};
std::thread t2 = std::thread { [](){ A a;}};
t1.join();
t2.join();
}
結果是
一個怎樣使這個正常工作,創造新的回調對於每個新對象,考慮到我有多個線程創建不同的對象?
編輯:
如建議通過e.jahandar,使用thread_local作品,以部分解決問題(僅如果每個線程創建1個對象)。由於這個原因,Callback<int(int*,int*)>::func
被分配在一個線程的基礎上。雖然,問題仍然存在,Callback<int(int*,int*)>::callback
。
沒有thread_local:
1. C callback function ptr 0x403148, C++ template function ptr 0x609180 Object ptr 0x7ff9ac9f3e60
2. C callback function ptr 0x403673
1. C callback function ptr 0x4031a6, C++ template function ptr 0x609180 Object ptr 0x7ff9ad1f4e60
2. C callback function ptr 0x403673
與thread_local:
1. C callback function ptr 0x403230, C++ template function ptr 0x7fc1ecc756d0 Object ptr 0x7fc1ecc74e20
2. C callback function ptr 0x403701
1. C callback function ptr 0x4031d2, C++ template function ptr 0x7fc1ec4746d0 Object ptr 0x7fc1ec473e20
2. C callback function ptr 0x403701
除了調用未定義的行爲(假設實際代碼中的register_with_library是用C語言編寫的C庫的成員),此解決方案不允許您註冊兩個相同類型的回調。它只覆蓋上次註冊回調時唯一的靜態變量,並默默丟棄前一個。 –
@ n.m是的,這正是問題所在。但有沒有解決方案? –
看到我的答案。如果您不耐煩,請跳至最後一段。 –