Commit 7f46cab3 authored by Tomáš Oberhuber's avatar Tomáš Oberhuber
Browse files

Implementing shared pointers to tnlArray.

parent eeca9e21
Loading
Loading
Loading
Loading
+105 −58
Original line number Diff line number Diff line
@@ -27,6 +27,10 @@ class tnlHost;
template< typename Element, typename Device, typename Index >
class tnlSharedArray;

/****
 * Array handles memory allocation and sharing of the same data between more Arrays.
 * 
 */
template< typename Element,
          typename Device = tnlHost,
          typename Index = int >
@@ -39,9 +43,19 @@ class tnlArray : public virtual tnlObject
      typedef Index IndexType;
      typedef tnlArray< Element, tnlHost, Index > HostType;
      typedef tnlArray< Element, tnlCuda, Index > CudaType;
      typedef tnlArray< Element, Device, Index > ThisType;
      
      tnlArray();
      
      tnlArray( const IndexType& size );
      
      tnlArray( Element* data,
                const IndexType& size );

      tnlArray( tnlArray< Element, Device, Index >& array,
                const IndexType& begin = 0,
                const IndexType& size = 0 );

      static tnlString getType();

      tnlString getTypeVirtual() const;
@@ -50,11 +64,26 @@ class tnlArray : public virtual tnlObject

      virtual tnlString getSerializationTypeVirtual() const;

      /****
       * This sets size of the array. If the array shares data with other arrays
       * these data are released. If the current data are not shared and the current
       * size is the same as the new one, nothing happens.
       */
      bool setSize( Index size );

      template< typename Array >
      bool setLike( const Array& array );

      void bind( Element* _data,
                 const Index _size );

      void bind( tnlArray< Element, Device, Index >& array,
                 const IndexType& begin = 0,
                 const IndexType& size = 0 );

      template< int Size >
      void bind( tnlStaticArray< Size, Element >& array );

      void swap( tnlArray< Element, Device, Index >& array );

      void reset();
@@ -110,19 +139,37 @@ class tnlArray : public virtual tnlObject
      //! Method for loading the object from a file as a binary data.
      bool load( tnlFile& file );
      
   bool save( const tnlString& fileName ) const;
      using tnlObject::load;

   bool load( const tnlString& fileName );
      using tnlObject::save;

      ~tnlArray();

   protected:
      
   //!Number of allocated elements
   Index size;
      void releaseData() const;

      //!Number of elements in array
      mutable Index size;

      //! Pointer to data
      mutable Element* data;

   //! Pointer to allocated data
   Element* data;
      /****
       * Pointer to the originally allocated data. They might differ if one 
       * long array is partitioned into more shorter arrays. Each of them
       * must know the pointer on allocated data because the last one must
       * deallocate the array. If outer data (not allocated by TNL) are bind
       * then this pointer is zero since no deallocation is necessary.
       */
      mutable Element* allocationPointer;

      /****
       * Counter of objects sharing this array or some parts of it. The reference counter is
       * allocated after first sharing of the data between more arrays. This is to avoid
       * unnecessary dynamic memory allocation.
       */
      mutable int* referenceCounter;
};

template< typename Element, typename Device, typename Index >
+215 −50
Original line number Diff line number Diff line
@@ -26,20 +26,87 @@
#include <core/arrays/tnlArrayOperations.h>
#include <core/arrays/tnlArrayIO.h>

#include "tnlArray.h"

using namespace std;

template< typename Element,
           typename Device,
           typename Index >
tnlArray< Element, Device, Index > :: tnlArray()
: size( 0 ), data( 0 )
tnlArray< Element, Device, Index >::
tnlArray()
: size( 0 ),
  data( 0 ),
  allocationPointer( 0 ),
  referenceCounter( 0 )
{
};

template< typename Element,
           typename Device,
           typename Index >
tnlString tnlArray< Element, Device, Index > :: getType()
tnlArray< Element, Device, Index >::
tnlArray( const IndexType& size )
: size( 0 ),
  data( 0 ),
  allocationPointer( 0 ),
  referenceCounter( 0 )
{
   this->setSize( size );
}

template< typename Element,
           typename Device,
           typename Index >
tnlArray< Element, Device, Index >::
tnlArray( Element* data,
          const IndexType& size )
: size( size ),
  data( data ),
  allocationPointer( 0 ),
  referenceCounter( 0 )
{   
}

template< typename Element,
           typename Device,
           typename Index >
tnlArray< Element, Device, Index >::
tnlArray( tnlArray< Element, Device, Index >& array,
          const IndexType& begin,
          const IndexType& size )
: size( size ),
  data( &array.getData()[ begin ] ),
  allocationPointer( array.allocationPointer ),
  referenceCounter( 0 )
{
   tnlAssert( begin < array.getSize(),
              std::cerr << " begin = " << begin << " array.getSize() = " << array.getSize() );
   tnlAssert( begin + size  < array.getSize(),
              std::cerr << " begin = " << begin << " size = " << size <<  " array.getSize() = " << array.getSize() );
   if( ! this->size )
      this->size = array.getSize() - begin;
   if( array.allocationPointer )
   {
      if( array.referenceCounter )
      {
         this->referenceCounter = array.referenceCounter;
         *this->referenceCounter++;
      }
      else
      {
         this->referenceCounter = array.referenceCounter = new int;
         *this->referenceCounter = 2;            
      }
   }   
}

template< typename Element,
          typename Device,
          typename Index >
tnlString 
tnlArray< Element, Device, Index >::
getType()
{
   return tnlString( "tnlArray< " ) +
                     ::getType< Element >() + ", " +
@@ -51,7 +118,9 @@ tnlString tnlArray< Element, Device, Index > :: getType()
template< typename Element,
           typename Device,
           typename Index >
tnlString tnlArray< Element, Device, Index > :: getTypeVirtual() const
tnlString 
tnlArray< Element, Device, Index >::
getTypeVirtual() const
{
   return this->getType();
};
@@ -59,7 +128,9 @@ tnlString tnlArray< Element, Device, Index > :: getTypeVirtual() const
template< typename Element,
           typename Device,
           typename Index >
tnlString tnlArray< Element, Device, Index > :: getSerializationType()
tnlString
tnlArray< Element, Device, Index >::
getSerializationType()
{
   return HostType::getType();
};
@@ -67,7 +138,9 @@ tnlString tnlArray< Element, Device, Index > :: getSerializationType()
template< typename Element,
           typename Device,
           typename Index >
tnlString tnlArray< Element, Device, Index > :: getSerializationTypeVirtual() const
tnlString 
tnlArray< Element, Device, Index >::
getSerializationTypeVirtual() const
{
   return this->getSerializationType();
};
@@ -75,20 +148,43 @@ tnlString tnlArray< Element, Device, Index > :: getSerializationTypeVirtual() co
template< typename Element,
           typename Device,
           typename Index >
bool tnlArray< Element, Device, Index > :: setSize( const Index size )
void
tnlArray< Element, Device, Index >::
releaseData() const
{
   tnlAssert( size >= 0,
              cerr << "You try to set size of tnlArray to negative value."
                   << "New size: " << size << endl );
   if( this->size == size ) return true;
   if( this->data )
   if( this->referenceCounter )
   {
      tnlArrayOperations< Device >::freeMemory( this->data );
      if( --*this->referenceCounter == 0 )
      {
         tnlArrayOperations< Device >::freeMemory( this->allocationPointer );
         delete this->referenceCounter;
      }
   }
   else
      if( allocationPointer )
         tnlArrayOperations< Device >::freeMemory( this->allocationPointer );
   this->allocationPointer = 0;
   this->data = 0;
   this->size = 0;
   this->referenceCounter = 0;
}

template< typename Element,
           typename Device,
           typename Index >
bool
tnlArray< Element, Device, Index >::
setSize( const Index size )
{
   tnlAssert( size >= 0,
              cerr << "You try to set size of tnlArray to negative value."
                   << "New size: " << size << endl );
   if( this->size == size && allocationPointer && ! referenceCounter ) return true;
   this->releaseData();
   tnlArrayOperations< Device >::allocateMemory( this->allocationPointer, size );
   this->data = this->allocationPointer;
   this->size = size;
   tnlArrayOperations< Device >::allocateMemory( this->data, size );
   if( ! this->data )
   if( ! this->allocationPointer )
   {
      cerr << "I am not able to allocate new array with size "
           << ( double ) this->size * sizeof( ElementType ) / 1.0e9 << " GB." << endl;
@@ -102,7 +198,9 @@ template< typename Element,
           typename Device,
           typename Index >
   template< typename Array >
bool tnlArray< Element, Device, Index > :: setLike( const Array& array )
bool
tnlArray< Element, Device, Index >::
setLike( const Array& array )
{
   tnlAssert( array. getSize() >= 0,
              cerr << "You try to set size of tnlArray to negative value."
@@ -113,27 +211,96 @@ bool tnlArray< Element, Device, Index > :: setLike( const Array& array )
template< typename Element,
           typename Device,
           typename Index >
void tnlArray< Element, Device, Index > :: swap( tnlArray< Element, Device, Index >& array )
void 
tnlArray< Element, Device, Index >::
bind( Element* data,
      const Index size )
{
   this->releaseData();
   this->data = data;
   this->size = size;   
}

template< typename Element,
           typename Device,
           typename Index >
void
tnlArray< Element, Device, Index >::
bind( tnlArray< Element, Device, Index >& array,
      const IndexType& begin,
      const IndexType& size )
{
   tnlAssert( begin < array.getSize(),
              std::cerr << " begin = " << begin << " array.getSize() = " << array.getSize() );
   tnlAssert( begin + size  < array.getSize(),
              std::cerr << " begin = " << begin << " size = " << size <<  " array.getSize() = " << array.getSize() );
   
   this->releaseData();
   if( size )
      this->size = size;
   else
      this->size = array.getSize() - begin;
   this->data = &array.getData()[ begin ];
   this->allocationPointer = array.allocationPointer;
   if( array.allocationPointer )
   {
      if( array.referenceCounter )
      {
         this->referenceCounter = array.referenceCounter;
         *this->referenceCounter++;
      }
      else
      {
         this->referenceCounter = array.referenceCounter = new int;
         *this->referenceCounter = 2;            
      }
   }   
}

template< typename Element,
           typename Device,
           typename Index >
   template< int Size >
void
tnlArray< Element, Device, Index >::
bind( tnlStaticArray< Size, Element >& array )
{
   this->releaseData();
   this->size = Size;
   this->data = array.getData();
}


template< typename Element,
          typename Device,
          typename Index >
void 
tnlArray< Element, Device, Index >::
swap( tnlArray< Element, Device, Index >& array )
{
   ::swap( this->size, array.size );
   ::swap( this->data, array.data );
   ::swap( this->allocationPointer, array.allocationPointer );
   ::swap( this->referenceCounter, array.referenceCounter );
};

template< typename Element,
          typename Device,
          typename Index >
void tnlArray< Element, Device, Index > :: reset()
void 
tnlArray< Element, Device, Index >::
reset()
{
   this->size = 0;
   tnlArrayOperations< Device >::freeMemory( this->data );
   this->data = 0;
   this->releaseData();
};

template< typename Element,
          typename Device,
          typename Index >
__cuda_callable__
Index tnlArray< Element, Device, Index > :: getSize() const
Index 
tnlArray< Element, Device, Index >::
getSize() const
{
   return this -> size;
}
@@ -141,7 +308,9 @@ Index tnlArray< Element, Device, Index > :: getSize() const
template< typename Element,
           typename Device,
           typename Index >
void tnlArray< Element, Device, Index > :: setElement( const Index& i, const Element& x )
void
tnlArray< Element, Device, Index >::
setElement( const Index& i, const Element& x )
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for setElement method in tnlArray "
@@ -153,7 +322,9 @@ void tnlArray< Element, Device, Index > :: setElement( const Index& i, const Ele
template< typename Element,
           typename Device,
           typename Index >
Element tnlArray< Element, Device, Index > :: getElement( const Index& i ) const
Element
tnlArray< Element, Device, Index >::
getElement( const Index& i ) const
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for getElement method in tnlArray "
@@ -166,7 +337,9 @@ template< typename Element,
          typename Device,
          typename Index >
__cuda_callable__
inline Element& tnlArray< Element, Device, Index > :: operator[] ( const Index& i )
inline Element&
tnlArray< Element, Device, Index >::
operator[] ( const Index& i )
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for operator[] in tnlArray "
@@ -179,7 +352,9 @@ template< typename Element,
           typename Device,
           typename Index >
__cuda_callable__
inline const Element& tnlArray< Element, Device, Index > :: operator[] ( const Index& i ) const
inline const Element& 
tnlArray< Element, Device, Index >::
operator[] ( const Index& i ) const
{
   tnlAssert( 0 <= i && i < this -> getSize(),
              cerr << "Wrong index for operator[] in tnlArray "
@@ -192,7 +367,8 @@ template< typename Element,
           typename Device,
           typename Index >
tnlArray< Element, Device, Index >&
   tnlArray< Element, Device, Index > :: operator = ( const tnlArray< Element, Device, Index >& array )
tnlArray< Element, Device, Index >::
operator = ( const tnlArray< Element, Device, Index >& array )
{
   tnlAssert( array. getSize() == this -> getSize(),
           cerr << "Source size: " << array. getSize() << endl
@@ -212,7 +388,8 @@ template< typename Element,
           typename Index >
   template< typename Array >
tnlArray< Element, Device, Index >&
   tnlArray< Element, Device, Index > :: operator = ( const Array& array )
tnlArray< Element, Device, Index >::
operator = ( const Array& array )
{
   tnlAssert( array. getSize() == this -> getSize(),
           cerr << "Source size: " << array. getSize() << endl
@@ -232,7 +409,9 @@ template< typename Element,
          typename Device,
          typename Index >
   template< typename Array >
bool tnlArray< Element, Device, Index > :: operator == ( const Array& array ) const
bool
tnlArray< Element, Device, Index >::
operator == ( const Array& array ) const
{
   if( array. getSize() != this -> getSize() )
      return false;
@@ -327,7 +506,9 @@ bool tnlArray< Element, Device, Index > :: save( tnlFile& file ) const
template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: load( tnlFile& file )
bool
tnlArray< Element, Device, Index >::
load( tnlFile& file )
{
   if( ! tnlObject :: load( file ) )
      return false;
@@ -360,26 +541,10 @@ bool tnlArray< Element, Device, Index > :: load( tnlFile& file )
template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: save( const tnlString& fileName ) const
{
   return tnlObject :: save( fileName );
}

template< typename Element,
          typename Device,
          typename Index >
bool tnlArray< Element, Device, Index > :: load( const tnlString& fileName )
{
   return tnlObject :: load( fileName );
}

template< typename Element,
          typename Device,
          typename Index >
tnlArray< Element, Device, Index > :: ~tnlArray()
tnlArray< Element, Device, Index >::
~tnlArray()
{
   if( this -> data )
      tnlArrayOperations< Device > :: freeMemory( this -> data );
   this->releaseData();
}

template< typename Element, typename Device, typename Index >
+34 −4
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ class tnlArrayTester : public CppUnit :: TestCase

   typedef tnlArrayTester< ElementType, Device, IndexType > ArrayTester;
   typedef CppUnit :: TestCaller< ArrayTester > TestCaller;
   typedef tnlArray< ElementType, Device, IndexType > Array;

   tnlArrayTester(){};

@@ -66,6 +67,7 @@ class tnlArrayTester : public CppUnit :: TestCase
      CppUnit :: TestResult result;
      suiteOfTests -> addTest( new TestCaller( "testConstructorDestructor", &ArrayTester::testConstructorDestructor ) );
      suiteOfTests -> addTest( new TestCaller( "testSetSize", &ArrayTester::testSetSize ) );
      suiteOfTests -> addTest( new TestCaller( "testBind", &ArrayTester::testBind ) );
      suiteOfTests -> addTest( new TestCaller( "testSetGetElement", &ArrayTester::testSetGetElement ) );
      suiteOfTests -> addTest( new TestCaller( "testComparisonOperator", &ArrayTester::testComparisonOperator ) );
      suiteOfTests -> addTest( new TestCaller( "testAssignmentOperator", &ArrayTester::testAssignmentOperator ) );
@@ -79,14 +81,42 @@ class tnlArrayTester : public CppUnit :: TestCase

   void testConstructorDestructor()
   {
      tnlArray< ElementType, Device, IndexType > u;
      Array u;
      Array v( 10 );
      CPPUNIT_ASSERT( v.getSize() == 10 );
   }

   void testSetSize()
   {
      tnlArray< ElementType, Device, IndexType > u, v;
      Array u, v;
      u.setSize( 10 );
      v.setSize( 10 );
      CPPUNIT_ASSERT( u.getSize() == 10 );
      CPPUNIT_ASSERT( v.getSize() == 10 );
   }
   
   void testBind()
   {
      Array u( 10 ), v;
      u.setValue( 27 );
      v.bind( u );
      CPPUNIT_ASSERT( v.getSize() == u.getSize() );
      CPPUNIT_ASSERT( u.getElement( 0 ) == 27 );
      v.setValue( 50 );
      CPPUNIT_ASSERT( u.getElement( 0 ) == 50 );
      u.reset();
      CPPUNIT_ASSERT( u.getSize() == 0 );
      CPPUNIT_ASSERT( v.getElement( 0 ) == 50 );
      
      ElementType data[ 10 ] = { 1, 2, 3, 4, 5, 6, 7, 8, 10 };
      u.bind( data, 10 );
      CPPUNIT_ASSERT( u.getElement( 1 ) == 2 );
      v.bind( u );
      CPPUNIT_ASSERT( v.getElement( 1 ) == 2 );
      u.reset();
      v.setElement( 1, 3 );      
      v.reset();
      CPPUNIT_ASSERT( data[ 1 ] == 3 );
   }

   void testSetGetElement()
+2 −2

File changed.

Contains only whitespace changes.