Solved

Question on Thread control functions and availability of member variables.

Posted on 2004-10-07
6
258 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
Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

 
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

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
Container Orchestration platforms empower organizations to scale their apps at an exceptional rate. This is the reason numerous innovation-driven companies are moving apps to an appropriated datacenter wide platform that empowers them to scale at a …
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

829 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