Click to See Complete Forum and Search --> : passing objects between threads


rbadea_a
August 10th, 2005, 08:43 AM
Hello,

I have the following questions:

Please explain in more detail the following quote from msdn:

Windows Handle Maps
As a general rule, a thread can access only MFC objects that it created.

This is because temporary and permanent Windows handle maps are kept in thread local storage to ensure protection from simultaneous access from multiple threads. For example, a worker thread cannot perform a calculation and then call a document's UpdateAllViews member function to have the windows that contain views on the new data modified. This will have no effect at all, because the map from CWnd objects to HWNDs is local to the primary thread. This means that one thread may have a mapping from a Windows handle to a C++ object, but another thread may map that same handle to a different C++ object. Changes made in one thread would not be reflected in the other.

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html/_core_multithreading.3a_.programming_tips.asp

Is the text above referencing ONLY MFC classes with handles, like CWnd ,CSocket, etc. (as specified in Technical Note 3 from the msdn VC++ documentation) or ALL MFC classes or ANY class (which I don't think) ?

What I mean is the following:
If I define a class of my own, CMyClass, which is not derived from any MFC class, can I pass a pointer to it in the call of AfxBeginThread ? Also, if the
object "CMyClass m_myObject" is declared as a member of a CWnd derived class in the main app thread, let's say CMyDialog (not on the heap), could there be some problems by passing this object to a worker thread? (Assuming of course the life time of the object is not an issue, destroyed when the app finished).

Example:

BOOL CMyDialogApp ::InitInstance()
{
if (!AfxSocketInit())
{
AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return FALSE;
}

AfxEnableControlContainer();

CMyDialog dlg;
m_pMainWnd = &dlg;
int nResponse = dlg.DoModal();
if (nResponse == IDOK)
{
}
else if (nResponse == IDCANCEL)
{
}

return FALSE;
}


Can a thread access also the stack of another thread? (Is passing a pointer to a stack object of another thread possible, again, presuming the lifetime of the stack object is not an issue) ?

Thank you .

Arjay
August 10th, 2005, 10:19 AM
You can pass a pointer to your own class between threads; however, you must be sure to synchronize access when reading or writing to the data (use a critical section, mutex or some other synch primitive). Btw, in your post you refer to a non-derived MFC class, but in your example you show an MFC-derived class. Is this a typo?

Arjay

rbadea_a
August 10th, 2005, 12:54 PM
The idea is that in the Dialog derived class I want to have as a data member
an object of my own. As far as I know, the main Dialog for a dialog based application is on the stack, as in the example I have posted. (I have posted an instance of an InitInstance function for the application class)
The Dialog derived class could be something like:

class CMyClass
{
CMyClass();
~CMyClass();
//other data members and functions
}

class CMyDialog : public CDialog
{
// Construction
public:
CMyDialog (CWnd* pParent = NULL); // standard constructor
// data :
CMyClass m_myClass;

// Implementation
protected:

};

I am not sure about the access rights of an thread in the stack area of another, I remember I have tried this an it worked , but I am not sure if such an access is normally allowed or not. Surely, synchronization is an obvious issue. I need to access some socket handles (not MFC object bound, just obtained directly from API call socket or WSASocket) and an IOCP (IO Completion Port) object from diferent threads. These are member object of a class of my own.

Anyway thank You for your quick answer.

MrViggy
August 11th, 2005, 10:18 AM
MFC class objects cannot be passed between threads, however HANDLES can. Now, if you have a dialog class, that has a member variable that is your own data, you can pass that data between threads. However, as was said, access to the data must be synchronized. Also, you have to be careful that if the data goes out of scope (on it's own, or because the dialog was destructed), your thread doesn't try to access it (which can happen in your example). You *could* pass the dialog class you your thread, as long as you only access your class member ("m_myClass" in your example). But that might be confusing to others, not to mention you run the risk of accidentally calling an MFC function.

A better method would be to allocate the data someplace else, and let both the thread and the dialog access it (perhaps a singleton).

Viggy

Axter
August 14th, 2005, 12:55 AM
Consider using the following smart pointer, which has automatic synchronization built-in:
http://code.axter.com/sync_ptr.h

Also need the following associated header to use above smart pointer:
http://code.axter.com/sync_ctrl.h