Sign in to follow this  
Prune

How to forward declare pthread_t when that is a typedef

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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... :(

Share this post


Link to post
Share on other sites
If you're getting redefinition errors then it's obviously already defined for you, so why do you need to forward declare it?

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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 file
class 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 file
class 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
I'm not sure what "re-implement the interface in the wrapper by delegation" means.

As for minimizing includes: Intel's compiler is spectacularly slow, actually, in building any moderately sized program, especially with optimizations maxed out. And that's on a Core i7.

I don't do precompiled headers because I modify headers often.

Share this post


Link to post
Share on other sites
Quote:
Original post by Prune
I'm not sure what "re-implement the interface in the wrapper by delegation" means.

As for minimizing includes: Intel's compiler is spectacularly slow, actually, in building any moderately sized program, especially with optimizations maxed out. And that's on a Core i7.

I don't do precompiled headers because I modify headers often.


Then only put those headers in the PCH which are rarely or never changed(Such as the pthread.h) instead of the headers you modify all the time. I'm agreeing with Sneftel here that you're over stressing on the minimizing the inclusion.

That also makes me wonder: Why are you using all the optimizations during the development process? Debug builds are there for a reason. Sure, if you want to test certain situations for speed, then yes, you will have to make a release build, but I doubt you're going to need to do everything in a release build during development.

Toolmaker

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this