Solved

Question on Thread control functions and availability of member variables.

Posted on 2004-10-07
6
255 Views
Last Modified: 2008-02-26
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
0
Comment
Question by:PMH4514
  • 4
  • 2
6 Comments
 
LVL 14

Accepted Solution

by:
wayside earned 50 total points
ID: 12249862
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
 
LVL 14

Expert Comment

by:wayside
ID: 12249900
> 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
 

Author Comment

by:PMH4514
ID: 12250048

>>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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 
LVL 14

Expert Comment

by:wayside
ID: 12250403
> 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
 

Author Comment

by:PMH4514
ID: 12253183
nice, that's basically what I had envisioned.. only I was thinking some kind of typedef struct.. same difference though right?
0
 
LVL 14

Expert Comment

by:wayside
ID: 12253737
Yup. Making it a class lets you create them in line, which I find more convenient, because classes have constructors.

0

Featured Post

Highfive Gives IT Their Time Back

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Templates For Beginners Or How To Encourage The Compiler To Work For You Introduction This tutorial is targeted at the reader who is, perhaps, familiar with the basics of C++ but would prefer a little slower introduction to the more ad…
IntroductionThis article is the second in a three part article series on the Visual Studio 2008 Debugger.  It provides tips in setting and using breakpoints. If not familiar with this debugger, you can find a basic introduction in the EE article loc…
The viewer will learn how to pass data into a function in C++. This is one step further in using functions. Instead of only printing text onto the console, the function will be able to perform calculations with argumentents given by the user.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now