Is C++ really portable?

D

DeMarcus

Let's say we're gonna make a system library and have a class with
two prerequisites.

* It will be used _a_lot_, and therefore need to be really efficient.
* It can have two different implementations. (e.g. Unix/Windows)

I feel stuck. The only solution I've seen so far is using the
design pattern 'abstract factory' that gives me a pointer to a pure
virtual interface (which can have whatever implementation). But that
forces me to make a memory allocation every time I need an instance
of that class! That's all but efficient.

Do I have to live with this? Or do I have to make some kind of

class SystemThing
{
....
private:

strange_unix_var uv;
strange_win_var wv;
}

and then use the appropriate variable in the library implementation?

How is this problem commonly solved?

Thanks
Daniel Marcus
 
R

Rolf Magnus

DeMarcus said:
Let's say we're gonna make a system library and have a class with
two prerequisites.

* It will be used _a_lot_, and therefore need to be really efficient.
* It can have two different implementations. (e.g. Unix/Windows)

I feel stuck. The only solution I've seen so far is using the
design pattern 'abstract factory' that gives me a pointer to a pure
virtual interface (which can have whatever implementation). But that
forces me to make a memory allocation every time I need an instance
of that class! That's all but efficient.

That depends on how efficient you need it to be. Each std::string will
also need to allocate its memory, and many programs also use "_a_lot_"
of strings.
Anyway, I don't see why you would need a factory here. A factory is used
to decide which class to instantiate at runtime. But an instance of
your program is unlikely to migrate from a unix system to a windows
system while running, isn't it? So why don't you just use #ifdef to
select the parts of the code based on the system your program is
compiled for?
 
D

DeMarcus

Rolf said:
DeMarcus wrote:




That depends on how efficient you need it to be. Each std::string will
also need to allocate its memory, and many programs also use "_a_lot_"
of strings.
Anyway, I don't see why you would need a factory here. A factory is used
to decide which class to instantiate at runtime. But an instance of
your program is unlikely to migrate from a unix system to a windows
system while running, isn't it? So why don't you just use #ifdef to
select the parts of the code based on the system your program is
compiled for?

I tried to keep away from non-C++ things, but to make it a little more
clear I'm in a position where a very same application can use two
different types of thread libraries (pthread and sproc) which are not
compatible. This means I would really like to be able to wrap and
extract that library so I can load it dynamically without the need to
recompile the application.

I'm stuck to pointers, ain't I?
 
J

Jakob Bieling

I tried to keep away from non-C++ things, but to make it a little more
clear I'm in a position where a very same application can use two
different types of thread libraries (pthread and sproc) which are not
compatible. This means I would really like to be able to wrap and
extract that library so I can load it dynamically without the need to
recompile the application.

I do not really understand why you want to be able to use two different
libraries, unless you are talking about two different libs for two different
OS's. In the latter case, you do not need any pointers, as Rolf Magnus
already pointed out. Maybe it helps to create a common interface that
forwards the calls to the right library. #defines will control to which
library the functions will forward the calls. This way you hide all the
#define acrobatics from the actual user code -- not neccessary, but maybe it
looks nicer :)

hth
 
E

E. Robert Tisdale

DeMarcus said:
Do I have to live with this? Or do I have to make some kind of

class SystemThing {
...
private: #ifdef unix
strange_unix_var uv; #else // must be windows
strange_win_var wv; #endif // unix
};

and then use the appropriate variable in the library implementation?

How is this problem commonly solved?
 
D

DeMarcus

Jakob said:
I do not really understand why you want to be able to use two different
libraries, unless you are talking about two different libs for two different
OS's. In the latter case, you do not need any pointers, as Rolf Magnus
already pointed out. Maybe it helps to create a common interface that
forwards the calls to the right library. #defines will control to which
library the functions will forward the calls. This way you hide all the
#define acrobatics from the actual user code -- not neccessary, but maybe it
looks nicer :)

To make a even more concrete example I want to make a class like this

class MyThread
{
public:
void start();
...

private:

pthread_t threadID;

};

Then I want to use that class in the application, but now suddenly the
application has to know what pthread_t is, and even worse, now I can
definately not link in any implementation of MyThread using anything
else than pthread_t.

I could always do something like this

class MyThread
{
public:
void start();
...

private:

char variableStore[ 4711 ];
}

and then in the implementation do (pthread_t*)variableStore = whatever;
or (sproc_t*)variableStore = whatever;
But that's DIRTY DIRTY DIRTY!
 
A

Andre Kostur

Jakob said:
I do not really understand why you want to be able to use two
different
libraries, unless you are talking about two different libs for two
different OS's. In the latter case, you do not need any pointers, as
Rolf Magnus already pointed out. Maybe it helps to create a common
interface that forwards the calls to the right library. #defines will
control to which library the functions will forward the calls. This
way you hide all the #define acrobatics from the actual user code --
not neccessary, but maybe it looks nicer :)

To make a even more concrete example I want to make a class like this

class MyThread
{
public:
void start();
...

private:

pthread_t threadID;

};

Then I want to use that class in the application, but now suddenly the
application has to know what pthread_t is, and even worse, now I can
definately not link in any implementation of MyThread using anything
else than pthread_t.

I could always do something like this

class MyThread
{
public:
void start();
...

private:

char variableStore[ 4711 ];
}

and then in the implementation do (pthread_t*)variableStore =
whatever; or (sproc_t*)variableStore = whatever;
But that's DIRTY DIRTY DIRTY!

Or use some other 3rd party libraries (such as ACE, perhaps
Boost::Thread) which will abstract out the threading details.
 
J

Jakob Bieling

To make a even more concrete example I want to make a class like this

class MyThread
{
public:
void start();
...

private:

pthread_t threadID;

};

Then I want to use that class in the application, but now suddenly the
application has to know what pthread_t is, and even worse, now I can
definately not link in any implementation of MyThread using anything
else than pthread_t.


Ah, a bit more tricky. But still, you will probably be able to use
#defines:

#ifdef _WINDOWS
#define pthread_t HANDLE
#else
#define pthread_t int // or whatever
#endif

Then the implementation will also use #defines to commensate the
difference between the two libraries.

hth
 
S

SenderX

* It will be used _a_lot_, and therefore need to be really efficient.
* It can have two different implementations. (e.g. Unix/Windows)

Here is some crude pseudo-code for portable a semaphore:





/* win_sema.h
-----------------*/

namespace win32
{

class CSema
{

public:

// Sema common interface

private:

HANDLE m_Sema;

};

}

namespace os
{
typedef win32::CSema CSema;
}





/* linux_sema.h
-----------------*/

namespace linux32
{

class CSema
{

public:

// Sema common interface

private:

sem_t m_hSema;

};

}

namespace os
{
typedef linux32::CSema CSema;
}





/* portable_sema.h
----------------------*/

#ifdef USE_WIN32

#include "win_sema.h"

#else

#include "linux_sema.h"

#endif





/* main.c
-------------------------*/

#define USE_WIN32

#include "portable_sema.h"

int main()
{
os::CSema PortableSema;

return 0;
}




Can you see what I did here?
 
S

SenderX

Can you see what I did here?

If you still confused I can post code that will compile. Its OT because it
actually has the os specific calls needed to create and implement the
semaphore.
 
S

Stephen Waits

DeMarcus said:
class MyThread
{
public:
void start();
...

private:

pthread_t threadID;

};


We do this in a way that many might think ugly, but it's quite
straightforward, easy to maintain, and does the job just fine.


#if defined(PLATFORM_PSP)
# include "psp/thread_impl_psp.h"
#elif defined(PLATFORM_PS2)
# include "ps2/thread_impl_ps2.h"
#else
# include "undef/thread_impl_undef.h"
#endif

class MyThread
{
public:
...
private:
MyThreadImpl impl;
};


I'm sure you get the idea. It's not very C++-ish as you seem to desire.

FWIW we have a cross platform SDK setup entirely like this building on a
variety of platforms, and even more compilers.

--Steve
 
J

Jeff Schwab

DeMarcus said:
Let's say we're gonna make a system library and have a class with
two prerequisites.

* It will be used _a_lot_, and therefore need to be really efficient.
* It can have two different implementations. (e.g. Unix/Windows)

I feel stuck. The only solution I've seen so far is using the
design pattern 'abstract factory' that gives me a pointer to a pure
virtual interface (which can have whatever implementation). But that
forces me to make a memory allocation every time I need an instance
of that class! That's all but efficient.

Do I have to live with this? Or do I have to make some kind of

class SystemThing
{
...
private:

strange_unix_var uv;
strange_win_var wv;
}

and then use the appropriate variable in the library implementation?

How is this problem commonly solved?

Write a header file to define the interface your library should have.
For each platform, implement the interface in a separate file. Choose
the implementation at link time. For example, if you control your
builds with makefiles and compile with g++, put conditional logic in the
makefiles (or in shell scripts) to define platform-specific arguments to
the compiler's -I, -L, and -R arguments. Wherever there is commonality
between the platform-specific implementations, abstract it into a
separate module. This approach avoids the unfortunate situation in
which you have different implementations in a single file, and have to
pick out the commonality using the preprocessor.
 
J

Jeff Schwab

Jeff said:
Write a header file to define the interface your library should have.
For each platform, implement the interface in a separate file. Choose
the implementation at link time.

Excuse me, that should say "build time," since details of compilation
may be platform-specific.
 
D

DeMarcus

Thank all of you for all your answers, I really
appreciate it. But there's one very imporatant
thing that I might have been a little vague about,
and that is the importance of not having to
recompile the application because of a library
change. Therefore #ifdef won't do.

Suppose you sell your application to someone and
this guy in turn buys a plugin to it from a third
party vendor, where this plugin only supports
"strangeThread" but not the apps default pthread.
Then it would be neat to just send him a new
strangeThread.so or .dll to put in a specific
directory and suddenly it works.

It's feasible with the design patterns 'abstract
factory' or 'bridge', but both of them result in
an overhead with pointer referencing and memory
allocation. I just wanted that C++ could do it
anyway, but the only solution I can see right now
is this solution

class MyThread
{
public:
void start();
...

private:

char varStore[ BIG_ENOUGH_TO_HOLD_THE_BIGGEST_
CLASS_DECLARATION_OF_ALL_POSSIBLE_IMPLEMENTATIONS ];
}

The header above could be used by anyone compiling
the application or third party plugins.

// Here's two different examples of implementation
void MyThread::start()
{
pthread_create( (pthread_t*)varStore, ... );
}

void MyThread::start()
{
strange_thread_create( (strange_thread_t*)varStore, ... );
}

If I do this dirty implementation then I can compile
the application once and hope and pray nobody makes
a thread library with a bigger class declaration than
BIG_ENOUGH_... that the application was compiled with.

My hope here was that the C++ compiler could take care
of that somehow, but I realize it's almost impossible.
 
C

Cy Edmunds

DeMarcus said:
Let's say we're gonna make a system library and have a class with
two prerequisites.

* It will be used _a_lot_, and therefore need to be really efficient.
* It can have two different implementations. (e.g. Unix/Windows)

I feel stuck. The only solution I've seen so far is using the
design pattern 'abstract factory' that gives me a pointer to a pure
virtual interface (which can have whatever implementation). But that
forces me to make a memory allocation every time I need an instance
of that class! That's all but efficient.

Do I have to live with this? Or do I have to make some kind of

class SystemThing
{
...
private:

strange_unix_var uv;
strange_win_var wv;
}

and then use the appropriate variable in the library implementation?

How is this problem commonly solved?

Thanks
Daniel Marcus


I write a lot of scientific/engineering kind of code which must run on
Windows and Unix. When I have to do something specific to an operating
system (e.g. load a dll/so by name) I try to localize the operating system
dependence to a single file. Polymorphism seems to be very useful here.

The other thing I do is to use Python for "glue" code. It ports across
operating systems pretty much seamlessly. It is too slow for number
crunching but that part of te code can be done in C or C++. This may not be
the NG to plug Python, but it is a joy to use for anything that isn't
time-critical.
 
S

Siemel Naran

DeMarcus said:
Thank all of you for all your answers, I really
appreciate it. But there's one very imporatant
thing that I might have been a little vague about,
and that is the importance of not having to
recompile the application because of a library
change. Therefore #ifdef won't do.

An ifdef in the cpp file will work. But then you're using the pointer to
implementation idea, so you pay the cost of a non-inline function call.
Suppose you sell your application to someone and
this guy in turn buys a plugin to it from a third
party vendor, where this plugin only supports
"strangeThread" but not the apps default pthread.
Then it would be neat to just send him a new
strangeThread.so or .dll to put in a specific
directory and suddenly it works.

It's feasible with the design patterns 'abstract
factory' or 'bridge', but both of them result in
an overhead with pointer referencing and memory
allocation. I just wanted that C++ could do it
anyway, but the only solution I can see right now
is this solution

Have you actually measured it to determine it is a bottleneck? How many
MyThread objects do you create? How does the time spent in creating the
DerivedMyThread object and calling its virtual functions compare to the time
spent in the rest of the application? It might not be anything at all.
class MyThread
{
public:
void start();
...

private:

char varStore[ BIG_ENOUGH_TO_HOLD_THE_BIGGEST_
CLASS_DECLARATION_OF_ALL_POSSIBLE_IMPLEMENTATIONS ];
}

The above strikes me as a valid use of reinterpret_cast in general, but only
a last resort if profiling suggests it. Pay attention to alignment issues
though. The char type usually has alignment 1, whereas pthread_t may have
alignment 4. To solve, there is no perfect way, but you can create a union
of all fundamental types along with your varStore[...] variable. The
union's size will be at least varStore[...] and will be properly aligned.
The header above could be used by anyone compiling
the application or third party plugins.

// Here's two different examples of implementation
void MyThread::start()
{
pthread_create( (pthread_t*)varStore, ... );
}

void MyThread::start()
{
strange_thread_create( (strange_thread_t*)varStore, ... );
}

How does the cost of a factory compare to the cost of pthread_create?

To make using the factory even faster you can overload MyThread::eek:perator
new and use pool allocation. But how many threads do you allocate anyway?
If I do this dirty implementation then I can compile
the application once and hope and pray nobody makes
a thread library with a bigger class declaration than
BIG_ENOUGH_... that the application was compiled with.

You don't have to pray for this. You can use a compile time assert to
assert that sizeof(actual_thread) <= sizeof(varStore). These compile time
asserts work by creating an array of size zero if the condition is false,
and such a thing fails compilation.
My hope here was that the C++ compiler could take care
of that somehow, but I realize it's almost impossible.

Not sure if any compiler can do what you're asking for.
 
G

Gianni Mariani

DeMarcus said:
Thank all of you for all your answers, I really
appreciate it. But there's one very imporatant
thing that I might have been a little vague about,
and that is the importance of not having to
recompile the application because of a library
change. Therefore #ifdef won't do.

Suppose you sell your application to someone and
this guy in turn buys a plugin to it from a third
party vendor, where this plugin only supports
"strangeThread" but not the apps default pthread.
Then it would be neat to just send him a new
strangeThread.so or .dll to put in a specific
directory and suddenly it works.

It's feasible with the design patterns 'abstract
factory' or 'bridge', but both of them result in
an overhead with pointer referencing and memory
allocation. I just wanted that C++ could do it
anyway, but the only solution I can see right now
is this solution

class MyThread
{
public:
void start();
...

private:

char varStore[ BIG_ENOUGH_TO_HOLD_THE_BIGGEST_
CLASS_DECLARATION_OF_ALL_POSSIBLE_IMPLEMENTATIONS ];
}

don't use 'char' - use somthing with the largest alignment
of any of the implemntations you require.

Also, on some systems, a virtual function call is just as fast
as a regular call.

Finally, one possibility is to go ahead and use a factory
but make it so the factory puts the function addresses
directly in the structure.

Somthing like:

class MyThread
{
friend class ThreadImpl;

void ( * StartFuncPtr )( MyThread * );
void ( * CleanupFuncPtr )( MyThread * );

long long var_store[ NUM_BIG_ENUFF ];

public:

inline Start()
{
StartFuncPtr( this );
}

virtual ~MyThread()
{
CleanupFuncPtr( this );
}

MyThread()
{
// factory initialize
ThreadFactoryInitializeNew( this );
}

// application overrides this function
virtual DoStuff() = 0;
};

The header above could be used by anyone compiling
the application or third party plugins.

// Here's two different examples of implementation
void MyThread::start()
{
pthread_create( (pthread_t*)varStore, ... );
}

void MyThread::start()
{
strange_thread_create( (strange_thread_t*)varStore, ... );
}

If I do this dirty implementation then I can compile
the application once and hope and pray nobody makes
a thread library with a bigger class declaration than
BIG_ENOUGH_... that the application was compiled with.

My hope here was that the C++ compiler could take care
of that somehow, but I realize it's almost impossible.

It's very possible. You can also make it very safe by making the ugly
nasty stuff private so that nothing else messes with the bits that they
should not.
 
K

Krzysztof Zelechowski

Uzytkownik "DeMarcus said:
Suppose you sell your application to someone and
this guy in turn buys a plugin to it from a third
party vendor, where this plugin only supports
"strangeThread" but not the apps default pthread.
Then it would be neat to just send him a new
strangeThread.so or .dll to put in a specific
directory and suddenly it works.
I think the plugin must be appropriate for your application and not the
opposite.
 
D

DeMarcus

Have you actually measured it to determine it is a bottleneck? How many
MyThread objects do you create? How does the time spent in creating the
DerivedMyThread object and calling its virtual functions compare to the time
spent in the rest of the application? It might not be anything at all.

Maybe you're right here, I may not lose much. I know that one shall
never begin with optimizing, but in this case where it is the structure
of the program it feels like if I do this wrong there will be no space
for optimizations later.

I was just worried about all the mutexes that will go from
myMutex.lock();
to
myMutex->lock();
(virtual)

I hope it won't be a too big performance hit.
To make using the factory even faster you can overload MyThread::eek:perator
new and use pool allocation. But how many threads do you allocate anyway?

I really like that pool allocation idea! That's an area where I want to
improve my programming skills. Do you know where to find exhaustive
information about creating rock solid buffer pools?

You don't have to pray for this. You can use a compile time assert to
assert that sizeof(actual_thread) <= sizeof(varStore). These compile time
asserts work by creating an array of size zero if the condition is false,
and such a thing fails compilation.

That's something I didn't know about. Do you know where I can read
more about it?
 
D

DeMarcus

Krzysztof said:
I think the plugin must be appropriate for your application and not the
opposite.

When you're Big Buck Inc. yes. But I'm not. ;) Therefore I will be the
only one losing if the application doesn't work as the customer
expected. If he goes to Big Buck Third Party Plugin Manufacturer Inc.
and ask them to change their plugins they will say they wait until my
app is working properly.

But you're right. This is actually a catch22 situation that probably
will never happen. The thing is that I personaly want to use pthreads
meanwhile many companies in the business use an older variant of
threads, so I need a simple way to deal with both.
 

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,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top