From 8ba4b4cf765325dc850ac701ca55eb815da58a8b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jakub=20Klinkovsk=C3=BD?= <klinkjak@fjfi.cvut.cz>
Date: Tue, 9 Jul 2019 20:33:49 +0200
Subject: [PATCH] Generalized copySTLList method to copyFromIterator which
 works with any STL-like iterator

---
 .../Containers/Algorithms/ArrayAssignment.h   |  2 +-
 .../Containers/Algorithms/ArrayOperations.h   | 28 ++++++++++------
 .../Algorithms/ArrayOperationsCuda.hpp        | 33 ++++++++++---------
 .../Algorithms/ArrayOperationsHost.hpp        | 18 ++++++----
 .../Algorithms/ArrayOperationsMIC.hpp         |  9 +++--
 src/TNL/Containers/Array.hpp                  |  4 +--
 6 files changed, 57 insertions(+), 37 deletions(-)

diff --git a/src/TNL/Containers/Algorithms/ArrayAssignment.h b/src/TNL/Containers/Algorithms/ArrayAssignment.h
index 78585003da..5d45bbbceb 100644
--- a/src/TNL/Containers/Algorithms/ArrayAssignment.h
+++ b/src/TNL/Containers/Algorithms/ArrayAssignment.h
@@ -40,7 +40,7 @@ public:
 template< typename Array,
           typename T,
           bool hasGetArrayData = detail::HasGetArrayData< T >::value >
-struct ArrayAssignment{};
+struct ArrayAssignment;
 
 /**
  * \brief Specialization for array-array assignment with containers implementing
diff --git a/src/TNL/Containers/Algorithms/ArrayOperations.h b/src/TNL/Containers/Algorithms/ArrayOperations.h
index 219465e18c..7977b6b728 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperations.h
+++ b/src/TNL/Containers/Algorithms/ArrayOperations.h
@@ -10,7 +10,6 @@
 
 #pragma once
 
-#include <list>
 #include <TNL/Devices/Host.h>
 #include <TNL/Devices/Cuda.h>
 #include <TNL/Devices/MIC.h>
@@ -46,9 +45,12 @@ struct ArrayOperations< Devices::Host >
                      const Index size );
 
    template< typename DestinationElement,
-             typename SourceElement >
-   static void copySTLList( DestinationElement* destination,
-                            const std::list< SourceElement >& source );
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
 
    template< typename Element1,
              typename Element2,
@@ -93,9 +95,12 @@ struct ArrayOperations< Devices::Cuda >
                      const Index size );
 
    template< typename DestinationElement,
-             typename SourceElement >
-   static void copySTLList( DestinationElement* destination,
-                            const std::list< SourceElement >& source );
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
 
    template< typename Element1,
              typename Element2,
@@ -177,9 +182,12 @@ struct ArrayOperations< Devices::MIC >
                      const Index size );
 
    template< typename DestinationElement,
-             typename SourceElement >
-   static void copySTLList( DestinationElement* destination,
-                            const std::list< SourceElement >& source );
+             typename Index,
+             typename SourceIterator >
+   static void copyFromIterator( DestinationElement* destination,
+                                 Index destinationSize,
+                                 SourceIterator first,
+                                 SourceIterator last );
 
    template< typename Element1,
              typename Element2,
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
index 68615a386c..e916be6aa8 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsCuda.hpp
@@ -12,6 +12,7 @@
 
 #include <iostream>
 #include <memory>
+#include <stdexcept>
 
 #include <TNL/Math.h>
 #include <TNL/ParallelFor.h>
@@ -94,27 +95,29 @@ copy( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::Cuda >::
-copySTLList( DestinationElement* destination,
-             const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
-   const auto size = source.size();
-   const std::size_t copy_buffer_size = std::min( Devices::Cuda::TransferBufferSize / (std::size_t) sizeof( DestinationElement ), ( std::size_t ) size );
    using BaseType = typename std::remove_cv< DestinationElement >::type;
-   std::unique_ptr< BaseType[] > copy_buffer{ new BaseType[ copy_buffer_size ] };
-   std::size_t copiedElements = 0;
-   auto it = source.begin();
-   while( copiedElements < size )
-   {
-      const auto copySize = std::min( size - copiedElements, copy_buffer_size );
-      for( std::size_t i = 0; i < copySize; i++ )
-         copy_buffer[ i ] = static_cast< DestinationElement >( * it ++ );
-      ArrayOperations< Devices::Cuda, Devices::Host >::copy( &destination[ copiedElements ], &copy_buffer[ 0 ], copySize );
-      copiedElements += copySize;
+   std::unique_ptr< BaseType[] > buffer{ new BaseType[ Devices::Cuda::getGPUTransferBufferSize() ] };
+   Index copiedElements = 0;
+   while( copiedElements < destinationSize && first != last ) {
+      Index i = 0;
+      while( i < Devices::Cuda::getGPUTransferBufferSize() && first != last )
+         buffer[ i++ ] = *first++;
+      ArrayOperations< Devices::Cuda, Devices::Host >::copy( &destination[ copiedElements ], buffer.get(), i );
+      copiedElements += i;
    }
+   if( first != last )
+      throw std::length_error( "Source iterator is larger than the destination array." );
 }
+
 template< typename Element1,
           typename Element2,
           typename Index >
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
index a50a10aaf0..4cfe789eca 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsHost.hpp
@@ -11,6 +11,7 @@
 #pragma once
 
 #include <type_traits>
+#include <stdexcept>
 #include <string.h>
 
 #include <TNL/ParallelFor.h>
@@ -91,15 +92,20 @@ copy( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::Host >::
-copySTLList( DestinationElement* destination,
-             const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
-   std::size_t i = 0;
-   for( const SourceElement& e : source )
-      destination[ i++ ] = e;
+   Index i = 0;
+   while( i < destinationSize && first != last )
+      destination[ i++ ] = *first++;
+   if( first != last )
+      throw std::length_error( "Source iterator is larger than the destination array." );
 }
 
 
diff --git a/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp b/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
index 601ce06668..5bf04dbaf5 100644
--- a/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
+++ b/src/TNL/Containers/Algorithms/ArrayOperationsMIC.hpp
@@ -112,11 +112,14 @@ copy( DestinationElement* destination,
 }
 
 template< typename DestinationElement,
-          typename SourceElement >
+          typename Index,
+          typename SourceIterator >
 void
 ArrayOperations< Devices::MIC >::
-copySTLList( DestinationElement* destination,
-             const std::list< SourceElement >& source )
+copyFromIterator( DestinationElement* destination,
+                  Index destinationSize,
+                  SourceIterator first,
+                  SourceIterator last )
 {
    throw Exceptions::NotImplementedError();
 }
diff --git a/src/TNL/Containers/Array.hpp b/src/TNL/Containers/Array.hpp
index 9807128036..76ce638443 100644
--- a/src/TNL/Containers/Array.hpp
+++ b/src/TNL/Containers/Array.hpp
@@ -132,7 +132,7 @@ Array( const std::list< InValue >& list,
 : allocator( allocator )
 {
    this->setSize( list.size() );
-   Algorithms::ArrayOperations< Device >::copySTLList( this->getData(), list );
+   Algorithms::ArrayOperations< Device >::copyFromIterator( this->getData(), this->getSize(), list.cbegin(), list.cend() );
 }
 
 template< typename Value,
@@ -604,7 +604,7 @@ Array< Value, Device, Index, Allocator >::
 operator=( const std::list< InValue >& list )
 {
    this->setSize( list.size() );
-   Algorithms::ArrayOperations< Device >::copySTLList( this->getData(), list );
+   Algorithms::ArrayOperations< Device >::copyFromIterator( this->getData(), this->getSize(), list.cbegin(), list.cend() );
    return *this;
 }
 
-- 
GitLab