How to send a string to _beginthreadex for the thread to read it?

Oval Piston
Oval Piston used Ask the Experts™
on
I want to use _beginthreadex and pass a character string, the name of a computer. What is the proper way to pass it?


1. By variable itself (sDomain)?

WCHAR sDomain[256] = {0};
...copy domain into sDomain
UINT threadID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &Thread_SaveDomainName, sDomain, 0, &threadID);

Open in new window


2. Or by the address of the variable (&sDomain)?

WCHAR sDomain[256] = {0};
...copy domain into sDomain
UINT threadID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &Thread_SaveDomainName, &sDomain, 0, &threadID);

Open in new window


3. Or make a struct and pass the struct element?

struct strDomain {TCHAR sDomain[256];};
strDomain *sDomain = new strDomain [1]();
UINT threadID = 0;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &Thread_SaveDomainName, &sDomain[0], 0, &threadID);

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Eduard GherguArchitect - Coder - Mentor

Commented:
Hi,

The function expects a void *, I don't understand the question.
murugesandinsWe like KT across the universe.  Shell_script Automation /bin/bash /bin/bash.exe /bin/ksh /bin/mksh.exe AIX C C++ CYGWIN_NT HP-UX Linux MINGW32 MINGW64 SunOS Windows_NT
@Oval Piston
Sample code using cygwin at windows:
#include <unistd.h>
#include <windows.h>
#include <limits.h>
#include <iostream>
using namespace std;
#include <process.h>
struct murugesandinsDomain
{
        public:
                TCHAR sDomain[256];
                murugesandinsDomain()
                {
                        memset( sDomain, '\0', sizeof(sDomain));
                        cout << "Constructor murugesandinsDomain::murugesandinsDomain\n";
                }
                murugesandinsDomain(murugesandinsDomain &md)
                {
                        cout << "murugesandinsDomain::murugesandinsDomain &md\n";
                }
                virtual ~murugesandinsDomain()
                {
                        cout << "Destructor murugesandinsDomain::~murugesandinsDomain\n";
                }
};
unsigned int Thread_SaveDomainName(void *data)
{
        murugesandinsDomain *mDomain = (murugesandinsDomain*)(data);
        if ( NULL == mDomain)
        {
                cout << "Thread:" << " mDomain : NULL\n";
        }
        else
        {
                cout << "Thread:" << " mDomain: " << (char*)(murugesandinsDomain*)mDomain->sDomain << "\n";
        }
        return 0;
}
int main()
{
        UINT threadID = 0;
        HANDLE hThread[10] = {};
        murugesandinsDomain *sDomainPtr[10] = { NULL};
        for( unsigned short ThreadLoop = 0; 3 > ThreadLoop; ThreadLoop++)
        {
#if defined(CYGWIN_NT)
                sDomainPtr[ThreadLoop] = new murugesandinsDomain();
                memset( sDomainPtr[ThreadLoop]->sDomain, '\0', sizeof(sDomainPtr[ThreadLoop]->sDomain));
                sprintf( sDomainPtr[ThreadLoop]->sDomain, "%s%d", "struct murugesandinsDomain", ThreadLoop);
                // _beginthreadex not available in Cygwin. Hence replaced _beginthreadex using CreateThread
                hThread[ThreadLoop] = CreateThread(NULL, 0, Thread_SaveDomainName, sDomainPtr[ThreadLoop], 0, &threadID);
#else
                // At MS C using _beginthreadx
                hThread[ThreadLoop] = _beginthreadex(NULL, 0, &Thread_SaveDomainName, sDomainPtr[ThreadLoop], 0, &threadID);
#endif
                WaitForSingleObject( hThread[ThreadLoop], INFINITE); // Wait at main thread for other threads to complete.
        }
        for( unsigned short ThreadLoop = 0; 3 > ThreadLoop; ThreadLoop++)
        {
                if ( NULL != sDomainPtr[ThreadLoop])
                {
                        delete sDomainPtr[ThreadLoop];
                        sDomainPtr[ThreadLoop] = NULL;
                }
        }
        return 0;
}

Open in new window


$ /usr/bin/g++ -g -D$(/usr/bin/uname -s | /usr/bin/sed "s/\-[0-9]\.[0-9]//") -Wall ./29167779.cpp -pthread -o ./a.out
$ ./a.out
Constructor murugesandinsDomain::murugesandinsDomain
Thread: mDomain: struct murugesandinsDomain0
Constructor murugesandinsDomain::murugesandinsDomain
Thread: mDomain: struct murugesandinsDomain1
Constructor murugesandinsDomain::murugesandinsDomain
Thread: mDomain: struct murugesandinsDomain2
Destructor murugesandinsDomain::~murugesandinsDomain
Destructor murugesandinsDomain::~murugesandinsDomain
Destructor murugesandinsDomain::~murugesandinsDomain

Open in new window

murugesandinsWe like KT across the universe.  Shell_script Automation /bin/bash /bin/bash.exe /bin/ksh /bin/mksh.exe AIX C C++ CYGWIN_NT HP-UX Linux MINGW32 MINGW64 SunOS Windows_NT
Porting at all operating systems:
#elif defined Linux
              // Related code
#elif defined AIX
              // Related code
#elif defined SunOS
              // Related code
#elif defined HP_UX_10_00
              // Related code
#elif defined HP_UX_11_00
              // Related code
#elif defined HP_UX_11_11
              // Related code
#elif defined HP_UX_11_22
              // Related code
#elif defined DOS_MODE
              // Related code
#else
        // Use related enhancement and modifications based on Operating systems, release, version, model...
        #error NOT SUPPORTED
#endif
Top Expert 2016
the usual way is to pass a pointer to a struct that contains the string.

struct ThreadData
{
      std::string strDomain;
      // more data
};


static ThreadData data = { "MyDomain" };
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, &Thread_SaveDomainName, &data, 0, &threadID);
[/code

in the thread start function (which best is a static member function of your application class) you do 

[code]
void MyApp::Thread_SaveDomainName(void * pArg)
{
      ThreadData * pData = ( ThreadData * )pArg;
      std::string mydomain = pData->strDomain;
      ....
}

Open in new window


note, i used a static ThreadData object because a local object would be destroyed when leaving the context where _beginthreadex was called. a member variable of your application class would be also fine because you should terminate the thread before the application object was destroyed. of course you also could create the struct object by new on the heap but in order to avoid memory leaks, the pointer needs to be returned and deleted when the thread was terminated. you could delete the pointer in the thread function before return but that normally was seen as bad programming if pointer creation and pointer deletion was done in different contexts.

note, i would recommend against using TCHAR for the string member. the idea of TCHAR was to be able to switch between 16-bit wide characters (as used by windows) and 8-bit ansi for the whole project by setting the character set in the project properties either to 'UNICODE' or to 'MultiByte'). i never saw a non-trivial project where that switch ever was performed as it requires to using the switchable types and macros for all components of your project. i used std::string in the sample code which has char as template type. if you want to use UTF16 character set (what is called UNICODE by MS) then std::wstring would be a suitable string class.

Sara
murugesandinsWe like KT across the universe.  Shell_script Automation /bin/bash /bin/bash.exe /bin/ksh /bin/mksh.exe AIX C C++ CYGWIN_NT HP-UX Linux MINGW32 MINGW64 SunOS Windows_NT
@Oval Piston
Always handle pointers.
Example:
if ( NULL == AnyPtr )
{
        cerr << "related error\n";
        exit(-1);
}

Open in new window

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial