12 Replies - 3773 Views - Last Post: 11 January 2011 - 02:51 PM Rate Topic: -----

#1 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

C++ Multithreading Problem

Posted 11 January 2011 - 09:01 AM

I'm trying to convert a program into a MultiThreading program to make it run faster but I'm having trouble getting started.

The program will use an amount of threads equal to the amount of cores in a system(I know how to find this), and the threads need to be able to access the variables that I had before trying to convert it to use multithreading.

I am using C++, windows.h, and microsoft VC++ 2008 express.

Here is the part of the program I'm having problems with:
in Object.h I have:
#ifndef OBJECT_H
#define OBJECT_H
#include <vector>
#include <windows.h>
#include "math.h"
#include "DarkGDK.h"
using namespace std;
class Object
{
private:
	DWORD WINAPI mainThread(LPVOID lpParam);
	int numCores; //number of available cores on CPUs.
	void bufferObjects();
};
#endif



and in Object.cpp i have:
void Object::bufferObjects()
{
HANDLE *Array_Of_Thread_Handles = NULL;
	Array_Of_Thread_Handles = new HANDLE[numCores];
	for(int i = 0; i < numCores; i++) 
	{
		Array_Of_Thread_Handles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)mainThread, (LPVOID)i, 0, NULL);
		//SetThreadAffinityMask(Array_Of_Thread_Handles[i], m_mask);
	}
	WaitForMultipleObjects(numCores, Array_Of_Thread_Handles, TRUE, INFINITE);
	
	for(int i = 0; i<numCores; i++)
	{
		CloseHandle(Array_Of_Thread_Handles[i]);
	}
}



I am getting the error:
error C2440: 'type cast' : cannot convert from 'overloaded-function' to 'LPTHREAD_START_ROUTINE'
None of the functions with this name in scope match the target type

I have gotten rid of this error by making the thread function static, but then the thread cannot access the variables of the Object.h class because it wants them to be "static" too, and I am not very familiar with static functions.

Is This A Good Question/Topic? 0
  • +

Replies To: C++ Multithreading Problem

#2 horace  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 290
  • View blog
  • Posts: 1,900
  • Joined: 25-October 06

Re: C++ Multithreading Problem

Posted 11 January 2011 - 09:14 AM

mainThread() is a none static member of Object - you have to call CreateThread() with a 'normal' C/C++ function or a static member function. Have a look at
http://social.msdn.m...eb-e76fb8e0f6f8

This post has been edited by horace: 11 January 2011 - 09:15 AM

Was This Post Helpful? 2
  • +
  • -

#3 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 09:19 AM

Oops I left out my mainThread function on accident, I didn't want to post my whole code because it'd about 500 lines long.
heres the function(non-static) while giving that error(and it's in the .h file too of course):
DWORD WINAPI Object::mainThread(LPVOID lpParam) 
{
	
	return 0; 
}



I'll have a look at that website now to see if I can find anything useful.
thanks for the reply.
Was This Post Helpful? 0
  • +
  • -

#4 horace  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 290
  • View blog
  • Posts: 1,900
  • Joined: 25-October 06

Re: C++ Multithreading Problem

Posted 11 January 2011 - 11:27 AM

try making it static, e.g.
	static DWORD WINAPI mainThread(LPVOID lpParam);


Was This Post Helpful? 0
  • +
  • -

#5 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 11:46 AM

I made it static now, but I have a couple other problems with it.

I have tried simplifying it by transferring the bad code to a new project.
This is what I have now:

Object.cpp:
//Author: Adam Morin
#include "Object.h"
#include <iostream>
#include "stdio.h"
using namespace std;
Object::Object(void)
{
	bufferObjects();
	numCores = countCores();
	testVariable = 0;
}

Object::~Object(void){}

int Object::countCores()
{
	SYSTEM_INFO sysinfo;
	GetSystemInfo( &sysinfo );
	int numCPU; //number of cores
	numCPU = sysinfo.dwNumberOfProcessors;
	return numCPU;
}

DWORD WINAPI Object::mainThread(LPVOID lpParam) 
{
	//testVariable++;
	return 0;
}

void Object::bufferObjects()  //re-structured this function sloppy in order to increase processing speed. //
{
	HANDLE *Array_Of_Thread_Handles = NULL;
	Array_Of_Thread_Handles = new HANDLE[numCores];
	for(int i = 0; i < numCores; i++) 
	{
		Array_Of_Thread_Handles[i] = CreateThread(NULL, 0, mainThread, this, 0, NULL);
	}
	WaitForMultipleObjects(numCores, Array_Of_Thread_Handles, TRUE, INFINITE);
	
	for(int i = 0; i<numCores; i++)
	{
		CloseHandle(Array_Of_Thread_Handles[i]);
	}
}




Object.h:
//Author: Adam Morin
#ifndef OBJECT_H
#define OBJECT_H
#include <windows.h>
class Object
{
private:
	static DWORD WINAPI mainThread(LPVOID lpParam);
	int numCores; //number of available cores on CPUs.
	int countCores(); //same
	int testVariable;
public:
	Object(void);
	~Object(void);
	void bufferObjects();
};
#endif



Main.cpp:
#include "Object.h"
int main()
{
	Object obj;
	obj.bufferObjects();
	return 0;
}



With this code I get a runtime error from windows saying: "Invalid Allocation size: 4294967295 bytes" with the simple "return 0;" thread.

I've been googling for an answer for about 8 hours now but can't find one, even though the tutorials look simple enough. I think the "this" in my CreateThread() function is supposed to transfer the variables in my Object class object to the created thread, but when I try to use testVariable++; in the thread it still says i cannot access non-static variables.

I haven't found any code snippits that use header files for this, so I am thinking that using header files in the way I am might be what is leading to my errors.
Was This Post Helpful? 0
  • +
  • -

#6 Salem_c  Icon User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 1628
  • View blog
  • Posts: 3,087
  • Joined: 30-May 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 12:51 PM

Read the link horace posted. You need a static function with a void* pointer with which to create a 'fake this' pointer to invoke an actual member function.
Was This Post Helpful? 0
  • +
  • -

#7 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 12:57 PM

It gives the exact same errors when I change LPVOID to void*, I have been seeing both so I figure they are interchangable, but I could easily be wrong here. And in my last post with the new project code the mainThread() is declared static in the header file.

Anyways I have to leave for about an hour and a half, I will work on it some more when I get home.
Was This Post Helpful? 0
  • +
  • -

#8 Salem_c  Icon User is offline

  • void main'ers are DOOMED
  • member icon

Reputation: 1628
  • View blog
  • Posts: 3,087
  • Joined: 30-May 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 12:59 PM

Post some latest code in the meantime please.
Was This Post Helpful? 0
  • +
  • -

#9 horace  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 290
  • View blog
  • Posts: 1,900
  • Joined: 25-October 06

Re: C++ Multithreading Problem

Posted 11 January 2011 - 01:46 PM

in the Object constructor
Object::Object(void)
{
	bufferObjects();
	numCores = countCores();


you call bufferObjects() which uses numCores before it is assigned a value (by countCores()), i.e.
void Object::bufferObjects()  //re-structured this function sloppy in order to increase processing speed. //
{
	HANDLE *Array_Of_Thread_Handles = NULL;
	Array_Of_Thread_Handles = new HANDLE[numCores];
	cout << " in byfferObjects " << numCores << endl;
	numCores=2;
	for(int i = 0; i < numCores; i++)    // <<<< used here!!
	{
		Array_Of_Thread_Handles[i] = CreateThread(NULL, 0, mainThread, this, 0, NULL);
	}


therefore the value of numCores is undefined (whatever is in the memory allocated to it) and you end up in the loop in bufferObjects() creating lots of threads until the program crashes. try
Object::Object(void)
{
	numCores = countCores();  // << call this first!!
	bufferObjects();


it helps if you put a few print statements (cout << in C++) a critical points in the code - you can then see where the program is getting too and you can print out values of variables etc. Using a debugger is an alternative approach.

This post has been edited by horace: 11 January 2011 - 02:05 PM

Was This Post Helpful? 1
  • +
  • -

#10 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 02:22 PM

Oh nice catch, that was a dumb mistake by me. That fixed the runtime error expecting a huge byte value. But now I still have the problem of not being able to change the Object class's variables within the mainThread() function(because it is static).

For example if I have:
DWORD WINAPI Object::mainThread(LPVOID lpParam) 
{
	testVariable++;
	return 0;
}



I get the error:
------ Build started: Project: Thread, Configuration: Debug Win32 ------
Compiling...
Object.cpp
c:\users\pc\desktop\projects\thread\thread\object.cpp(26) : error C2597: illegal reference to non-static member 'Object::testVariable'
c:\users\pc\desktop\projects\thread\thread\object.cpp(26) : error C3867: 'Object::testVariable': function call missing argument list; use '&Object::testVariable' to create a pointer to member
c:\users\pc\desktop\projects\thread\thread\object.cpp(26) : error C2105: '++' needs l-value
Build log was saved at "file://c:\Users\PC\Desktop\Projects\Thread\Thread\Debug\BuildLog.htm"
Thread - 3 error(s), 0 warning(s)
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========



I thought I read that putting the keyword "this" inside the CreateThread() function allows me to use the variables in the mainThread(), but it is not working with my code. I googled for a while and couldn't find any tutorials that actually had code like that inside the thread.

In the ends I am planning on breaking a large for loop nested inside another large for loop into multiple threads(4 for my processor), because currently the program buffers slow with 1000+ objects but only uses 25% cpu usage. And it is a good learning experience.

And thanks again for all the replies.
Was This Post Helpful? 0
  • +
  • -

#11 horace  Icon User is offline

  • D.I.C Lover
  • member icon

Reputation: 290
  • View blog
  • Posts: 1,900
  • Joined: 25-October 06

Re: C++ Multithreading Problem

Posted 11 January 2011 - 02:33 PM

you pass this (pointer to the instance of Object) as parameter 4 to CreateThread which is passed to the thread so you should be able to
DWORD WINAPI Object::mainThread(LPVOID lpParam)
{
	((Object*)lpParam)->testVariable++;


This post has been edited by horace: 11 January 2011 - 02:34 PM

Was This Post Helpful? 1
  • +
  • -

#12 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 02:38 PM

Ohh...Thanks that works perfectly, I should be able to figure the rest out now that I can finally change variables.
Was This Post Helpful? 0
  • +
  • -

#13 Trep619  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 17
  • Joined: 23-December 10

Re: C++ Multithreading Problem

Posted 11 January 2011 - 02:51 PM

Here is my current solved problem in case anyone searches for the same thing in the future.

I think when I tried this a few hours ago I had: return (Object*)lpParam->run(); instead of: return ((Object*)lpParam)->run();
So it gave me an error for that.
Another dumb mistake, but now it works.

main.cpp:
#include "Object.h"
int main()
{
	Object obj;
	return 0;
}



Object.cpp:
//Author: Adam Morin
#include "Object.h"
#include <iostream>
#include "stdio.h"
using namespace std;
Object::Object(void)
{
	testVariable = 0;
	numCores = countCores();
	bufferObjects();
	cout << testVariable;
}

Object::~Object(void){}

int Object::countCores()
{
	SYSTEM_INFO sysinfo;
	GetSystemInfo( &sysinfo );
	int numCPU; //number of cores
	numCPU = sysinfo.dwNumberOfProcessors;
	return numCPU;
}

DWORD WINAPI Object::mainThread(LPVOID lpParam) 
{
	return ((Object*)lpParam)->run();
}
DWORD Object::run()
{
	testVariable++;
	return 0;
}

void Object::bufferObjects()  //re-structured this function sloppy in order to increase processing speed. //
{
	HANDLE *Array_Of_Thread_Handles = NULL;
	Array_Of_Thread_Handles = new HANDLE[numCores];
	for(int i = 0; i < numCores; i++) 
	{
		Array_Of_Thread_Handles[i] = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)mainThread, this, 0, NULL);
	}
	WaitForMultipleObjects(numCores, Array_Of_Thread_Handles, TRUE, INFINITE);
	
	for(int i = 0; i<numCores; i++)
	{
		CloseHandle(Array_Of_Thread_Handles[i]);
	}
}



Object.h:
//Author: Adam Morin
#ifndef OBJECT_H
#define OBJECT_H
#include <windows.h>
class Object
{
private:
	static DWORD WINAPI mainThread(void* lpParam);
	DWORD run();
	int numCores; //number of available cores on CPUs.
	int countCores(); //same
	int testVariable;
public:
	Object(void);
	~Object(void);
	void bufferObjects();
};
#endif


Was This Post Helpful? 0
  • +
  • -

Page 1 of 1