5

How can I pass boost::shared_ptr as a pointer to a Windows Thread function ? assume following code :

test::start()
{
    ....
    _beginthreadex( NULL, 0, &test::threadRun, &shared_from_this(), 0, &threadID );

    ...
    ...
}

/*this is a static function*/
UINT __stdcall test::threadRun( LPVOID lpParam )
{ 
     shared_ptr<test> k = *static_cast< shared_ptr<test>* >(lpParam);
     ...
}

I think this code is incorrect, what is your idea ? how can I do this ?

EDIT : I solved my problem by boost::weak_ptr. check my own answer in this page

Community
  • 1
  • 1
Behrouz.M
  • 3,445
  • 6
  • 37
  • 64
  • 2
    why don't you just use Boost.Thread instead? – jalf Feb 24 '11 at 08:21
  • I have a lot of codes that worked with windows thread, currently I have not enough time to convert them to boost.Thread, Also, I have never used boost.thread. – Behrouz.M Feb 24 '11 at 08:23
  • 3
    you don't need to convert them all. But Boost.Thread is type safe, and handles this problem very intuitively. – jalf Feb 24 '11 at 08:33

4 Answers4

3

When you have to pass parameter from a class to a static function/method and what you have is a callback parameter (usual in thread callbacks), I usually pass this to the callback. This way you have one simple cast and you have access to all members of your class. Practically, the callback is as a member of your class :

test::start()
{
    // [...]
    _beginthreadex(NULL, 0, &test::threadRun, this, 0, &threadID);
    // [...]
}

// this is a static function
UINT __stdcall test::threadRun(LPVOID lpParam)
{ 
     test* self = static_cast<test*>(lpParam);

     // do whatever you want with all the instance members :)

     self->getMyShared();
     self->useMyGreatMemberMethof();

     // ...
}

my2c

neuro
  • 14,948
  • 3
  • 36
  • 59
1

You should use a reinterpret_cast and take care that you hold at least one shared_ptr during the spawning. Otherwise your object will be destroyed. That is, since you pass a pointer to shared_ptr, you won't enjoy the usual pointer protection and if all your existing shared_ptrs are destroyed, then when your thread is spawned it will contain an illegal pointer.

FireAphis
  • 6,650
  • 8
  • 42
  • 63
1

I solved my problem by boost::weak_ptr:

test::start()
{
    ....
    shared_ptr<test> shPtr = shared_from_this();
    boost::weak_ptr<test> wPtr=shPtr;
    _beginthreadex( NULL, 0, &test::threadRun, &wPtr, 0, &threadID );

    ...
    ...
}

/*this is a static function*/
UINT __stdcall test::threadRun( LPVOID lpParam )
{ 
shared_ptr<test> k      = static_cast< boost::weak_ptr<test>* >(lpParam)->lock();
     ...
}
Behrouz.M
  • 3,445
  • 6
  • 37
  • 64
  • 3
    This is not guaranteed to solve the problem as wPtr is a local variable in test::start() and will be invalidated when test::start() ends, so the issue is the same as before unless you wait for the thread you start to "pick up" the parameter before start() exits. – CashCow Feb 24 '11 at 12:11
0

This is one of the situations actually where intrusive reference counting works well.

If you want to pass the boost::shared_ptr you can put it into a struct that has intrusive reference counting and pass it in.

This is assuming you don't just want to pass in a raw pointer and get the receiving thread to delete it when finished.

CashCow
  • 30,981
  • 5
  • 61
  • 92