Thread issues

Hi, first thanks for the reply of my mail about printing. Now I have
another problem.

Recently, my project’s event handler is a little lagging, even in
fullscreen mode. If I clicked the mouse button sequentially, sometimes it
wouldn’t be catched by the handler. So I decided to make the event handler
and image drawing sequences into different threads. I’m confused about how
should I implement the threading. I’ve looked at several tutorials about
SDL_thread, but they didn’t work. You see, in my projects all was handled
by one universal singleton object. That object will handle everything from
other objects’ creations, accessing the objects, freeing the objects,
drawing, event handler, etc. Thus the main function will only consist of:

void main()
{
CMainApp *mMainApp; //The universal object
mMainApp = new CMainApp;
mMainApp->start();
}

So, I implemented the thread function and creation in the object:

The declarations:

class CMainApp
{
Public:
CMainApp();
~CMainApp();
int drawThreadFunc(void *data);
void start();
void draw();
//Variables
Private:
bool done;
SDL_Thread *mThread;
//Other functions&variables

};

The implementations:

CMainApp::CMainApp()
{
done=false;

}

CMainApp::~CMainApp()
{

}

int CMainApp::drawThreadFunc(void *data)
{
while(!done)
{
draw(); //Drawing the surface
}
}

void CMainApp::start()
{
mThread = SDL_CreateThread(drawThreadFunc, NULL );
while(!done)
{
eventHandling(); //Catch and handle events
}
SDL_KillThread(mThread);
}

But when I compiled the code, it show this error message (FYI I used
Kdevelop):
/home/benang/mattinggame/src/MainApp.cpp:129: error: argument of type ?int
(CMainApp::)(void*)? does not match ?int ()(void)?

Why does this happen? Is my threading code above correct?

void main()
{
CMainApp *mMainApp; //The universal object
mMainApp = new CMainApp;
mMainApp->start();
}

So, I implemented the thread function and creation in the object:

The declarations:

class CMainApp
{
Public:
CMainApp();
~CMainApp();
int drawThreadFunc(void *data);
void start();
void draw();
//Variables
Private:
bool done;
SDL_Thread *mThread;
//Other functions&variables

};

The implementations:

CMainApp::CMainApp()
{
done=false;

}

CMainApp::~CMainApp()
{

}

int CMainApp::drawThreadFunc(void *data)
{
while(!done)
{
draw(); //Drawing the surface
}
}

void CMainApp::start()
{
mThread = SDL_CreateThread(drawThreadFunc, NULL );
while(!done)
{
eventHandling(); //Catch and handle events
}
SDL_KillThread(mThread);
}

But when I compiled the code, it show this error message (FYI I used
Kdevelop):
/home/benang/mattinggame/src/MainApp.cpp:129: error: argument of type ?int
(CMainApp::)(void*)? does not match ?int ()(void)?

Why does this happen? Is my threading code above correct?

The threading is ok, although you may want to use SDL_WaitThread instead
of SDL_KillThread so the drawing thread has a chance to finish and clean
up.

The error is because the function pointer you gave to create thread
doesn’t match the prototype the function expects. What you’ve probably
overlooked is that since drawThreadFunc is a class member function, it
implicitly takes a pointer to its object (this) as a parameter. As a
reult, it isn’t the right prototype. You could try type casting the
function and passing this instead of NULL to create thread, but I wouldn’t
be surprised if that won’t work.

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function isn’t
exposed beyond the class, and you get a nice clean objecty interface for
threads.On Mon, 14 Aug 2006 benang at cs.its.ac.id wrote:


Jeff Jackowski
http://ro.com/~jeffj/

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function isn’t
exposed beyond the class, and you get a nice clean objecty interface for
threads.


Jeff Jackowski
http://ro.com/~jeffj/

Sorry, I’m lost. Can you be more spesific?

Make thread function static.

class CMainApp
{

ETC …

public:

static int drawThreadFunc(void *data){
CMainApp pMyApp=dynamic_cast<CMainApp>(data);
pMyApp->DoThings();
etc …
etc …
}

ETC …

};

void CMainApp::start()
{
mThread = SDL_CreateThread(drawThreadFunc, (void*)this);
while(!done)
blah
blah
blah

HTH,

  • Tom>> …

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function isn’t
exposed beyond the class, and you get a nice clean objecty interface for
threads.


Jeff Jackowski
http://ro.com/~jeffj/

Sorry, I’m lost. Can you be more spesific?


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

oops,

dynamic cast doesn’t work on void pointers AFAIK, so just use a C style
cast.

  • Tom> Make thread function static.

class CMainApp
{

ETC …

public:

static int drawThreadFunc(void *data){
CMainApp pMyApp=dynamic_cast<CMainApp>(data);
pMyApp->DoThings();
etc …
etc …
}

ETC …

};

void CMainApp::start()
{
mThread = SDL_CreateThread(drawThreadFunc, (void*)this);
while(!done)
blah
blah
blah

HTH,

  • Tom

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function isn’t
exposed beyond the class, and you get a nice clean objecty interface for
threads.


Jeff Jackowski
http://ro.com/~jeffj/

Sorry, I’m lost. Can you be more spesific?

Tom Wilson wrote:

oops,

dynamic cast doesn’t work on void pointers AFAIK, so just use a C style
cast.

No, use a static_cast instead.

Okay, I’ve implemented it. But, why do I get this error?

Xlib: unexpected async reply (sequence 0x66)!
/bin/sh: line 1: 30026 Segmentation fault>

Make thread function static.

class CMainApp
{

ETC …

public:

static int drawThreadFunc(void *data){
CMainApp pMyApp=dynamic_cast<CMainApp>(data);
pMyApp->DoThings();
etc …
etc …
}

ETC …

};

void CMainApp::start()
{
mThread = SDL_CreateThread(drawThreadFunc, (void*)this);
while(!done)
blah
blah
blah

HTH,

  • Tom

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and
a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function
isn’t
exposed beyond the class, and you get a nice clean objecty interface
for
threads.


Jeff Jackowski
http://ro.com/~jeffj/

Sorry, I’m lost. Can you be more spesific?


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

benang at cs.its.ac.id wrote:

Okay, I’ve implemented it. But, why do I get this error?

Xlib: unexpected async reply (sequence 0x66)!
/bin/sh: line 1: 30026 Segmentation fault

On most platforms you can only do drawing from the starting thread, not
additional threads spawned. My guess is that this is the problem here.

Pete.

Okay, I’ve switched the thread, but it still error (although the error
message is not the same). Now I moved the thread function into a global
function (right above the main function). And it worked. But still, I’m a
bit curious as to why if the thread were inside a class in didn’t work.
BTW, when the function were still in a class before I get a segmentation
error:

int CMainApp::theDrawingThread(void *data)
{
/// @todo implement me
CMainApp pMyApp=static_cast<CMainApp>(data);
unsigned long test=0;
while(pMyApp->getDone()==false) //Segmentation Error
{
pMyApp->mSceneMgr->draw(); //Segmentation Error
pMyApp->screen->DrawScene(); //Segmentation Error
if (pMyApp->mMousePointer==true) SDL_ShowCursor(1); //Segmentation Error
else SDL_ShowCursor(0);

	cout<<test++<<"\n";
}

}

Okay from what I’ve read in the wiki, the SDL_CreateThread will pass the
void pointer data. But I guess the data is not there because there’s a
segmentation error.> @benang_at_cs.its.ac wrote:

Okay, I’ve implemented it. But, why do I get this error?

Xlib: unexpected async reply (sequence 0x66)!
/bin/sh: line 1: 30026 Segmentation fault

On most platforms you can only do drawing from the starting thread, not
additional threads spawned. My guess is that this is the problem here.

Pete.

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function isn’t
exposed beyond the class, and you get a nice clean objecty interface for
threads.

Sorry, I’m lost. Can you be more spesific?

Given your latest post, I think you may be confused about the this
pointer. Try this example code to help.

class example {
public:
int i;
static int j;
int func1(void *) {
i++; // have a this pointer, so can use non-static
// variables. this is passed as a parameter
// implicitly.
this->i++; // same as above
j++;
}
static int func2(void e) {
// cannont use i – no this pointer in a static function
j++; // can still use static variables
if (e) {
((example
)e)->i++;
}
}
};

int example::j; // only one of these

int main() {
example e, p; // each have an i, but still only one j

e.func1(NULL); // &e is the this pointer passed to the function

e.func2(NULL); // No this pointer. These two calls are identical.
example::func2(NULL); // Don’t need to specify an object.

example::func1(NULL): // error! No object, so no this pointer

SDL_CreateThread(e.func1, NULL); // error! e.func1 is not a function pointer
SDL_CreateThread(example::func1, NULL); // error! func1 needs a this
// pointer, so it takes more than one parameter
SDL_CreateThread(example::func2, NULL); // OK – static function doesn’t
// take a this pointer
}On Mon, 14 Aug 2006 benang at cs.its.ac.id wrote:


Jeff Jackowski
http://ro.com/~jeffj/

Okay, now why did the segmentation errors occur? FYI, I only split a
function, copy-pasted half of the code into a thread function,
static_casted the void pointer, and changed the code requiring “this” into
the static_casted variable. The code worked fine before I split it into a
thread function. To simplify what I meant:

Original code:
void CMainApp::startProses()
{
while(!mDone)
{
go(); //Event Handler
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);

}

}

Code with thread:

void CMainApp::startProses()
{
mThread = SDL_CreateThread(theDrawingThread, NULL );
while(getDone()==false)
{
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);
}
SDL_WaitThread( mThread, NULL);

}

int CMainApp::theThreadFunc(void *data)
{
CMainApp pMyApp=static_cast<CMainApp>(data);
while(pMyApp->getDone()==false) //Segmentation Error
{
pMyApp->go(); //Segmentation Error
}
}

BTW, I have a thread problem here. My application sometimes crashed and/or
showing this error:

X Error of failed request: BadLength (poly request too large or internal
Xlib length error)
Major opcode of failed request: 3 (X_GetWindowAttributes)
Serial number of failed request: 9211
Current serial number in output stream: 9209

Why is that?

Thanks in advance.> On Mon, 14 Aug 2006 @benang_at_cs.its.ac wrote:

The solution is to either not use a member function or use a static
function. Both ways eliminate the implicit this pointer parameter. You
could also make a thread class with a pure virtual thread function and
a
non-virtual run function. Could use a static run, but even better, have
run give a static non-member function in the class’s source file to
SDL_CreateThread as the entry point. This way, the helper function
isn’t
exposed beyond the class, and you get a nice clean objecty interface
for
threads.

Sorry, I’m lost. Can you be more spesific?

Given your latest post, I think you may be confused about the this
pointer. Try this example code to help.

class example {
public:
int i;
static int j;
int func1(void *) {
i++; // have a this pointer, so can use non-static
// variables. this is passed as a parameter
// implicitly.
this->i++; // same as above
j++;
}
static int func2(void e) {
// cannont use i – no this pointer in a static function
j++; // can still use static variables
if (e) {
((example
)e)->i++;
}
}
};

int example::j; // only one of these

int main() {
example e, p; // each have an i, but still only one j

e.func1(NULL); // &e is the this pointer passed to the function

e.func2(NULL); // No this pointer. These two calls are identical.
example::func2(NULL); // Don’t need to specify an object.

example::func1(NULL): // error! No object, so no this pointer

SDL_CreateThread(e.func1, NULL); // error! e.func1 is not a function
pointer
SDL_CreateThread(example::func1, NULL); // error! func1 needs a this
// pointer, so it takes more than one parameter
SDL_CreateThread(example::func2, NULL); // OK – static function doesn’t
// take a this pointer
}


Jeff Jackowski
http://ro.com/~jeffj/

Okay, now why did the segmentation errors occur? FYI, I only split a
function, copy-pasted half of the code into a thread function,
static_casted the void pointer, and changed the code requiring “this” into
the static_casted variable. The code worked fine before I split it into a
thread function. To simplify what I meant:

Original code:
void CMainApp::startProses()
{
while(!mDone)
{
go(); //Event Handler
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);

}
}

Code with thread:

void CMainApp::startProses()
{
mThread = SDL_CreateThread(theDrawingThread, NULL );
while(getDone()==false)
{
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);
}
SDL_WaitThread( mThread, NULL);

}

int CMainApp::theThreadFunc(void *data)
{
CMainApp pMyApp=static_cast<CMainApp>(data);
while(pMyApp->getDone()==false) //Segmentation Error
{
pMyApp->go(); //Segmentation Error
}
}

BTW, I have a thread problem here. My application sometimes crashed and/or
showing this error:

X Error of failed request: BadLength (poly request too large or internal
Xlib length error)
Major opcode of failed request: 3 (X_GetWindowAttributes)
Serial number of failed request: 9211
Current serial number in output stream: 9209

Why is that?

Oops, sorry. The thread function’s name was incorrect. It should be:

mThread = SDL_CreateThread(theThreadFunc, NULL );

Sorry.

Oops, sorry. The thread function’s name was incorrect. It should be:

mThread = SDL_CreateThread(theThreadFunc, NULL );

Sorry.

This is beacuse you are passing NULL for the “data” in the thread func,
and then trying to cast this into an object.

Try placing a breakpoint on the cast and see what I mean.

Anyway, it should be:

void CMainApp::startProses()
{
mThread = SDL_CreateThread(theThreadFunc, (void*)this );
while(getDone()==false)
{
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);
}
SDL_WaitThread( mThread, NULL);

}

int CMainApp::theThreadFunc(void *data)
{
assert ( “OMG NULL POINTER, EXPLOSIONS AND FIRE” && data);

if(0 != data){
	CMainApp *pMyApp=static_cast<CMainApp*>(data);
	while(pMyApp->getDone()==false) //Segmentation Error
	{
		pMyApp->go(); //Segmentation Error
	}
}
else{
	MessagePopupThing("darn it");
}

}

First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence error?>

This is beacuse you are passing NULL for the “data” in the thread func,
and then trying to cast this into an object.

Try placing a breakpoint on the cast and see what I mean.

Anyway, it should be:

void CMainApp::startProses()
{
mThread = SDL_CreateThread(theThreadFunc, (void*)this );
while(getDone()==false)
{
mSceneMgr->draw(); //Blitting
screen->DrawScene(); //Flipping
if (mMousePointer==true) SDL_ShowCursor(1);
else SDL_ShowCursor(0);
}
SDL_WaitThread( mThread, NULL);

}

int CMainApp::theThreadFunc(void *data)
{
assert ( “OMG NULL POINTER, EXPLOSIONS AND FIRE” && data);

if(0 != data){
CMainApp pMyApp=static_cast<CMainApp>(data);
while(pMyApp->getDone()==false) //Segmentation Error
{
pMyApp->go(); //Segmentation Error
}
}
else{
MessagePopupThing(“darn it”);
}
}


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

BTW, the error was:

X Error of failed request: BadLength (poly request too large or internal
Xlib length error)
Major opcode of failed request: 3 (X_GetWindowAttributes)
Serial number of failed request: 605
Current serial number in output stream: 604> First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence error?

benang at cs.its.ac.id wrote:

First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence error?

Evidently you are running on some Linux or some flavour of Unix.

use the “strace” command (you may need to install it)

strace executable >logFile.log

where executable is the name of your SDL game or whatever.

Then try and re-produce the crash. strace will produce a massive
amount of data. But it should tell you exactly what your program was
doing before it died.

Post the last few lines of this on the list. And the code concerned.

There are probably other ways than using strace, like examining core
dumps and alike which I am sure we will hear about …

HTH

  • Tom

benang at cs.its.ac.id wrote:

BTW, the error was:

X Error of failed request: BadLength (poly request too large or internal
Xlib length error)
Major opcode of failed request: 3 (X_GetWindowAttributes)
Serial number of failed request: 605
Current serial number in output stream: 604

this might also be of use to you:

http://linuxfocus.berlios.de/English/July2004/article343.shtml

  • Tom

Done that already. The funny thing is it didn’t occur when I straced it.
Also, the problem isn’t always occur. I don’t know what triggered it
though. I’ve mutexed the thread, still the problem is there.> @benang_at_cs.its.ac wrote:

First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came
up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence
error?

Evidently you are running on some Linux or some flavour of Unix.

use the “strace” command (you may need to install it)

strace executable >logFile.log

where executable is the name of your SDL game or whatever.

Then try and re-produce the crash. strace will produce a massive
amount of data. But it should tell you exactly what your program was
doing before it died.

Post the last few lines of this on the list. And the code concerned.

There are probably other ways than using strace, like examining core
dumps and alike which I am sure we will hear about …

HTH

  • Tom

SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

benang at cs.its.ac.id wrote:

Done that already. The funny thing is it didn’t occur when I straced it.
Also, the problem isn’t always occur. I don’t know what triggered it
though. I’ve mutexed the thread, still the problem is there.

keep stracing until it does occur

First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came
up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence
error?

Evidently you are running on some Linux or some flavour of Unix.

use the “strace” command (you may need to install it)

strace executable >logFile.log

where executable is the name of your SDL game or whatever.

Then try and re-produce the crash. strace will produce a massive
amount of data. But it should tell you exactly what your program was
doing before it died.

Post the last few lines of this on the list. And the code concerned.

There are probably other ways than using strace, like examining core
dumps and alike which I am sure we will hear about …

HTH

  • Tom

SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl


SDL mailing list
SDL at libsdl.org
http://www.libsdl.org/mailman/listinfo/sdl

Okay, now it gets weirder. When I straced it again (and again, and again
until the problem occurs), it crashed. The previous error message didn’t
show up.> @benang_at_cs.its.ac wrote:

Done that already. The funny thing is it didn’t occur when I straced it.
Also, the problem isn’t always occur. I don’t know what triggered it
though. I’ve mutexed the thread, still the problem is there.

keep stracing until it does occur

  • Tom

@benang_at_cs.its.ac wrote:

First, sorry for the late reply. I’ve been away for 4 days.

Ahh, thanks. Looks like my bad habit of not noticing tiny details came
up
again. I should’ve noticed it before.

BTW, what about my other question? The one about the lost sequence
error?

Evidently you are running on some Linux or some flavour of Unix.

use the “strace” command (you may need to install it)

strace executable >logFile.log

where executable is the name of your SDL game or whatever.

Then try and re-produce the crash. strace will produce a massive
amount of data. But it should tell you exactly what your program was
doing before it died.

Post the last few lines of this on the list. And the code concerned.

There are probably other ways than using strace, like examining core
dumps and alike which I am sure we will hear about …

HTH

  • Tom