Interfaces and their implementations, is this code legal/correct?

S

SenderX

I am a basically a life-long Win32 C programmer specializing in high-end
winsock servers.

Before I dive into portable C++ programming, I wanted to code up an example
of what I thought would be a workable Collection template library. The idea
is to design API's that operate on interfaces, and provide
multi-implementations to that "single" API. C++ Interfaces and
Implementations, seems to behave like Win32 COM objects?



Please look over the following code sketch, and point out ALL of the flaws
that render it non-portable and/or non-std:

;)


Interfaces.cpp
--------------------


#ifndef NULL
# define NULL 0
#endif


// Collection objects
namespace Collections
{


// Forwards
template< typename T > class ICollection;
template< typename T > class IIterator;
template< typename T > class TNode;
template< typename T > class TStack;




// *** Interfaces ***


// The collection interface
template< typename T >

class ICollection
{

public:

virtual ~ICollection() {}

virtual void Push( T const* pObj, int iTimeout = 0 ) = 0;

virtual T* Pop( int iTimeout = 0 ) = 0;

virtual bool Pop( T const* pObj, int iTimeout = 0 ) = 0;

virtual IIterator< T >* RequestIterator() = 0;

virtual void ReleaseIterator( IIterator< T >* pIterator ) = 0;

};


// The iterator interface
template< typename T >

class IIterator
{

public:

// RAII
class CGuard
{

public:

CGuard( IIterator< T >* pIterator ) : m_pIterator( pIterator ) {}

~CGuard() { m_pIterator->GetCollection()->ReleaseIterator(
m_pIterator ); };


public:

IIterator< T >* operator ->() { return m_pIterator; }


private:

IIterator< T >* m_pIterator;

};


public:

virtual ~IIterator() {}

virtual void Next() = 0;

virtual void Prev() = 0;

virtual void Front() = 0;

virtual void Back() = 0;

virtual bool Eof() = 0;

virtual bool Bof() = 0;

virtual T* GetObj() = 0;

virtual ICollection< T >* GetCollection() = 0;

};




// *** Implmentation ***


// The collection node
template< typename T >

class TNode
{

public:

TNode( T const* pObj = NULL ) : m_pNext( NULL ), m_pObj( pObj ) {}


public:

TNode< T >* m_pNext;

T const* m_pObj;

};


// A stack object
template< typename T >

class TStack : public ICollection< T >
{

class CIterator;


private:

friend class CIterator;

class CIterator : public IIterator< T >
{

public:

CIterator( TStack< T >& Stack )
: m_Stack( Stack ),
m_pCurrent( NULL ),
m_pNext( NULL ),
m_pPrev( NULL ) {}


public:

void Next() {}

void Prev() {}

void Front() {}

void Back() {}


bool Eof()
{
return ( m_pCurrent && m_pCurrent->m_pNext ) ? true : false;
}


bool Bof()
{
return ( m_Stack.m_pFront == m_pCurrent ) ? true : false;
}


T* GetObj()
{
return ( m_pCurrent ) ? const_cast< T* >( m_pCurrent->m_pObj ) :
NULL;
}


ICollection< T >* GetCollection() { return &m_Stack; }


private:

TStack< T >& m_Stack;

TNode< T >* m_pCurrent;

TNode< T >* m_pNext;

TNode< T >* m_pPrev;

};


public:

void Push( T const* pObj, int iTimeout = 0 )
{

}


T* Pop( int iTimeout = 0 )
{
return NULL;
}


bool Pop( T const* pObj, int iTimeout = 0 )
{
return false;
}


IIterator< T >* RequestIterator()
{
return new CIterator( *this );
}


void ReleaseIterator( IIterator< T >* pIterator )
{
delete pIterator;
}


private:

TNode< T >* m_pFront;

};


}


// Test object
class CTest
{

public:

CTest() : m_Val1( 0 ) {}

public:

long m_Val1;

};


int main()
{
// Get the ICollection interface
Collections::ICollection< CTest >* pCol
= new Collections::TStack< CTest >;

{
// Get the ICollection's IIterator interface
Collections::IIterator< CTest >::CGuard
pIterator( pCol->RequestIterator() );
}

delete pCol;

return 0;
}


Thank you! =)



P.S.

I will be implementing some very fast, portable, lock-free algo's that will
use the interfaces posted here. If your interested I can post the code when
it is finished.
 
S

SenderX

Uhm, yes: try specific questions instead of "do this work for

I apologize.

* Submit the code to the online Comeau compiler, it's one of the
most standard-conforming around.

Nice. So most compiler portability questions can be skipped, as long as the
code in question compiled without warning in a "strictly conforming"
compiler?

* Use smart-pointers such as std::auto_ptr and boost::shared_ptr
instead of raw C++ pointers.

I was thinking of a templated smart pointer interface, IAutoPtr.

So I can use one reference counted interface, and use it for C pointers and
COM's IUnknown interface.

Does that sound workable?


P.S.

How portable is the _asm keyword and 64-bit integers ( __int64 && long
long ) among popular c++ compilers?

My algos rely on a tiny bit of assembly.
 
A

Alf P. Steinbach

I apologize.



Nice. So most compiler portability questions can be skipped, as long as the
code in question compiled without warning in a "strictly conforming"
compiler?

No, but error- and warning-free compilation with a compiler such as Comeau
is a good indication that the code is practically clean -- if it weren't,
then the chances are near certainty that the compiler would catch something.

But the only way to ensure portability is to (1) design and code for it,
(2) compile with the relevant compilers and (3) test on the relevant systems.

Systematically.



I was thinking of a templated smart pointer interface, IAutoPtr.

So I can use one reference counted interface, and use it for C pointers and
COM's IUnknown interface.

Does that sound workable?

Not immediately. COM reference counting keeps the reference count in each
referred object, ordinary C++ smart-pointers keep the count in the pointer
object or in a shared helper object. Generally, nail => hammer, screw =>
screwdriver, and so on.

How portable is the _asm keyword

Not portable at all.

and 64-bit integers ( __int64 && long long ) among popular c++ compilers?

Not at all, but in C99 (and possibly future C++0x) it's another story.


My algos rely on a tiny bit of assembly.

Wrap it behind a clean C++ interface.
 
S

SenderX

No, but error- and warning-free compilation with a compiler such as Comeau
is a good indication that the code is practically clean

I got a "compile succeeded" using strict mode. So I am currently on the
correct path...

But the only way to ensure portability is to (1) design and code for it,
(2) compile with the relevant compilers and (3) test on the relevant systems.

Systematically.

Yep. ;(


Damn. Any special tricks to get assembly code to compile across different
compilers? ;)

compilers?

Not at all, but in C99 (and possibly future C++0x) it's another story.
Mmmk.



Wrap it behind a clean C++ interface.

That would allow for a single interface that implements varying assembly
code specific to different processors.

// Interfaces

class IAtomic
-- CompareAndSwap(...) = 0;
-- ExchangeAdd(...) = 0;


// Specific processor implmenataions
class CIA32Atomic : public IAtomic
{
...
};


class CIA64Atomic : public IAtomic
{
...
};


class CPowerPCAtomic : public IAtomic
{
...
};


class CPowerPC64Atomic : public IAtomic
{
...
};


class CAMD64Atomic : public IAtomic
{
...
};

My lock-free code has to be portable across compiler, platform, and
processor. I think C++ and this group can help me.

Thanks.
 
A

Alf P. Steinbach

Damn. Any special tricks to get assembly code to compile across different
compilers? ;)

The usual "trick" is to write the assembly in -- assembly.

Then link it into the application.

E.g., parts of the C++ runtime library, for most any compiler, is
implemented that way.
 
G

Greg Comeau

Nice. So most compiler portability questions can be skipped,
as long as the code in question compiled without warning in
a "strictly conforming" compiler?

Use one of the "zillion" non-strictly conforming modes
of Comeau then if that is your concern. :)
 

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

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top