Question on Thread control functions and availability of member variables.

If I launch a thread from within an object:

m_pThread = AfxBeginThread(ThreadProcessProc, this, THREAD_PRIORITY_NORMAL, 0, 0, NULL );

and define my ThreadProcessProc as follows:

UINT CVideoCapture::ThreadProcessProc( LPVOID a_pParam )
{
    CVideoCapture* pInstance = (CVideoCapture*) a_pParam;
    // ...
}

Here I've passed "this" as the param to the control function, and so within the ThreadProcessProc method, I cast a_pParam to (CVideoCapture*) so that the calling object is availalbe within the thread's controlling function.

This is correct so far right?

I'm still a bit confused though, if I want to access any member variables or functions defined in the calling object, do I have to do so via this pointer to the calling object?

For example, say the object that is launching the thread has a member variable m_pSomeMember, and an accessor for that called GetSomeMember(). Within my thread control function, if I want to access m_pSomeMember, do I have to do this:

   if ( pInstance->GetSomeMember() == 1 )

or can I access it directly like this:

  if (m_pSomeMember == 1)


Is this where static members come into play? If I want direct access to a member variable from within a thread controlling function, I have to declare it statically, ie.

    BOOL   CVideoCapture::m_bKillThread;

CVideoCapture::CVideoCapture()  // constructor
{
}

What if the member variable my thread control function needs access to is not static? Do I need to implement an accessor method for it which I'd call via the local pInstance reference I cast from the a_pParam?

I hope this makes sense! I'm still just a bit confused.

-Paul
PMH4514Asked:
Who is Participating?

Improve company productivity with a Business Account.Sign Up

x
 
waysideConnect With a Mentor Commented:
First, thread functions need to be declared as static.

Second, because thread functions are static, they have no "this" pointer. You are passing in an object pointer via the parameter and casting it to what you want. So you must use it to access all of the members of the objects. Your statement:

> do I have to do this:

>    if ( pInstance->GetSomeMember() == 1 )

is correct, that's how you have to do it.

If you just try

>  if (m_pSomeMember == 1)

it won't compile because there is no "this" pointer in this function. You would have to do

if (pInstance->pSomeMember == 1)

assuming pSomeMember is declared as public.



0
 
waysideCommented:
> If I want direct access to a member variable from within a thread controlling function, I have to declare it statically

No, you use the param passed in as the argument and cast to the object you need. Then you can access any public members of the object just as you would with any object pointer, i.e.

pInstance->pSomeMember

or

pInstance->GetSomeMember()

I hope this is clear...
0
 
PMH4514Author Commented:

>>First, thread functions need to be declared as static.

yup, I got that.. I showed the implementation of it actually, this is how it's defined in the header:

static UINT ThreadProcessProc( LPVOID a_pParam );

>>is correct, that's how you have to do it.
ok, so I was on the right track.. I was confused because an example I was looking at was setting a m_pKillThread member variable to true at a certain point, and I thought "why can the control function access that member variable on its own?" but then I discovered that m_pKillThread was also declared static.


>>No, you use the param passed in as the argument and cast to the object you need.
>>Then you can access any public members of the object just as you would with any object pointer,

ok this makes total sense. So is it pretty much "convention" to pass "this" as the paramater to the controlling function? "this" of course being a reference to the object that is launching the thread? Or does it totally depend on context and what the thread is doing? My first inclination was to define a struct that held references to all of the launching objects variables that I would need access to, but passing "this" and using accessors does seem much more clear.

>>I hope this is clear...
perfectly, answered my questions exactly. Thanks!

-Paul

0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
waysideCommented:
> So is it pretty much "convention" to pass "this" as the paramater to the controlling function?

It is convention? I don't know, I do it a lot though. It depsnds on what you need to do in the thread.

A lot of times I need more than one piece of data in the thread function, so I have helper classes to package them up:

class PtrPair {
public:
  PtrPair() {i=j=NULL;}
  PtrPair(void *m, void *n) { i=m; j=n; }
  PtrPair(const class PtrPair &p) { i=p.i; j=p.j; }
  void *i,*j;
};

Then I would do something like:

m_pThread = AfxBeginThread(ThreadProcessProc, new PtrPair(this, p_otherptr), THREAD_PRIORITY_NORMAL, 0, 0, NULL );

and in the thread func:

UINT CVideoCapture::ThreadProcessProc( LPVOID a_pParam )
{
   PtrPair pPair = (PtrPair *)a_pParam;
   CVideoCapture* pInstance = (CVideoCapture*) (pPair.i);
   COtherObject* pOtherObj = (COtherObject *)(pPair.j);
   delete pPair;

...
}

I have a bunch of these for different numbers of arguments.
   
0
 
PMH4514Author Commented:
nice, that's basically what I had envisioned.. only I was thinking some kind of typedef struct.. same difference though right?
0
 
waysideCommented:
Yup. Making it a class lets you create them in line, which I find more convenient, because classes have constructors.

0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.