I'm not sure what the correct syntax is for this because it involves the winapi which i'm not familiar with. For example, i didnt know it won't let me xhangethe predefined thread function parameters from processClient(LPVOID) to processClient(LPVOID&).
I need to pass the "params" object by reference(just so theres no problems for now, even though im not going to change values in it) to the thread function "processClient()".
... struct(the object) declaration
struct ClientParams{
ClientParams::ClientParams():sock(INVALID_SOCKET), i(NULL){};
public:
SOCKET sock;
int i;
};
... in processClient(LPVOID lpParam){
SOCKET ClientSocket=(SOCKET)*lpParam->sock; ?? doesnt work
int i=*lpParam->i; ?? doesn't work
}
... in main{
ClientParams *params = new ClientParams();
params->i=some_value;
params->sock=ClientSocket;
CreateThread(
NULL, // don't inherit handle
0, // use default size for the executable
processClient,
(LPVOID)params, // thread data
0, // run right away
&i );
}
SOCKET ClientSocket=(SOCKET)*lpParam->sock; ?? doesnt work
lpParam has the same value it did when you passed it, in main, where it was 'params', of type 'ClientParams*', so you don't have any business dereferencing it with '*'. The rest of it is just a precedence problem. It should be
SOCKET ClientSocket=((ClientParams*)lpParam)->sock;
Access structure members must through the structure.
SOCKET ClientSocket=((ClientParams*)lpParam)->sock;
Related
I am trying to run a C++ thread but also pass in the instance to the class itself. I cannot seem to figure it out.
I have a struct for parameters to the thread:
struct CLASS_PARAMS {
SomeClass* ptr;
};
I then call my setup method:
void SomeClass::setup() {
CLASS_PARAMS params;
params.ptr = this;
CreateThread(NULL, 0, SetupThread, ¶ms, 0, NULL);
}
and right above SomeClass::setup(), I define SetupThread:
DWORD WINAPI SetupThread(LPVOID lpParam) {
CLASS_PARAMS* params = (CLASS_PARAMS *) lpParam;
SomeClass* inst = params->ptr;
....
....
}
However, I get read-access violations on using inst. I have other methods in SomeClass that I need to access via the thread:
inst->getSomeValue();
...
inst->setSomeValue(someValue);
...
but it will not allow me. Any suggestions on what I'm doing wrong?
You allocate CLASS_PARAMS on stack, so it is destroyed before used.
Allocate it dynamically, pass pointer and free it in the thread.
Alternatively, if you need to pass only this, pass it without wrapping structure, just cast to LPVOID and back (but be sure to use the same class pointer type to avoid pointer adjustment bugs)
I've been re-architecting some fairly procedural C++ into something more classy. The original code runs just fine and part of it spins up a new thread to do some file cleaning. The function that does this cleaning is the entry point for the new thread. See code below. NB: This code won't execute, but it shows the principle that worked.
#include <stdlib.h>
// Structure for passing application data to a new thread.
typedef struct threadData {
networkShare* netArchive;
rig* rigInfo;
rigDatabase* dbConn;
networkConn* netConn;
char* logBuffer;
} THREADDATA;
// Global handle to a mutex object
// Used to control access to the inter thread log buffer
HANDLE ghMutex;
DWORD WINAPI cleanLocalArchive(LPVOID lpParam) {
THREADDATA* p_threadData = (THREADDATA*)lpParam;
// ... Do stuff ...
return <<something>>;
}
int main(int argc, char** argv) {
// Variables for local archive thread
HANDLE h_CleanerThread = 0;
THREADDATA* p_threadData = NULL;
DWORD dwThreadId;
// Create a mutex with no initial owner
ghMutex = CreateMutex(
NULL, // default security attributes
FALSE, // initially not owned
NULL); // unnamed mutex
if (ghMutex == NULL) {
printf("CreateMutex error: %d\n", GetLastError());
return 1;
}
// Declare the data structure for passing app setting to a new Thread and populate it.
p_threadData = DBG_NEW THREADDATA;
p_threadData->netArchive = &rigArchive;
p_threadData->rigInfo = &thisRig;
p_threadData->logBuffer = (char*)malloc(BUF_SIZE);
p_threadData->dbConn = &archiveDB;
p_threadData->netConn = &netConnection;
// Initialise p_threadData->logBuffer in case we never put anything else in there.
sprintf_s(p_threadData->logBuffer, BUF_SIZE, "");
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
cleanLocalArchive, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
// ... Do other stuff ...
return 0;
}
I've now refactored the code into classes and the function "cleanLocalArchive" is a member function of the application class AircatFeeder. When I call this member function in the in CreateThread() I get various errors depending on what I do to the code:
As-is: call line = "cleanLocalArchive,"
error C3867: 'AirCatFeeder::cleanLocalArchive': non-standard syntax; use '&' to create a pointer to member
So I add in an ampersand: call line = "&cleanLocalArchive,"
error C2276: '&': illegal operation on bound member function expression
error C2660: 'CreateThread': function does not take 5 arguments
After some head scratching and Google-Foo I found this link which I hoped would solve the issue. It certainly shed some light on the why. I created a wrapper function outside the class and tried calling that. The function and its call was as follows:
Function call:
// Start a new thread
h_CleanerThread = CreateThread(
NULL, // default security attributes
0, // use default stack size
trampoline, // thread function name
p_threadData, // argument to thread function
0, // use default creation flags
&dwThreadId); // returns the thread identifier
Wrapper Function:
DWORD trampoline(LPVOID data) {
AirCatFeeder* scheduler = static_cast<AirCatFeeder*>(data);
return scheduler->cleanLocalArchive(data);
}
However, I still ended up with the same issues/error messages. Whether I call the member function, or the wrapper function, IntelliSense still reports a similar error message:
argument of type "DWORD(*)(LPVOID lpParam)" is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
Hopefully it is now clear what I'm trying to achieve. Can someone please educate me on what I'm doing wrong? Thanks.
Answer courtesy of Hans Passant. See Comments on question:
The trampoline is missing WINAPI in its definition.
I understand that pthread_t should be treated as an opaque value, however I don't know how to initialize it when used as a class member, and how can I check for its validity.
Consider this code sample:
class MyClass
{
public:
pthread_t thread;
MyClass()
: thread(0) // Wrong because pthread_t should be an opaque value,
// so how should I initialize it?
{}
~MyClass()
{
if( thread ) // Wrong, but how can I verify if it is valid?
pthread_join(thread, NULL);
}
};
I also understand that if pthread_create() fails, the pthread_t value may be inconsistent. So I should only rely on the return value from pthread_create(). But this means that I should keep this returned value along with pthread_t and use it to check thread validity? And in this case, how should I initialize in the class constructor this value?
class MyClass
{
public:
pthread_t thread;
int threadValid;
MyClass()
: thread(0), // Wrong because pthread_t should be an opaque value,
// so how should I initialize it?
, threadValid(1) // pthread_create return zero in case of success,
// so I can initialize this to any nonzero value?
{}
~MyClass()
{
if( threadValid == 0 ) // Nonzero means thread invalid.
// Is this the correct approach?
{
pthread_join(thread, NULL);
threadValid = 1;
}
}
};
I have a Windows API background, and there a thread has its HANDLE value, which may be initialized safely to NULL, and can be checked against NULL, and if CreateThread() fails, it just consistently returns NULL. There's no way, with pthreads, to keep this neat and simple approach?
pthread_t is a C type, so it must have a trivial default constructor; so you can just value-initialize it:
: thread(), // ...
Your usage of threadValid seems somewhat confused. It would be better to make it a bool initially set to false and then only set it true once pthread_create succeeds.
But this means that I should keep this returned value along with pthread_t and use it to check thread validity?
Yes, or more simply keep a boolean, like already mentioned.
And in this case, how should I initialize in the class constructor this value?
Don't initialize it, it's not mandatory to initialize members in C++.
Unfortunately you can only use a guard variable to know if its value make sense or not.
So for instance you can't use 0 because it would be a valid pthread_t on some systems (DG/UX for instance).
You should have to use something else to know if the value can be used or not, and you should value-initialize it.
If you can compromise on portability (non production code for instance), consider that on Linux and Android pthread_t should be like an int type, and on Darwin it should be an handle, so it would work if you initialize it to 0.
pthread_t thread_handle;
pthread_attr_t thread_attributes;
pthread_attr_init(&thread_attributes);
pthread_attr_setdetachstate(&thread_attributes, PTHREAD_CREATE_JOINABLE);
threadValid = (::pthread_create(&thread_handle, &thread_attributes, function, data) == 0);
and when shutting it down:
if (threadValid) {
::pthread_join(thread_handle, 0);
}
Don't start your thread in the constructor though.
i have a question about a behaviour i don't quite understand:
i have two variations of c++ code:
CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) clientThread, ( LPVOID ) connectionSocket, 0, NULL );
thread:
Client a;
a.clientsocket = connectionSocket;
a.testText()
a.sendSocket();
works just fine (sendSocket sends some test data to the socket).
However if i do
Client a;
a.clientsocket = connectionSocket;
CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) clientThread, ( LPVOID ) &a, 0, NULL );
and use
thread:
a.testText();
a.sendSocket();
only testText() works.
I am a bit confused why that is. I am a hobbyist on C++ though :-)
edit:
added the Client class:
class Client
{
public:
SOCKET clientsocket;
Client()
{
}
~Client(){}
void displayMessage()
{
std::cout << "test message client class" << std::endl;
}
int sendSocket()
{
char *sendbuf = "CLIENT TEST";
send(clientsocket, sendbuf, (int)strlen(sendbuf),0);
closesocket(clientsocket);
return 0;
}
};
I'm guessing that in your main thread the CreateThread succeeds and then then your Client variable, a, goes out of scope and therefore destructed.
Anon is might be on the right track that something goes out of scope, but I think that it's the connectionSocket. However, you would have to provide more details on what you mean when you say that a.sendSocket() doesn't work. Does the application crash? Do you catch an exception? Does the application continue to work, but the sendSocket() call didn't result in actually sending something? What's the actual problem?
In the first case you pass a connectionSocket and in the second case a pointer to a which is of type Client. Maybe you meant:
CreateThread( NULL, 0, ( LPTHREAD_START_ROUTINE ) clientThread, ( LPVOID ) a.clientsocket, 0, NULL );
It looks to me like it's the a object that goes out of scope. The SOCKET is just an int HANDLE value and gets stored in a member of a. 'a' goes out of scope in the thread-creating function as the creating thread runs on, (or is corrupted when the next accept() returns).
Try:
Client a= new Client();
Think 15 times before allocating objects on the stack in multithreaded code, then decide to dynamically allocate.
PS - #Anon got there first - I didn't notice.
from your client class
SOCKET clientsocket;
whenever you pass that on into a thread then the SOCKET is going to have the copy constructor called on it. This copy constructor may be undefined or it may be trying to open up a new connection on the same port and causing it to fail.
change it to this:
SOCKET* clientsocket;
then have it so that whenever you want to do...
a.clientsocket = connectionSocket;
the variable "connectionSocket" is a pointer and then boom goes the dynamite. When it is not declared as a variable the copy constructor is called and you get a whole new socket than the one you were using before. i think that should help?
I'm working with a C++ class-library that provides a Thread base-class where the user has to
implement a run() method.
Is there a recommended way on how to pass parameters to that run() method? Right now
I prefer to pass them via the constructor (as pointers).
I'm not sure about C++, but that's how you would do it in Java. You'd have a class that extends Thread (or implements Runnable) and a constructor with the parameters you'd like to pass. Then, when you create the new thread, you have to pass in the arguments, and then start the thread, something like this:
Thread t = new MyThread(args...);
t.start();
Must be the same in your case.
An alternative is to extend this Thread class to accept a functor as only constructor parameter, so that you can bind any call inside it.
Then the class using threads wont need to inherit from Thread, but only have one (or more) Thread member. The functor calls any start point you want ( some method of the class with any parameters )
Here is a typical pattern:
1) Define a data structure that encapsulates all the data your thread needs
2) In the main thread, instantiate a copy of the data structure on the heap using operator new.
3) Fill in the data structure, cast the pointer to void*, pass the void* to the thread procedure by whatever means you are provided by your thread library.
4) When the worker thread gets the void*, it reinterpret_cast's it to the data structure, and then takes ownership of the object. Meaning when the thread is done with the data, the thread deallocates it, as opposed to the main thread deallocating it.
Here is example code you can compile & test in Windows.
#include "stdafx.h"
#include <windows.h>
#include <process.h>
struct ThreadData
{
HANDLE isRunning_;
};
DWORD WINAPI threadProc(void* v)
{
ThreadData* data = reinterpret_cast<ThreadData*>(v);
if( !data )
return 0;
// tell the main thread that we are up & running
SetEvent(data->isRunning_);
// do your work here...
return 1;
}
int main()
{
// must use heap-based allocation here so that we can transfer ownership
// of this ThreadData object to the worker thread. In other words,
// the threadProc() function will own & deallocate this resource when it's
// done with it.
ThreadData * data = new ThreadData;
data->isRunning_ = CreateEvent(0, 1, 0, 0);
// kick off the new thread, passing the thread data
DWORD id = 0;
HANDLE thread = CreateThread(0, 0, threadProc, reinterpret_cast<void*>(data), 0, &id);
// wait for the worker thread to get up & running
//
// in real code, you need to check the return value from WFSO and handle it acordingly.
// Here I assume the retval is WAIT_OBJECT_0, indicating that the data->isRunning_ event
// has become signaled
WaitForSingleObject(data->isRunning_,INFINITE);
// we're done, wait for the thread to die
WaitForSingleObject(thread, INFINITE);
CloseHandle(thread);
return 0;
}
A common problem with thread startup is that the arguments passed exist on only the stack in the calling function. Thread startup is often deferred, such that the calling function returns and it is only some time later the thread actually starts - by which time the arguments are no longer in existence.
One solution to this is to create an event and then start the thread, passing the event as one of the arguments. The starting function then waits on the event, which is signalled by the thread when it has completed startup.
You can pass the parameters as members of the thread class. The thread which creates the thread can presumably call other methods and/or call member functions before the thread starts. Therefore it can populate whatever members are necessary for it to work. Then when the run method is called, it will have the necessary info to start up.
I am assuming that you will use a separate object for each thread.
You would normally put all the threads you create into an array, vector etc.
It is ok to pass them via constructor. Just be sure that pointers will live longer than the thread.
Well, I'd prefer to put the parameters in the Start() method, so you can have a protected constructor, and doesn't have to cascade the parameters through derived class constructor.
I'd prolly let my decleration look something like this:
class Thread
{
public:
virtual void Start(int parameterCount, void *pars);
protected:
Thread();
virtual void run(int parameterCount, void *pars) = 0;
}
Just make sure that your parameters are somehow contracted, e.g. #1 will be int, #2 will be a double etc. etc. :)