Array of sockets as a parameters in CreateThread - c++

I have an exmaple wich describes how to send 1 socket as a parameter to the new thread.
SOCKET clientSocket;
...
CreateThread(NULL, NULL, SexToClient, &clientSocket, NULL, &thID);
...}
DWORD WINAPI SexToClient(LPVOID client) {
SOCKET clientSocket;
clientSocket = ((SOCKET*)client)[0];
... }
But now I want to make another thread with array of sockets. How can I send them and use in thread?
And what does mean [0] at the end of this line? In this particular example we're send only one socket and it's working fine.
((SOCKET*)client)[0];

You can pass any arguments to the CreateThread method by wrapping all the arguments into simple structure. For example:
struct ThreadParams {
std::vector<SOCKET *> sockets;
std::string clientName;
// more params
};
All you need to do is to initialize this structure before calling CreateThread function, and then pass a pointer:
ThreadParams * params = new ThreadParams();
params.setParameters();
CreateThread(, , SexToClient, params, );
DWORD WINAPI SexToClient(LPVOID arg) {
ThreadParams * params = reinterpret_cast<ThreadParams *>(arg);
// delete after usage;
delete params;
}

You can call CreateThread as many times as you want with different data as the fourth parameters and the new thread will get that data.
((SOCKET*)client)[0]
just grabs the first element. It casts it to a SOCKET pointer then grabs the first element. This is another way to write
*(SOCKET *)client;

Related

How to pass in the 'this' pointer to a C++ WinAPI thread?

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, &params, 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)

C++ - Passing an object to CreateThread() by ref

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;

Create thread within DLL

I'm working on a .NET profiler which I'm writing in c++ (a dll that uses ATL). I want to create a thread that writes into a file every 30 seconds. I want the thread function to be a method of one of my classes
DWORD WINAPI CProfiler::MyThreadFunction( void* pContext )
{
//Instructions that manipulate attributes from my class;
}
when I try to start the thread
HANDLE l_handle = CreateThread( NULL, 0, MyThreadFunction, NULL, 0L, NULL );
I got this error :
argument of type "DWORD (__stdcall CProfiler::*)(void *pContext)"
is incompatible with parameter of type "LPTHREAD_START_ROUTINE"
How to properly create a thread within a DLL?
Any help would be apreciated.
You cannot pass a pointer to a member function as if it were a regular function pointer. You need to declare your member function as static. If you need to call the member function on an object you can use a proxy function.
struct Foo
{
virtual int Function();
static DWORD WINAPI MyThreadFunction( void* pContext )
{
Foo *foo = static_cast<Foo*>(pContext);
return foo->Function();
}
};
Foo *foo = new Foo();
// call Foo::MyThreadFunction to start the thread
// Pass `foo` as the startup parameter of the thread function
CreateThread( NULL, 0, Foo::MyThreadFunction, foo, 0L, NULL );

Handling of LPWSAOVERLAPPED after WSASend

I am currently writing a winsock server-side socket in managed C++. After creating the LPWSAOVERLAPPED object and passing it to the WSASend function, I do not see where to delete it when the operation completes nonblocking (WSASend returns SOCKET_ERROR and WSAGetLastError() returns WSA_IO_PENDING). My current solution was to create a System::Threading::WaitHandle, get the unsafe pointer to the wait handle and pass that onto hEvent under the LPWSAOVERLAPPED object. However, this is causing unnessecary object creation since I do not really care about when the send operation is completed. On the other hand, I need a LPWSAOVERLAPPED object in order to make the operation complete non-blocking. Does anyone have any better solution to solve this? Here is my current code:
void Connectivity::ConnectionInformation::SendData(unsigned char data[], const int length)
{
if (isClosed || sendError)
return;
Monitor::Enter(this->sendSyncRoot);
try
{
LPWSAOVERLAPPED overlapped = OverlappedObjectPool::GetOverlapped();
WaitHandle ^ handle = gcnew ManualResetEvent(false);
IntPtr handlePointer = handle->SafeWaitHandle->DangerousGetHandle();
sendInfo->buf = (char*)data;
sendInfo->len = length;
overlapped->Internal = 0;
overlapped->InternalHigh = 0;
overlapped->Offset = 0;
overlapped->OffsetHigh = 0;
overlapped->Pointer = 0;
overlapped->hEvent = (void*)handlePointer; //Set pointer
if (WSASend(connection, sendInfo, 1, NULL, 0, overlapped, NULL) == SOCKET_ERROR)
{
if (WSAGetLastError() == WSA_IO_PENDING)
{
ThreadPool::UnsafeRegisterWaitForSingleObject(handle, sentCallback, (IntPtr)((void*)overlapped), -1, true);
}
else
{
this->sendError = true;
//The send error bool makes sure that the close function doesn't get called
//during packet processing which could lead to a lot of null reffernce exceptions.
OverlappedObjectPool::GiveObject(overlapped);
}
}
else
{
handle->Close();
sentData((IntPtr)((void*)overlapped), false);
}
}
finally
{
Monitor::Exit(this->sendSyncRoot);
}
}
For async I/O, completion is notified either by the calling of a completion routine or by the queueing of an IOCP completion message to an IOCP completion queue. In both cases, it should be noted that the OVL struct should have the lifetime of at least the entire async operation, but can be longer if convenient:)
In the case of a completion routine, the unused hEvent parameter in the OVL can be used to transfer a pointer to an 'IOrequest' class instance that contains the data buffer/s, WSABUF array and the OVL struct as members, (and surely a pointer to the socket object for which the I/O has been issued). The OVL pointer is supplied as a parameter to the completion routine and so the hEvent can be retrieved and cast to the class type, so retrieving the complete class instance - OVL, data buffer etc. When the data has been processed, (or immediately in the completion routine the case of WSASend), and this IOrequest is eventually destroyed, (or repooled), the OVL will go with it. This sounds a bit incestuous, but works fine and does not need any nasty macro or other tricks.
A similar approach can be used with full IOCP or, alternatively, the OVL passed as the lpCompletionKey 'spare' parameter.
Oh - and you do care if the operation is completed - you need to at least check for errors.

C++ passing an object to a thread

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?