|
A very well written article and rock solid source. Thanks!
|
|
|
|
|
I seriously doubt whether the author has tested this code in Solaris.
In Solaris the function that you pass to pthread_create in C++ must be a global
function marked as extern "C". That function could just call your static
member function, or it could call a member function on an object that it
somehow knows about (which is probably what the static member function
did, anyway).
|
|
|
|
|
Example1.cpp is successfully executed, but Example2.cpp has error message as below..
"Creating of thread failed!"
Is there anybody who solved this problem?
Thank you...
|
|
|
|
|
MSDN:
lReleaseCount
[in] Amount by which the semaphore object's current count is to be increased. The value must be greater than zero. If the specified amount would cause the semaphore's count to exceed the maximum count that was specified when the semaphore was created, the count is not changed and the function returns FALSE.
|
|
|
|
|
Hello,
First of all, thanks for this code... simple, light and working... just what I needed
My concern is about the licence. You put a copyright header in your files but there is not much more information about this.
As an open-source project, can we use it ? modify it ? ApachePublicLicence-it ?
Thank you !
|
|
|
|
|
Hi,
I created a patch file to make the Thread.h compile on newer gcc compilers.
Als included the other corrections from previous mails
--- orig/Posix/Thread.h 2003-11-12 20:26:00.000000000 +0100
+++ src/Posix/Thread.h 2005-08-18 08:50:57.000000000 +0200
@@ -17,10 +17,9 @@
#define InvalidHandle 0
-template
-<
- typename Thread_T
->
+typedef void *( * pthread_fn )( void * );
+
+template <typename Thread_T>
class Thread
{
private:
@@ -72,11 +71,13 @@ class Thread
Instance I(Param,0,Function,CancelEnable,CancelAsync);
- int R = pthread_create((pthread_t *)H,&attr,ThreadMainHandler,(void *)&I);
- pthread_attr_destroy(&attr);
-
- if ( !R ) S_Create().Wait();
- else if ( H ) *H = InvalidHandle;
+ Handle h=InvalidHandle;
+ int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
+
+ pthread_attr_destroy(&attr);
+
+ if(H) *H = h;
+ if ( !R ) S_Create().Wait();
M_Create().Unlock();
return errno;
@@ -103,11 +104,13 @@ class Thread
Instance I(Param,const_cast<Thread *>(this),0,CancelEnable,CancelAsync);
- int R = pthread_create((pthread_t *)H,&attr,ThreadMainHandler,(void *)&I);
- pthread_attr_destroy(&attr);
-
- if ( !R ) S_Create().Wait();
- else if ( H ) *H = InvalidHandle;
+ Handle h=InvalidHandle;
+ int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
+
+ pthread_attr_destroy(&attr);
+
+ if(H) *H = h;
+ if ( !R ) S_Create().Wait();
M_Create().Unlock();
return errno;
@@ -160,9 +163,9 @@ class Thread
Instance( Thread_C_R P, Thread<Thread_T> *const &O, const Thread<Thread_T>::Handler &pH = 0, const bool &CE=false, const bool &CA=false )
: pFN(pH), Data(P), Owner(O), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
- Thread<Thread_T>::Thread_C_R Data;
+ Handler pFN;
+ Thread_C_R Data;
Thread<Thread_T> * Owner;
- Thread<Thread_T>::Handler pFN;
unsigned char Flags;
};
};
@@ -171,7 +174,7 @@ class Thread
// Explicit specialization, no thread parameters
//
-class Thread<void>
+template <> class Thread<void>
{
private:
typedef struct Instance;
@@ -217,11 +220,13 @@ class Thread<void>
Instance I(0,Function,CancelEnable,CancelAsync);
- int R = pthread_create((pthread_t *)H,&attr,ThreadMainHandler,(void *)&I);
- pthread_attr_destroy(&attr);
-
- if ( !R ) S_Create().Wait();
- else if ( H ) *H = InvalidHandle;
+ Handle h=InvalidHandle;
+ int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
+
+ pthread_attr_destroy(&attr);
+
+ if(H) *H = h;
+ if ( !R ) S_Create().Wait();
M_Create().Unlock();
return errno;
@@ -247,11 +252,13 @@ class Thread<void>
Instance I(const_cast<Thread *>(this),0,CancelEnable,CancelAsync);
- int R = pthread_create((pthread_t *)H,&attr,ThreadMainHandler,(void *)&I);
- pthread_attr_destroy(&attr);
-
- if ( !R ) S_Create().Wait();
- else if ( H ) *H = InvalidHandle;
+ Handle h=InvalidHandle;
+ int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);
+
+ pthread_attr_destroy(&attr);
+
+ if(H) *H = h;
+ if ( !R ) S_Create().Wait();
M_Create().Unlock();
return errno;
@@ -303,8 +310,8 @@ class Thread<void>
Instance( Thread<void> *const &O, const Thread<void>::Handler &pH = 0, const bool &CE=false, const bool &CA=false )
: pFN(pH), Owner(O), Flags(0) { if ( CE ) Flags|=1; if ( CA ) Flags|=2; }
- Thread<void> * Owner;
Thread<void>::Handler pFN;
+ Thread<void> * Owner;
unsigned char Flags;
};
};
|
|
|
|
|
Works fine thanks a lot !!!
|
|
|
|
|
Thanks! This worked out great. I am porting some code to MAC OS X and I was running into compiler problems when using GCC 4.0 (for Apple).
|
|
|
|
|
tell me how exactly to apply the patch. I'm using fedora 10. your patch file is giving some error.
patch [some options] oldfile newfile
tell me which options to use....
Nirandas,
a developer from India.
http://www.nirandas.com
|
|
|
|
|
I manually patched the entire file...
still the errno creates a problem. what to do of that.....
Nirandas,
a developer from India.
http://www.nirandas.com
|
|
|
|
|
\Win32\Thread.h
line 92
typedef void (* Handler) ( Thread_R );
should be:
typedef void (THREAD_CALL/*Here*/ * Handler) ( Thread_R );
??
To be or not to be!
|
|
|
|
|
I am using MS VC6.0 and it is impossible for me to update to VC.NET. So I made a few changes(commented out sth) to this code and it seems to work well now, but I'm not sure!
File: \Win32\Thread.h
Location: Bottom of template class Thread(about line 220 ~ 228)
Changes
<br />
struct Instance<br />
{<br />
Instance( Thread_C_R P, Thread<Thread_T> *const &O, const Thread<Thread_T>::Handler &pH = 0 )<br />
: pFN(pH), Data(P), Owner(O) {}<br />
<br />
Thread<Thread_T>::Thread_C_R Data;<br />
Thread<Thread_T> * Owner;<br />
Thread<Thread_T>::Handler pFN;<br />
};<br />
To
<br />
struct Instance<br />
{<br />
Instance( Thread_C_R P, Thread<Thread_T> *const &O, const Handler &pH = 0 )<br />
: pFN(pH), Data(P), Owner(O) {}<br />
<br />
Thread_C_R Data;<br />
Thread<Thread_T> * Owner;<br />
Handler pFN;<br />
};<br />
Is this OK?
Please tell me! Thanx!!
Chinese People Are Very Good
|
|
|
|
|
Hi, I try to use your class in an application that should compile under Windows and Linux.
So far I had written a little test app that compile with Vc++, but when I try to compile it with g++ I got some error:
[mathmoi@localhost ThreadTest]$ g++ -c -O7 TestThread.cpp
In file included from Thread.h:9,
from TestThread.cpp:2:
Posix/Thread.h: Dans static member function « static int
Thread<void>::Create(void (* const&)(), pthread_t* const&, const bool&,
const unsigned int&, const bool&, const bool&) »:
Posix/Thread.h:220: error: conversion invalide de «
void*(*)(Thread<void>::Instance*) » vers « void*(*)(void*) »
Posix/Thread.h: Dans member function « int Thread<void>::Create(pthread_t*
const&, const bool&, const unsigned int&, const bool&, const bool&) const
»:
Posix/Thread.h:250: error: conversion invalide de «
void*(*)(Thread<void>::Instance*) » vers « void*(*)(void*) »
TestThread.cpp:4:21: windows.h : Aucun fichier ou répertoire de ce type
Posix/Thread.h: Dans member function « int Thread<Thread_T>::Create(const
Thread_T&, pthread_t* const&, const bool&, const unsigned int&, const bool&,
const bool&) const [with Thread_T = int] »:
TestThread.cpp:24: instantiated from here
Posix/Thread.h:106: error: conversion invalide de «
void*(*)(Thread<int>::Instance*) » vers « void*(*)(void*) »
TestThread.cpp:46:2: attention : pas de retour chariot à la fin du fichier
[mathmoi@localhost ThreadTest]$ g++ -v
Lecture des spécification à partir de /usr/lib/gcc-lib/i386-redhat-linux/3.3.2/specs
Configuré avec: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --enable-shared --enable-threads=posix --disable-checking --disable-libunwind-exceptions --with-system-zlib --enable-__cxa_atexit --host=i386-redhat-linux
Modèle de thread: posix
version gcc 3.3.2 20040119 (Red Hat Linux 3.3.2-8)
Can you help me with this ?
Mathieu Pagé
pagemathieu @ Microsoft email system . com
|
|
|
|
|
I do have a quick fix for you that *should* work - I am working with a much newer version that will be reflected here soon. for you, here's what to do:
1. Add this to the beginning of Posix/Thread.h
typedef void *( * pthread_fn )( void * );
2. There's exactly 4 places in the file where you see this:
(part of what I fixed in the new version!)
<br />
int R = pthread_create((pthread_t *)H,&attr,ThreadMainHandler,(void *)&I);<br />
pthread_attr_destroy(&attr);<br />
<br />
if ( !R ) S_Create().Wait();<br />
else if ( H ) *H = InvalidHandle;<br />
Replace it with this:
<br />
Handle h=InvalidHandle;<br />
int R = pthread_create((pthread_t *)&h,&attr,(pthread_fn)ThreadMainHandler,(void *)&I);<br />
<br />
pthread_attr_destroy(&attr);<br />
<br />
if(H) *H = h;<br />
if ( !R ) S_Create().Wait();<br />
This is a just-for-now workaround, but it should fix the error you get, along with a bug I found that arises in RH9 when the handle pointer is null. Hope it helps!
- Phillip
|
|
|
|
|
Hi, it fixed my problem, but I got some others now !
I can compile my test application doing "g++ -c TestThread.cpp", but when I try to compile and link doing this : "g++ *.c++" I got this:
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN6ThreadIvE4KillEm+0xd): dans la fonction « Thread<void>::Kill(unsigned long)»:
: undefined reference to `pthread_cancel'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZNK6ThreadIiE6CreateERKiRKPmRKbRKjS7_S7_+0x5a): dans la fonction « Thread<int>::Create(int const&, unsigned long* const&, bool const&, unsigned const&, bool const&, bool const&) const»:
: undefined reference to `pthread_attr_setstacksize'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN9SemaphoreC1Ei+0x1f): dans la fonction « Semaphore::Semaphore[in-charge](int)»:
: undefined reference to `sem_init'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN9SemaphoreD1Ev+0x1a): dans la fonction « Semaphore::~Semaphore [in-charge]()»:
: undefined reference to `sem_destroy'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZNK9Semaphore4WaitEv+0x11): dans la fonction « Semaphore::Wait() const»:
: undefined reference to `sem_wait'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZNK9Semaphore4PostEv+0x11): dans la fonction « Semaphore::Post() const»:
: undefined reference to `sem_post'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN5MutexC1Ev+0x17): dans la fonction « Mutex::Mutex[in-charge]()»:
: undefined reference to `pthread_mutexattr_init'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN5MutexC1Ev+0x28): dans la fonction « Mutex::Mutex[in-charge]()»:
: undefined reference to `pthread_mutexattr_settype'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN5MutexC1Ev+0x4d): dans la fonction « Mutex::Mutex[in-charge]()»:
: undefined reference to `pthread_mutexattr_destroy'
/tmp/ccqx2Edp.o(.gnu.linkonce.t._ZN9SemaphoreD0Ev+0x1a): dans la fonction « Semaphore::~Semaphore [in-charge deleting]()»:
: undefined reference to `sem_destroy'
collect2: ld a retourné 1 code d'état d'exécution
maybe I miss a library or something.
thanks for your previous help.
Mathieu P.
|
|
|
|
|
<br />
try this:<br />
<br />
g++ -c TestThread.cpp" -lpthread<br />
^^<br />
Thread Functions<br />
<br />
you need to link to the POSIX thread library. If that's all you get for errors, then it appears that my fix for you worked.<br />
|
|
|
|
|
Thank you very much phillip, it does the trick
everything is working now.
While looking to your source code I saw no licence, so i am wondering: Can I use your code in any type of program ?
The one I'm actualy working on is a Chess engine that is not commercial nor open source for now. But it could change in the futur, so I would like to know what is your politic about this.
again thanks for your help.
Mathieu P.
|
|
|
|
|
Hi Mathieu,
I obviously haven't checked this article for a while I've been very busy beginning my graduate studies in computer science.
The answer to your question is yes, you can use my code anywhere, and some mention of my name & contact info (phillip@sitbon.net) is all I ask. This may change in the future, but I don't have time to decide how to handle that at the moment. I am interested in your project, so feel free to keep in touch as well.
Sorry for not keeping things up to date - I've been swamped. I have some new code to introduce, and I have finally decided that exceptions in my code isn't really a performance hit, so they are there as well - this greatly simplifies things.
good luck with the code!
- Phillip
|
|
|
|
|
>Hi Mathieu,
> I obviously haven't checked this article for a while I've been very busy beginning my graduate studies in computer science.
>
> The answer to your question is yes, you can use my code anywhere, and some mention of my name & contact info (phillip@sitbon.net) is all I ask. This may change in the future, but I don't have time to decide how to handle that at the moment. I am interested in your project, so feel free to keep in touch as well.
Thank you ! I will obvously give you all the credit you deserve, your name was already in each source files, I just added your address.
> Sorry for not keeping things up to date - I've been swamped. I have some new code to introduce, and I have finally decided that exceptions in my code isn't really a performance hit, so they are there as well - this greatly simplifies things.
No problem for the delay. If you have any new version of the classes I would like to have then, so if you could contact me when they will be publicly avaible it would be fine.
In case you'd like to have a suggestion, I would be very usefull to have some priority management functions. It seem really simple to implement under windows, but not so trivial under posix since the posix OSs can declare differents priority levels. This is not a request, just a wish.
>good luck with the code!
Thanks, Good luck with your studies.
Mathieu Pagé
|
|
|
|
|
Sorry about that... formatting got screwed up and I couldn't delete it :P
Anyway, the thread functions reside in libpthread, so that's why you need to link to the POSIX thread library using -lpthread
|
|
|
|
|
I get the following errors when compiling under VC++ 6.0. Are these bugs in the compiler?
Compiling...
example1.cpp
d:\dev\cross_platform_thread_class\zip\win32\thread.h(214) : error C2065: 'uintptr_t' : undeclared identifier
d:\dev\cross_platform_thread_class\zip\win32\thread.h(165) : error C2629: unexpected 'struct Thread<int>::Instance ('
d:\dev\cross_platform_thread_class\example1.cpp(41) : see reference to class template instantiation 'Thread<int>' being compiled
d:\dev\cross_platform_thread_class\zip\win32\thread.h(165) : error C2334: unexpected token(s) preceding ':'; skipping apparent function body
d:\dev\cross_platform_thread_class\example1.cpp(41) : see reference to class template instantiation 'Thread<int>' being compiled
d:\dev\cross_platform_thread_class\zip\win32\thread.h(168) : error C2027: use of undefined type 'Thread<int>'
d:\dev\cross_platform_thread_class\example1.cpp(41) : see reference to class template instantiation 'Thread<int>' being compiled
d:\dev\cross_platform_thread_class\zip\win32\thread.h(170) : error C2027: use of undefined type 'Thread<int>'
d:\dev\cross_platform_thread_class\example1.cpp(41) : see reference to class template instantiation 'Thread<int>' being compiled
Error executing cl.exe.
example1.exe - 5 error(s), 0 warning(s)
Thanks in advance for your assistance.
Al:an
|
|
|
|
|
Hi There,
First of all, I want to apologize for listing VC6 without having tested it... I should have known better. I'm going to have to dig it up and see if I can reproduce your problem.
My best advice at the moment would be to get the newest version of the Platform SDK (Feb 2003 I believe), because you should not be getting an error that uintptr_t is undefined - check your <process.h> to make sure it's there. If M$ put the versions in their includes, I'd be able to tell you exactly what you need.
In the meantime, I will check for conformance issues, just in case my template usage is not compatible with VC6.
Does anyone else have the same issue? Or the opposite? (for VC6)
- Phillip
|
|
|
|
|
I received a different error in VC++ 6.
Compiling...<br />
thread_tester.cpp<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\win32\thread.h(222) : error C2629: unexpected 'struct Thread<int>::Instance ('<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\thread_tester.cpp(26) : see reference to class template instantiation 'Thread<int>' being compiled<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\win32\thread.h(222) : error C2334: unexpected token(s) preceding ':'; skipping apparent function body<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\thread_tester.cpp(26) : see reference to class template instantiation 'Thread<int>' being compiled<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\win32\thread.h(225) : error C2027: use of undefined type 'Thread<int>'<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\thread_tester.cpp(26) : see reference to class template instantiation 'Thread<int>' being compiled<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\win32\thread.h(227) : error C2027: use of undefined type 'Thread<int>'<br />
c:\winnt\profiles\celeona\desktop\windows event agent\thread_source\thread_tester.cpp(26) : see reference to class template instantiation 'Thread<int>' being compiled<br />
Error executing cl.exe.<br />
Creating browse info file...<br />
<br />
thread_source.exe - 4 error(s), 0 warning(s)
I suspect it is also due to the SDK version. Unfortunately, updating the SDK is not an option for me at this time, but this workaround took care of the problem.
Insert this code below line 76:
template<typename Thread_T> class Thread;<br />
<br />
template<typename Thread_T><br />
struct Instance<br />
{<br />
private:<br />
Instance( Thread<Thread_T>::Thread_C_R P, Thread<Thread_T> *const &O, const Thread<Thread_T>::Handler &pH = 0 )<br />
: pFN(pH), Data(P), Owner(O) {}<br />
Thread<Thread_T>::Thread_C_R Data;<br />
Thread<Thread_T> * Owner;<br />
Thread<Thread_T>::Handler pFN;<br />
friend class Thread<Thread_T>; <br />
};
Change the typedef on line 85 to:
typedef Instance<Thread_T> _MyInst;
Then change all other instances of "Instance" in the Thread class to _MyInst, and remove the struct declared at the bottom of class Thread.
Works great now, even with my antique version of VC++. I actually like this class better then the one in boost because it doesn't require any other components in the boost library.
|
|
|
|
|
I'n glad somebody appreciates it Thanks for the workaround... I'll incorporate it into my code soon. I upgraded to VC2003, so I haven't gone back to look at the VC6 issues lately.
Thanks again!
Phillip
|
|
|
|
|
Thank you for help us, but after I changed the code following your instruction I got errors like this:
--------------------------------
<codecompiling...
example.cpp
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(78) :="" error="" c2946:="" explicit="" instantiation;="" 'class="" thread'="" is="" not="" a="" template-class="" specialization
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(84)="" c2629:="" unexpected="" 'struct="" instance="" ('
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(84)="" c2334:="" token(s)="" preceding="" ':';="" skipping="" apparent="" function="" body
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(86)="" c2027:="" use="" of="" undefined="" type="" 'thread'
="" g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(78)="" see="" declaration="" 'thread'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(86)="" c2146:="" syntax="" missing="" ';'="" before="" identifier="" 'data'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(86)="" c2501:="" 'thread_c_r'="" storage-class="" or="" specifiers
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(86)="" 'data'="" specifiers
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(88)="" 'thread'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(88)="" 'pfn'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(88)="" 'handler'="" 'pfn'="" specifiers
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(90)="" instance'="" specialization
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(245)="" c2989:="" 'thread'="" template="" class="" has="" already="" been="" defined="" as="" non-template="" class
="" 'thread'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(250)="" c2143:="" '<'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(250)="" '<'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(251)="" '{'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\win32\thread.h(251)="" c2447:="" header="" (old-style="" formal="" list?)
g:\个人资料\工作目录\learnsocket\sockettest\multithread\example.cpp(41)="" ','="" '<'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\example.cpp(41)="" c2059:="" '<'
g:\个人资料\工作目录\learnsocket\sockettest\multithread\example.cpp(42)="" fatal="" c1903:="" unable="" to="" recover="" from="" previous="" error(s);="" stopping="" compilation
error="" executing="" cl.exe.
creating="" browse="" info="" file...
bscmake:="" bk1506="" cannot="" open="" file="" '.\debug\example.sbr':="" no="" such="" directory
error="" bscmake.exe.
multithread.exe="" -="" 21="" error(s),="" 0="" warning(s)
<="" code="">
--------------------------------
I am using VC++6.0 Enterprise Edition, Windows XP
To be or not to be!
|
|
|
|
|