I have a simple Threads class based on pthreads which works fine with a standard static callback function.
Is it possible to generalize Threads to work with lambdas, too?
problems:
sandbox.cpp:27:26: error: invalid cast from type ‘main(int, char*)::’ to type ‘void’
thread_cb() needs to deal with generically casting void* back into something callable
I suspect the second problem may be solved with template methods or maybe std::function, but not sure how.
#include <vector>
#include <iostream>
#include <pthread.h>
class Threads
{
public:
Threads() { }
~Threads() { }
private:
static void *thread_cb( void *v )
{
// following will also need to change
void (*my_fptr)() =
reinterpret_cast<void(*)()>(reinterpret_cast<long long>(v));
my_fptr();
return nullptr;
}
public:
template<typename CALLBACK>
void spawn( CALLBACK cb )
{
pthread_t t;
void *p = (void*)( cb ); // problem here
pthread_create( &t, nullptr, thread_cb, p );
m_threads.push_back( t );
}
void join_all()
{
for ( auto& p : m_threads )
pthread_join( p, nullptr );
}
private:
std::vector< pthread_t > m_threads;
};
static void my_cb()
{
std::cerr << "bar" << std::endl;
}
int main(int argc, char** argv)
{
Threads t;
t.spawn( my_cb ); // ok
t.spawn( []() { std::cerr << "foo" << std::endl; } ); // not ok
t.join_all();
return 0;
}
You can use "lambda to function pointer" conversion. ...be that as it may, I strongly recommend std::thread.
template<typename CALLBACK>
void spawn( CALLBACK cb )
{
pthread_t t;
// void *p = (void*)( cb );
// pthread_create( &t, nullptr, thread_cb, p );
void (*pfn)() = cb; // function pointer to `void()`
pthread_create( &t, nullptr, thread_cb, reinterpret_cast<void*>(pfn) );
m_threads.push_back( t );
}
Related
For exchanging data between classes, I use a kind of "main-hub-class", from which each other class can access the data.
Now, to make this thread-safe I came up with a templated struct that holds a variable and a boost::shared_mutex for that variable:
class DataExchange {
[...]
template <typename T>
struct ShareDataEntry {
T value;
boost::shared_mutex _mutex;
};
SharedDataEntry<int> ultraSonicValue;
[...]
}
In the .cpp I am trying to use that like this:
void DataExchange::setUltrasSonicValue(int _value) {
boost::unique_lock<boost::shared_mutex> lock ( ultraSonicValue._mutex ); // <-- this segfaults
ultraSonicValue.value = _value;
lock.unlock();
}
From gdb, I get the error
__GI____pthread_mutex_lock (mutex=0x58) at pthread_mutex_lock.c:66
66 pthread_mutex_lock.c: No such file or directory
What am I doing wrong? My guess is that the mutex isn't initialized? But how (and where) would I do that?
EDIT
Updated code sample, now showing everything I use, also with a test for the problem I described:
DataExchange.hpp:
#pragma once
#include <boost/thread.hpp>
class DataExchange {
private:
DataExchange();
DataExchange(DataExchange const&) {};
DataExchange& operator=(DataExchangeconst&) { return *instance; };
static DataExchange* instance;
template <typename T>
struct ShareDataEntry {
T value;
boost::shared_mutex _mutex;
};
// simple int with extra mutex
int testIntOne;
boost::shared_mutex testIntOne_M;
// int in my struct
SharedDataEntry<int> testIntTwo;
public:
static DataExchange* getInstance();
~DataExchange() { delete instance; };
void setTestIntOne(int _tmp);
int getTestIntOne();
void setTestIntTwo(int _tmp);
int getTestIntTwo();
}
DataExchange.cpp:
#include "infrastructure/DataExchange.hpp"
DataExchange* DataExchange::instance = NULL;
DataExchange::DataExchange() {};
DataExchange* DataExchange::getInstance() {
if (instance == NULL) instance = new DataExchange;
return instance;
}
void DataExchange::setTestIntOne(int _tmp) {
boost::unique_lock<boost::shared_mutex> lock ( testIntOne_M ); // this is now where the segfault occurs
testIntOne = _tmp;
lock.unlock();
}
int DataExchange::getTestIntOne() {
boost::shared_lock<boost::shared_mutex> lock ( testIntOne_M );
return testIntOne;
}
void DataExchange::setTestIntTwo(int _tmp) {
boost::unique_lock<boost::shared_mutex> lock ( testIntTwo._mutex );
testIntTwo.value = _tmp;
lock.unlock();
}
int DataExchange::getTestIntTwo() {
boost::shared_lock<boost::shared_mutex> lock ( testIntTwo._mutex );
return testIntTwo.value;
}
main.cpp:
#inlcude "infarstructure/DataExchange.hpp"
int main(int argc, char *argv[]) {
DataExchange* dataExchange = DataExchange::getInstance();
// this line segfaults already, altough I was pretty sure it worked before
dataExchange->setTestIntOne(5);
cout << dataExchange->getTestIntOne() << "\n";
dataExchange->setTestIntTwo(-5);
cout << dataExchange->getTestIntTwo() << "\n";
return 0;
}
Does it segfault because the mutex wasn't initialized?
Also, I am very sure it worked earlier, at least the first way (without the struct).
Second Edit:
Alright, everything is working fine now. It was a stupid mistake on my part. Both approaches work flawlessly - as long as one initializes the DataExchange object.
I'm trying to register a class member function as a (regular) callback function. Unless I've misunderstood something, this should be possible using std::bind (using C++11). I do this the following way:
std::function<void (GLFWwindow*, unsigned int)> cb = std::bind(&InputManager::charInputCallback, this, std::placeholders::_1, std::placeholders::_2);
My callback function is defined in the following way:
void InputManager::charInputCallback(GLFWwindow* window, unsigned int key)
I'm able to test cb immediately after creating using random data:
cb(NULL, 0x62);
I can confirm that this data is sent correctly to the callback function by printing to the terminal from within it.
However, I want to register this function to GLFW so that the keypresses of the program window gets sent to the callback function. I do that like this:
glfwSetCharCallback(window, (GLFWcharfun) &cb);
Like I said before: calling it manually works just fine. When I register it as a callback though, I get a segmentation fault whenever I press a key and GLFW tries to call the callback function.
Is std::bind not what I'm looking for? Am I using it incorrectly?
Edit:
I don't think this question is a duplicate of How can I pass a class member function as a callback? like it has been identified as. While we're adressing the same problem, I'm asking about this particular solution, using std::bind, which is only mentioned but never explained in one of the answers to the other question.
Here is the function declaration:
GLFWcharfun glfwSetCharCallback ( GLFWwindow * window,
GLFWcharfun cbfun
)
Where GLFWcharfun is defined as typedef void(* GLFWcharfun) (GLFWwindow *, unsigned int)
There is an obvious problem here in that you do not get the opportunity to pass in a 'context' object which will automatically map the callback back to an instance of InputManager. So you will have to perform the mapping manually using the only key you have available - the window pointer.
Here is one strategy...
#include <map>
#include <mutex>
struct GLFWwindow {};
typedef void(* GLFWcharfun) (GLFWwindow *, unsigned int);
GLFWcharfun glfwSetCharCallback ( GLFWwindow * window,
GLFWcharfun cbfun
);
struct InputManager;
struct WindowToInputManager
{
struct impl
{
void associate(GLFWwindow* window, InputManager* manager)
{
auto lock = std::unique_lock<std::mutex>(mutex_);
mapping_[window] = manager;
}
void disassociate(GLFWwindow* window, InputManager* manager)
{
auto lock = std::unique_lock<std::mutex>(mutex_);
mapping_.erase(window);
}
InputManager* find(GLFWwindow* window) const
{
auto lock = std::unique_lock<std::mutex>(mutex_);
auto i = mapping_.find(window);
if (i == mapping_.end())
return nullptr;
else
return i->second;
}
mutable std::mutex mutex_;
std::map<GLFWwindow*, InputManager*> mapping_;
};
static impl& get_impl() {
static impl i {};
return i;
}
void associate(GLFWwindow* window, InputManager* manager)
{
get_impl().associate(window, manager);
}
void disassociate(GLFWwindow* window, InputManager* manager)
{
get_impl().disassociate(window, manager);
}
InputManager* find(GLFWwindow* window)
{
return get_impl().find(window);
}
};
struct InputManager
{
void init()
{
// how to set up the callback?
// first, associate the window with this input manager
callback_mapper_.associate(window_, this);
// now use a proxy as the callback
glfwSetCharCallback(window_, &InputManager::handleCharCallback);
}
static void handleCharCallback(GLFWwindow * window,
unsigned int ch)
{
// proxy locates the handler
if(auto self = callback_mapper_.find(window))
{
self->charInputCallback(window, ch);
}
}
void charInputCallback(GLFWwindow * window,
int ch)
{
// do something here
}
GLFWwindow* window_;
static WindowToInputManager callback_mapper_;
};
Or if you prefer closures:
#include <map>
#include <mutex>
struct GLFWwindow {};
typedef void(* GLFWcharfun) (GLFWwindow *, unsigned int);
GLFWcharfun glfwSetCharCallback ( GLFWwindow * window,
GLFWcharfun cbfun
);
struct InputManager;
struct WindowToInputManager
{
using sig_type = void (GLFWwindow *, unsigned int);
using func_type = std::function<sig_type>;
struct impl
{
void associate(GLFWwindow* window, func_type func)
{
auto lock = std::unique_lock<std::mutex>(mutex_);
mapping_[window] = std::move(func);
}
void disassociate(GLFWwindow* window)
{
auto lock = std::unique_lock<std::mutex>(mutex_);
mapping_.erase(window);
}
const func_type* find(GLFWwindow* window) const
{
auto lock = std::unique_lock<std::mutex>(mutex_);
auto i = mapping_.find(window);
if (i == mapping_.end())
return nullptr;
else
return std::addressof(i->second);
}
mutable std::mutex mutex_;
std::map<GLFWwindow*, func_type> mapping_;
};
static impl& get_impl() {
static impl i {};
return i;
}
template<class F>
void associate(GLFWwindow* window, F&& f)
{
get_impl().associate(window, std::forward<F>(f));
glfwSetCharCallback(window, &WindowToInputManager::handleCharCallback);
}
void disassociate(GLFWwindow* window)
{
// call whatever is the reverse of glfwSetCharCallback here
//
// then remove from the map
get_impl().disassociate(window);
}
const func_type* find(GLFWwindow* window)
{
return get_impl().find(window);
}
static void handleCharCallback(GLFWwindow* w, unsigned int ch)
{
auto f = get_impl().find(w);
// note - possible race here if handler calls disasociate. better to return a copy of the function?
if (f) {
(*f)(w, ch);
}
}
};
struct InputManager
{
void init()
{
callback_mapper_.associate(window_, [this](auto* window, int ch) { this->charInputCallback(window, ch); });
}
void charInputCallback(GLFWwindow * window,
int ch)
{
// do something here
}
GLFWwindow* window_;
WindowToInputManager callback_mapper_;
};
Is there a way to std::bind to a std::weak_ptr? I'd like to store a "weak function" callback that automatically "disconnects" when the callee is destroyed.
I know how to create a std::function using a shared_ptr:
std::function<void()> MyClass::GetCallback()
{
return std::function<void()>(std::bind(&MyClass::CallbackFunc, shared_from_this()));
}
However the returned std::function keeps my object alive forever. So I'd like to bind it to a weak_ptr:
std::function<void()> MyClass::GetCallback()
{
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
}
But that doesn't compile. (std::bind will accept no weak_ptr!) Is there any way to bind to a weak_ptr?
I've found discussions about this (see below), but there seems to be no standard implementation. What is the best solution for storing a "weak function", in particular if Boost is not available?
Discussions / research (all of these use Boost and are not standardized):
weak_function
weak_ptr binding
"weak" binding (and a fix for it)
weak_fn
Another weak_fn
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, thisWeakPtr));
You should never do this. Ever.
MyClass::CallbackFunc is a non-static member function of the class MyClass. Being a non-static member function, it must be called with a valid instance of MyClass.
The entire point of weak_ptr is that it isn't necessarily valid. You can detect its validity by transforming it into a shared_ptr and then testing if the pointer is NULL. Since weak_ptr is not guaranteed to be valid at all times, you cannot call a non-static member function with one.
What you're doing is no more valid than:
std::bind(&MyClass::CallbackFunc, nullptr)
It may compile, but it will eventually crash when you try to call it.
Your best bet is to use actual logic, to not call the callback function if the weak_ptr is not valid. bind is not designed to do logic; it just does exactly what you tell it to: call the function. So you need to use a proper lambda:
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>([thisWeakPtr]()
{
auto myPtr = thisWeakPtr.lock();
if(myPtr)
myPtr->CallbackFunc()
});
I was able to create weak_pointers of std::function and tested it with clang-3.2 (you didn't give any compiler restrictions).
Here's a sample app that creates and tests what I believe you are asking for:
#include <functional>
#include <memory>
#include <iostream>
typedef std::function<void(void)> Func;
typedef std::shared_ptr<Func> SharedFunc;
typedef std::weak_ptr<Func> WeakFunc;
void Execute( Func f ) {
f();
}
void Execute( SharedFunc sf ) {
(*sf)();
}
void Execute( WeakFunc wf ) {
if ( auto f = wf.lock() )
(*f)();
else
std::cout << "Your backing pointer went away, sorry.\n";
}
int main(int, char**) {
auto f1 = [](){ std::cout << "Func here.\n"; };
Execute( f1 );
auto f2 = [](){ std::cout << "SharedFunc here.\n"; };
SharedFunc sf2( new Func(f2) );
Execute( sf2 );
auto f3 = [](){ std::cout << "WeakFunc here.\n"; };
SharedFunc sf3( new Func(f3) );
WeakFunc wf3( sf3 );
Execute( wf3 );
// Scoped test to make sure that the weak_ptr is really working.
WeakFunc wf4;
{
auto f4 = [](){ std::cout << "You should never see this.\n"; };
SharedFunc sf4( new Func(f4) );
wf4 = sf4;
}
Execute( wf4 );
return 0;
}
The output was:
~/projects/stack_overflow> clang++-mp-3.2 --std=c++11 --stdlib=libc++ weak_fun.cpp -o wf && ./wf
Func here.
SharedFunc here.
WeakFunc here.
Your backing pointer went away, sorry.
#include <iostream>
#include <string>
#include <memory>
#include <functional>
using namespace std;
template < typename T > class LockingPtr {
std :: weak_ptr < T > w;
public:
typedef shared_ptr < T > result_type;
LockingPtr ( const std :: shared_ptr < T > & p ) : w ( p ) { }
std :: shared_ptr < T > lock ( ) const {
return std :: shared_ptr < T > ( w );
}
std :: shared_ptr < T > operator-> ( ) const {
return lock ( );
}
template < typename ... Args > std :: shared_ptr < T > operator( ) ( Args ... ) const {
return lock ( );
}
};
template < typename T > LockingPtr < T > make_locking ( const shared_ptr < T > & p ) {
return p;
}
namespace std {
template < typename T > struct is_bind_expression < LockingPtr < T > > :
public true_type { };
}
int main() {
auto p = make_shared < string > ( "abc" );
auto f = bind ( & string :: c_str, make_locking ( p ) );
cout << f ( ) << '\n';
p.reset ( );
try {
cout << f ( ) << '\n';
} catch ( const exception & e ) {
cout << e.what ( ) << '\n';
}
// your code goes here
return 0;
}
output:
abc
bad_weak_ptr
I know this is an old question, but I have the same requirement and I'm sure I'm not alone.
The solution in the end for me was to return a function object that returns a boost::optional<> depending on whether the function was called or not.
code here:
#include <boost/optional.hpp>
#include <memory>
namespace value { namespace stdext {
using boost::optional;
using boost::none;
struct called_flag {};
namespace detail
{
template<class Target, class F>
struct weak_binder
{
using target_type = Target;
using weak_ptr_type = std::weak_ptr<Target>;
weak_binder(weak_ptr_type weak_ptr, F f)
: _weak_ptr(std::move(weak_ptr))
, _f(std::move(f))
{}
template<class...Args,
class Result = std::result_of_t<F(Args...)>,
std::enable_if_t<not std::is_void<Result>::value>* = nullptr>
auto operator()(Args&&...args) const -> optional<Result>
{
auto locked_ptr = _weak_ptr.lock();
if (locked_ptr)
{
return _f(std::forward<Args>(args)...);
}
else
{
return none;
}
}
template<class...Args,
class Result = std::result_of_t<F(Args...)>,
std::enable_if_t<std::is_void<Result>::value>* = nullptr>
auto operator()(Args&&...args) const -> optional<called_flag>
{
auto locked_ptr = _weak_ptr.lock();
if (locked_ptr)
{
_f(std::forward<Args>(args)...);
return called_flag {};
}
else
{
return none;
}
}
weak_ptr_type _weak_ptr;
F _f;
};
}
template<class Ret, class Target, class...FuncArgs, class Pointee, class...Args>
auto bind_weak(Ret (Target::*mfp)(FuncArgs...), const std::shared_ptr<Pointee>& ptr, Args&&...args)
{
using binder_type = decltype(std::bind(mfp, ptr.get(), std::forward<Args>(args)...));
return detail::weak_binder<Target, binder_type>
{
std::weak_ptr<Target>(ptr),
std::bind(mfp, ptr.get(), std::forward<Args>(args)...)
};
}
}}
called (for example) like so:
TEST(bindWeakTest, testBasics)
{
struct Y
{
void bar() {};
};
struct X : std::enable_shared_from_this<X>
{
int increment(int by) {
count += by;
return count;
}
void foo() {
}
Y y;
int count = 0;
};
auto px = std::make_shared<X>();
auto wf = value::stdext::bind_weak(&X::increment, px, std::placeholders::_1);
auto weak_call_bar = value::stdext::bind_weak(&Y::bar, std::shared_ptr<Y>(px, &px->y));
auto ret1 = wf(4);
EXPECT_TRUE(bool(ret1));
EXPECT_EQ(4, ret1.get());
auto wfoo1 = value::stdext::bind_weak(&X::foo, px);
auto retfoo1 = wfoo1();
EXPECT_TRUE(bool(retfoo1));
auto retbar1 = weak_call_bar();
EXPECT_TRUE(bool(retbar1));
px.reset();
auto ret2 = wf(4);
EXPECT_FALSE(bool(ret2));
auto retfoo2 = wfoo1();
EXPECT_FALSE(bool(retfoo2));
auto retbar2 = weak_call_bar();
EXPECT_FALSE(bool(retbar2));
}
source code and tests available here:
https://github.com/madmongo1/valuelib
Not sure why that definition is not in boost. There must be a good reason (how to deal with lock fail? Is throwing from there acceptable? Thread safety?) Anyway, that will validate your callee.
namespace boost {
template<class T> T * get_pointer(boost::weak_ptr<T> const& p)
{
boost::shared_ptr< T > _strong = p.lock();
if( _strong )
return _strong.get();
else
throw 1;
}
}
int main(int arg, char *argv[])
{
boost::weak_ptr< MyType > weak_bad;
{
boost::shared_ptr< MyType > strong(new MyType);
boost::weak_ptr< MyType > weak(strong);
boost::function< void(int) > _func1 = boost::bind(&MyType::setX, weak, _1);
_func1(10);
weak_bad = strong;
}
try {
boost::function< void(int) > _func1 = boost::bind(&MyType::setX, weak_bad, _1);
_func1(10);
}
catch(...)
{
std::cout << "oops!";
}
return 0;
};
Another solution:
You could wrap the std::function. The class producing the callback would hold a shared_ptr< wrapper_type > and provide a weak_ptr< wrapper_type >. The producing object would be the one with the ownership, if it goes out of scope, callers won't be able to promote their weak reference. Your wrapper type could forward call arguments to the std::function or simply expose it via its interface. Just make sure that on copy you properly handle the shared_ptr on the wrapper (don't share).
template< typename _Ty >
struct wrapper
{
wrapper(_Ty wrappe)
: _wrappe(wrappe)
{ }
_Ty _wrappe;
};
...
boost::shared_ptr< wrapper < std::func< ... > > _func(new wrapper < std::func< ... > );
...
boost::weak_ptr< wrapper < std::func< ... > getCallBack() {
return _func;
}
How about this? it works only for actions std::function<void()> but perhaps it can be generalized for arbitrarily parameterized functions.
#include <memory>
#include <functional>
template<typename T>
void
perform_action_or_ignore_when_null(
std::weak_ptr<T> weak,
std::function< void( std::shared_ptr<T> ) > func
)
{
if(auto ptr = weak.lock())
func(ptr);
}
template<typename T>
std::function<void()>
ignore_when_null(
std::weak_ptr<T> weak,
std::function< void( std::shared_ptr<T> ) > func
)
{
return std::bind(perform_action_or_ignore_when_null<T>, weak, func);
}
here's an example usage:
struct Foo {
Foo() {}
void bar() {
std::cout << "hello world!" << std::endl;
}
};
void main()
{
std::weak_ptr<Foo> weakfoo;
std::function<void(std::shared_ptr<Foo>)> foobar = std::bind(&Foo::bar, std::placeholders::_1);
{
auto foo = std::make_shared<Foo>();
weakfoo = foo;
auto f = ignore_when_null(weakfoo, foobar);
f(); // prints "hello world!";
}
auto g = ignore_when_null(weakfoo, foobar);
g(); // does nothing
}
You can bind weak_ptr to the function as one of parameters,
and check it when the function is called.
For example:
std::function<void()> MyClass::GetCallback()
{
std::weak_ptr<MyClass> thisWeakPtr(shared_from_this());
return std::function<void()>(std::bind(&MyClass::CallbackFunc, this,
thisWeakPtr));
}
void MyClass::CallbackFunc(const std::weak_ptr<MyClass>& thisWeakPtr)
{
if (!thisWeakPtr.lock()) {
return;
}
// Do your callback job.
// ...
}
I created a widget.h file containing the declartions of pthread_function and I wanted to call it in a member function destroyWidget of that class Widget in widget.cpp. but always shows an error. I'll show the .cpp and .h file.
widget.h file
class Widget
{
public:
Widget();
void createWidget(int x,int y,int w,int h);
void showWidget();
int wid;
pthread_t thread;
int *incomingval,id;
void join();
Window win;
XEvent evt;
private:
void* destroyWidget(void* ptr);
Display *disp;
int screenNumber;
unsigned long white;
unsigned long black;
long eventMask;
GC gc;
int tbit;
int *incoming,val;
};
now the widget.cpp
Widget::Widget()
{
disp=XOpenDisplay( NULL );
screenNumber=DefaultScreen(disp);
white=WhitePixel(disp,screenNumber);
black=BlackPixel(disp,screenNumber);
eventMask=StructureNotifyMask;
tbit=0;
}
void Widget::createWidget(int x,int y,int w,int h)
{
wid=w;
win= XCreateSimpleWindow(disp,DefaultRootWindow(disp),x,y,w,h,1,white,black);
}
void Widget::showWidget()
{
XMapWindow(disp,win);
XFlush(disp);
gc=XCreateGC(disp,win,0,NULL);
XSetForeground(disp,gc,white);
XDrawLine(disp,win,gc,wid-10,0,wid,10);
XDrawLine(disp,win,gc,wid-10,10,wid,0);
//calling the thread function
pthread_create( &thread, NULL, destroyWidget, this);
}
void Widget::join()
{
pthread_join( thread, NULL);
}
void* Widget::destroyWidget(void* ptr)
{
Widget* mw = static_cast(ptr);
eventMask=ButtonPressMask|ButtonReleaseMask;
XSelectInput(disp,win,eventMask);
do{
printf("id= %d",id);
XNextEvent(disp,&evt);
}while(evt.type!=ButtonRelease);
XDestroyWindow(disp,win);
XCloseDisplay(disp);
return NULL;
}
now the main.cpp file
#include "widget.h"
#include
int main()
{
Widget* w=new Widget();
Widget* n=new Widget();
n->createWidget(20,20,150,150);
w->createWidget(50,50,250,250);
n->showWidget();
w->showWidget();
n->join();
w->join();
return 0;
}
the error is
widget.cpp: In member function ‘void Widget::showWidget()’:
widget.cpp:44:51: error: argument of type ‘void* (Widget::)(void*)’ does not match ‘void* (*)(void*)’
The problem is that pthread_create is a C-style function; you need to give it a pointer-to-function. Widget::destroyWidget() is a pointer-to-member-function. (Remember that non-static member functions always have an implied this argument, which pthread_create doesn't know how to provide.)
See the answers to this question for some possible solutions: pthread function from a class.
The third argument to pthread_create has the signature (in C++):
extern "C" void* (*pointerToFunction)( void* );
You're trying to pass it the address of a member function:
void* (Widget::*pointerToMemberFunction)( void* );
The signatures are incompatible: the second requires an object on which
to call it, and is not extern "C".
The simplest way of handling this is to use boost::thread, with all
it's functional object support. Otherwise, you can define something
like the following:
struct AbstractTask
{
virtual ~AbstractTask() {}
virtual void* run() = 0;
};
template<typename T, void* (T::*ptr)()>
class Task
{
T* myObject;
public:
Task( T* object ) : myObject( object ) {}
virtual void* run()
{
return (myObject->*ptr)();
}
};
extern "C" void* taskRunner( void* arg )
{
std::auto_ptr<AbstractTask> p( static_cast<AbstractTask*>( arg ) );
return p->run();
}
pthread_t taskStarter( AbstractTask* obj )
{
pthread_t result;
pthread_create( &result, NULL, &taskRunner, obj );
return result;
}
To start a thread, you then call:
thread = taskStarter( new Task<Widget, &Widget::destroyWidget>( this ) );
(This is from memory, from an earlier project, so there might be some
typos in it, but you get the idea. And you probably want to add some
error handling in taskStarter.)
Like Oli said you can't use a member function when a C-style function expects a "normal" function pointer. However, what you can do is make a separate function that calls back your destroyWidget() method.
Like so:
void* start_routine(void* arg)
{
Widget* widget = static_cast<Widget* >(arg);
widget->destroyWidget();
return NULL;
}
void Widget::showWidget()
{
pthread_create(&thread, NULL, &start_routine, this);
}
void Widget::destroyWidget()
{
// your code
}
Consider I have the following struct:
struct IDirect3D
{
IDirect3D() : ref_count_(0) {}
unsigned long Release() { return --ref_count_; }
private:
long ref_count_;
~IDirect3D() {}
};
I want to use shared_ptr to it like in the followed code (minimal example):
int main()
{
boost::shared_ptr<IDirect3D> ptr;
IDirect3D* p = 0; // initialized somewhere
ptr.reset( p, boost::mem_fn( &IDirect3D::Release ) );
return 0;
}
This works OK in most cases, but crases if p in equal to 0. I have the following deleter which I want to use:
template<typename T, typename D>
inline void SafeDeleter( T*& p, D d )
{
if ( p != NULL ) {
(p->*d)();
p = NULL;
}
}
But the following code gives a lot of error (looks like it dumps the whole bind.hpp):
ptr.reset( p, boost::bind( SafeDeleter, _1, &IDirect3D::Release ) );
What's wrong with my using of bind?
Release() comes from IUnknown- so why not just use that:
void my_deleter(IUnknown* p) {
// ...
}
ptr.reset(p, &my_deleter);
Note that Boost also has an intrusive_ptr which would seem more natural here:
void intrusive_ptr_add_ref(IUnknown* p) { p->AddRef (); }
void intrusive_ptr_release(IUnknown* p) { p->Release(); }
boost::intrusive_ptr<IDirect3D> d3d(...);
IDirect3D* p = 0;
d3d.reset(p);
Your actual issue is probably that there is a non-template function SafeDeleter - to specifically use the template-function you'd have to use something like:
ptr.reset(p, boost::bind(&SafeDeleter<IDirect3D, ULONG (IDirect3D::*)()>,
_1, &IDirect3D::Release));