Threading Library, I don't understand what is wrong here.

S

smorrey

Howdy folks,
I recently purchased a book on C++ MUD creation and it features alot of
nifty tidbits.
The book is
MUD GAME PROGRAMMING by Ron Penton
Publisher: Premier Press

Anyways of particular interest and what drew me to the book was the
crossplatform threading library.
But the problem is it appears to be broken at a single line of code,
and I can't seem to refactor it to get it work. It's likely something
incredibly simple I'm missing here.
There are only 2 files involved, one is the header and one is the
implementation of the header a "testapp" as it were.
The test app fails to compile properly with this message
ThreadLibTest.cpp: In function 'void PrintThread(void*)':
ThreadLibTest.cpp:8: error: cast from 'void*' to 'char' loses
precision

Here is the code for the testapp

#include <iostream>
#include <unistd.h>
#include "ThreadLib.h"



int main() {
ThreadLib::ThreadID a, b;
a = ThreadLib::Create( PrintThread, (void*)'a' );
b = ThreadLib::Create( PrintThread, (void*)'b' );

ThreadLib::WaitForFinish( b );
ThreadLib::WaitForFinish( a );

char c;
cin >> c;
return 0;
}

void PrintThread( void* data ) {
// convert the data passed in into a character.
char c = (char)data;

for( int i = 0; i < 10000; i++ ) {
cout << c;
cout.flush();
}
}


And here is the code for the ThreadLib.h file

#include <unistd.h>
#ifdef WIN32 // Windows 95 and above
#include <windows.h>
#else // Linux
#include <pthread.h>
#endif
namespace ThreadLib{
typedef void (*ThreadFunc)(void*);

#ifdef WIN32 // Windows 95 and above
typedef DWORD ThreadID;
std::map< DWORD, HANDLE > g_handlemap;
#else // Linux
typedef pthread_t ThreadID;
#endif

class DummyData {
public:
ThreadFunc m_func;
void* m_data;
};

#ifdef WIN32
DWORD WINAPI DummyRun( void* p_data )
#else
void* DummyRun( void* p_data )
#endif
{
// convert the dummy data
DummyData* data = (DummyData*)p_data;

// run the function with the given data
data->m_func( data->m_data );

// now delete the data
delete data;

// and return 0.
return 0;
}

inline ThreadID Create(ThreadFunc p_func, void* p_param ){
ThreadID t;
// create a new dummy data block
DummyData* data = new DummyData;
data->m_func = p_func;
data->m_data = p_param;

#ifdef WIN32 // create a WIN32 thread
HANDLE h;
h = CreateThread( NULL, 0, DummyRun, data, 0, &t );
if( h != 0 ) {
// insert the handle into the handlemap
g_handlemap[t] = h;
}
#else // create a Linux thread
pthread_create( &t, 0, DummyRun, data );
#endif

if( t == 0 ) {
// delete the data first
delete data;
// throw an error
//throw Exception( CreationFailure );
}
return t;
}

inline ThreadID GetID() {
#ifdef WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}

inline void WaitForFinish( ThreadID p_thread ) {
#ifdef WIN32
// look up the handle and wait for the thread to finish
WaitForSingleObject( g_handlemap[p_thread], INFINITE );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// "join" the thread. This essentially transfers control over to
// the thread and waits for it to finish.
pthread_join( p_thread, NULL );
#endif
}

inline void Kill( ThreadID& p_thread ) {
#ifdef WIN32
// terminate the thread
TerminateThread( g_handlemap[p_thread], 0 );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// cancel the thread.
pthread_cancel( p_thread );
#endif
}

inline void YieldThread( int p_milliseconds = 1 ) {
#ifdef WIN32
Sleep( p_milliseconds );
#else
usleep( p_milliseconds * 1000 );
#endif
}
}


Any help on this would be appreciated, I tried to go to the authors
website but it appears to be down.
I'm just so frustrated because to me at least this code looks exactly
right.
Anyways thanks in advance!
Regards,
 
M

Markus Svilans

Hi,

This cast,

(void*)'a'

means you are casting a character (byte) value to a void pointer. This
is where your error is coming from.

I think you should probably try double quotes:

(void*)"a"

Then you will be casting a char pointer to a void pointer, which seems
like what you intended to do.

Double quotes mean a string (array of chars, accessed via char*), and
single quotes mean a single character value (byte).

Regards,
Markus.


Howdy folks,
I recently purchased a book on C++ MUD creation and it features alot of
nifty tidbits.
The book is
MUD GAME PROGRAMMING by Ron Penton
Publisher: Premier Press

Anyways of particular interest and what drew me to the book was the
crossplatform threading library.
But the problem is it appears to be broken at a single line of code,
and I can't seem to refactor it to get it work. It's likely something
incredibly simple I'm missing here.
There are only 2 files involved, one is the header and one is the
implementation of the header a "testapp" as it were.
The test app fails to compile properly with this message
ThreadLibTest.cpp: In function 'void PrintThread(void*)':
ThreadLibTest.cpp:8: error: cast from 'void*' to 'char' loses
precision

Here is the code for the testapp

#include <iostream>
#include <unistd.h>
#include "ThreadLib.h"



int main() {
ThreadLib::ThreadID a, b;
a = ThreadLib::Create( PrintThread, (void*)'a' );
b = ThreadLib::Create( PrintThread, (void*)'b' );

ThreadLib::WaitForFinish( b );
ThreadLib::WaitForFinish( a );

char c;
cin >> c;
return 0;
}

void PrintThread( void* data ) {
// convert the data passed in into a character.
char c = (char)data;

for( int i = 0; i < 10000; i++ ) {
cout << c;
cout.flush();
}
}


And here is the code for the ThreadLib.h file

#include <unistd.h>
#ifdef WIN32 // Windows 95 and above
#include <windows.h>
#else // Linux
#include <pthread.h>
#endif
namespace ThreadLib{
typedef void (*ThreadFunc)(void*);

#ifdef WIN32 // Windows 95 and above
typedef DWORD ThreadID;
std::map< DWORD, HANDLE > g_handlemap;
#else // Linux
typedef pthread_t ThreadID;
#endif

class DummyData {
public:
ThreadFunc m_func;
void* m_data;
};

#ifdef WIN32
DWORD WINAPI DummyRun( void* p_data )
#else
void* DummyRun( void* p_data )
#endif
{
// convert the dummy data
DummyData* data = (DummyData*)p_data;

// run the function with the given data
data->m_func( data->m_data );

// now delete the data
delete data;

// and return 0.
return 0;
}

inline ThreadID Create(ThreadFunc p_func, void* p_param ){
ThreadID t;
// create a new dummy data block
DummyData* data = new DummyData;
data->m_func = p_func;
data->m_data = p_param;

#ifdef WIN32 // create a WIN32 thread
HANDLE h;
h = CreateThread( NULL, 0, DummyRun, data, 0, &t );
if( h != 0 ) {
// insert the handle into the handlemap
g_handlemap[t] = h;
}
#else // create a Linux thread
pthread_create( &t, 0, DummyRun, data );
#endif

if( t == 0 ) {
// delete the data first
delete data;
// throw an error
//throw Exception( CreationFailure );
}
return t;
}

inline ThreadID GetID() {
#ifdef WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}

inline void WaitForFinish( ThreadID p_thread ) {
#ifdef WIN32
// look up the handle and wait for the thread to finish
WaitForSingleObject( g_handlemap[p_thread], INFINITE );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// "join" the thread. This essentially transfers control over to
// the thread and waits for it to finish.
pthread_join( p_thread, NULL );
#endif
}

inline void Kill( ThreadID& p_thread ) {
#ifdef WIN32
// terminate the thread
TerminateThread( g_handlemap[p_thread], 0 );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// cancel the thread.
pthread_cancel( p_thread );
#endif
}

inline void YieldThread( int p_milliseconds = 1 ) {
#ifdef WIN32
Sleep( p_milliseconds );
#else
usleep( p_milliseconds * 1000 );
#endif
}
}


Any help on this would be appreciated, I tried to go to the authors
website but it appears to be down.
I'm just so frustrated because to me at least this code looks exactly
right.
Anyways thanks in advance!
Regards,
 
S

smorrey

Oh my god!
I can't believe I missed that, this has had me tearing my hair out for
days!
Anyways thank you very, very much!

Markus said:
Hi,

This cast,

(void*)'a'

means you are casting a character (byte) value to a void pointer. This
is where your error is coming from.

I think you should probably try double quotes:

(void*)"a"

Then you will be casting a char pointer to a void pointer, which seems
like what you intended to do.

Double quotes mean a string (array of chars, accessed via char*), and
single quotes mean a single character value (byte).

Regards,
Markus.


Howdy folks,
I recently purchased a book on C++ MUD creation and it features alot of
nifty tidbits.
The book is
MUD GAME PROGRAMMING by Ron Penton
Publisher: Premier Press

Anyways of particular interest and what drew me to the book was the
crossplatform threading library.
But the problem is it appears to be broken at a single line of code,
and I can't seem to refactor it to get it work. It's likely something
incredibly simple I'm missing here.
There are only 2 files involved, one is the header and one is the
implementation of the header a "testapp" as it were.
The test app fails to compile properly with this message
ThreadLibTest.cpp: In function 'void PrintThread(void*)':
ThreadLibTest.cpp:8: error: cast from 'void*' to 'char' loses
precision

Here is the code for the testapp

#include <iostream>
#include <unistd.h>
#include "ThreadLib.h"



int main() {
ThreadLib::ThreadID a, b;
a = ThreadLib::Create( PrintThread, (void*)'a' );
b = ThreadLib::Create( PrintThread, (void*)'b' );

ThreadLib::WaitForFinish( b );
ThreadLib::WaitForFinish( a );

char c;
cin >> c;
return 0;
}

void PrintThread( void* data ) {
// convert the data passed in into a character.
char c = (char)data;

for( int i = 0; i < 10000; i++ ) {
cout << c;
cout.flush();
}
}


And here is the code for the ThreadLib.h file

#include <unistd.h>
#ifdef WIN32 // Windows 95 and above
#include <windows.h>
#else // Linux
#include <pthread.h>
#endif
namespace ThreadLib{
typedef void (*ThreadFunc)(void*);

#ifdef WIN32 // Windows 95 and above
typedef DWORD ThreadID;
std::map< DWORD, HANDLE > g_handlemap;
#else // Linux
typedef pthread_t ThreadID;
#endif

class DummyData {
public:
ThreadFunc m_func;
void* m_data;
};

#ifdef WIN32
DWORD WINAPI DummyRun( void* p_data )
#else
void* DummyRun( void* p_data )
#endif
{
// convert the dummy data
DummyData* data = (DummyData*)p_data;

// run the function with the given data
data->m_func( data->m_data );

// now delete the data
delete data;

// and return 0.
return 0;
}

inline ThreadID Create(ThreadFunc p_func, void* p_param ){
ThreadID t;
// create a new dummy data block
DummyData* data = new DummyData;
data->m_func = p_func;
data->m_data = p_param;

#ifdef WIN32 // create a WIN32 thread
HANDLE h;
h = CreateThread( NULL, 0, DummyRun, data, 0, &t );
if( h != 0 ) {
// insert the handle into the handlemap
g_handlemap[t] = h;
}
#else // create a Linux thread
pthread_create( &t, 0, DummyRun, data );
#endif

if( t == 0 ) {
// delete the data first
delete data;
// throw an error
//throw Exception( CreationFailure );
}
return t;
}

inline ThreadID GetID() {
#ifdef WIN32
return GetCurrentThreadId();
#else
return pthread_self();
#endif
}

inline void WaitForFinish( ThreadID p_thread ) {
#ifdef WIN32
// look up the handle and wait for the thread to finish
WaitForSingleObject( g_handlemap[p_thread], INFINITE );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// "join" the thread. This essentially transfers control over to
// the thread and waits for it to finish.
pthread_join( p_thread, NULL );
#endif
}

inline void Kill( ThreadID& p_thread ) {
#ifdef WIN32
// terminate the thread
TerminateThread( g_handlemap[p_thread], 0 );
// close the handle of the thread
CloseHandle( g_handlemap[p_thread] );
// remove the handle from the map
g_handlemap.erase( p_thread );
#else
// cancel the thread.
pthread_cancel( p_thread );
#endif
}

inline void YieldThread( int p_milliseconds = 1 ) {
#ifdef WIN32
Sleep( p_milliseconds );
#else
usleep( p_milliseconds * 1000 );
#endif
}
}


Any help on this would be appreciated, I tried to go to the authors
website but it appears to be down.
I'm just so frustrated because to me at least this code looks exactly
right.
Anyways thanks in advance!
Regards,
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top