How to forward declare pthread_t when that is a typedef

Started by
10 comments, last by Toolmaker 14 years, 11 months ago
I'm using pthreads for win32 and I want to forward declare pthread_t: struct pthread_t; but I get this error: 'pthread_t' : redefinition; different basic types It is declared in the pthreads headers as typedef struct { void * p; /* Pointer to actual object */ unsigned int x; /* Extra information - reuse count etc */ } ptw32_handle_t; typedef ptw32_handle_t pthread_t; where ptw32_handle_t is a struct; however on a Linux system, pthread_t is itself a struct, not typedef, and I want my code to build on Win and Linux. So how do I do the forward declaration? I don't want to include pthread.h in the header with the class declaration where I'm storing a *pthread_t as it's a file that gets included in many places where pthread.h doesn't need to be. [Edited by - Prune on April 29, 2009 7:11:24 PM]
"But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?" --Mark Twain

~~~~~~~~~~~~~~~Looking for a high-performance, easy to use, and lightweight math library? http://www.cmldev.net/ (note: I'm not associated with that project; just a user)
Advertisement
#ifdef _WIN32  struct ptw32_handle_t;  typedef ptw32_handle_t pthread_t;#else  struct pthread_t;#endif
error C2371: 'ptw32_handle_t' : redefinition; different basic types
Looks like ptw32_handle_t is a typedef as well (typedef struct {...} ptw32_handle_t). Since the struct ptw32_handle_t is a typedef of is unnamed, I can't forward declare that one... :(
"But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?" --Mark Twain

~~~~~~~~~~~~~~~Looking for a high-performance, easy to use, and lightweight math library? http://www.cmldev.net/ (note: I'm not associated with that project; just a user)
If you're getting redefinition errors then it's obviously already defined for you, so why do you need to forward declare it?
The error is in pthread.h which is included in the .cpp file.

myclass.h
~~~~~~~~~
pthread_t forward declaration
class with pointer to pthread_t

myclass.cpp
~~~~~~~~~~~
#include "myclass.h"
#include <pthread.h>
class function definitions
"But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?" --Mark Twain

~~~~~~~~~~~~~~~Looking for a high-performance, easy to use, and lightweight math library? http://www.cmldev.net/ (note: I'm not associated with that project; just a user)
When I want to achieve something like that (for example when an exported class contains non-exported template-instantiated members), I use something I stole from Qt:

// Header fileclass foo : public boost::noncopyable{    // Forward declaration of my implementation class    class impl;    // If you don't want to create your own copy constructor and assignment operator, use a shared ptr from the standard library or boost, or inherit from boost::noncopyable    impl *d;    foo();    ~foo();}// Implementation fileclass foo::impl{public:    pthread_t *handle;};foo::foo()    : d( new impl() ){}foo::~foo(){   delete d;}


Ofcourse there's an extra new and delete in it, but a thread isn't going to be created that much to matter anyway.
The issue is that the mutexes they have are also typedefs, and there the additional pointer indirection will have a performance impact.
I'm tempted to use, if I can't resolve this issue, the operating system API, with user-space interlocked operations to check when locks don't need to call WaitForSingleObject etc.
It's simple enough on Windows, but I also need it to build on Linux and there I'm not sure what threading API is provided by the OS, to bypass pthreads.
"But who prays for Satan? Who, in eighteen centuries, has had the common humanity to pray for the one sinner that needed it most?" --Mark Twain

~~~~~~~~~~~~~~~Looking for a high-performance, easy to use, and lightweight math library? http://www.cmldev.net/ (note: I'm not associated with that project; just a user)
How about creating a new struct pthread_t_wrapper, which would be forward-declared in your interface and defined in your implementation to hold a pthread_t? There's no runtime cost, but you'd have to change all pthread API call sites to use the wrapper's member.
E8 17 00 42 CE DC D2 DC E4 EA C4 40 CA DA C2 D8 CC 40 CA D0 E8 40E0 CA CA 96 5B B0 16 50 D7 D4 02 B2 02 86 E2 CD 21 58 48 79 F2 C3
Quote:Original post by Jan Wassenberg
How about creating a new struct pthread_t_wrapper, which would be forward-declared in your interface and defined in your implementation to hold a pthread_t? There's no runtime cost, but you'd have to change all pthread API call sites to use the wrapper's member.


Or you could re-implement the interface in the wrapper by delegation. That should get optimized out too, in normal circumstances anyway.
Just include pthread.h in myclass.h. The days of obsessively minimizing header inclusions to speed up compilation are pretty much over... our hard disks are a lot faster these days.

Obsessively minimizing header inclusions to prevent circular inclusion thanks to C/C++'s quaintly broken linker model, of course, is still de rigueur. But that doesn't apply to API includes.

This topic is closed to new replies.

Advertisement