00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032 #ifndef PHX_ALLOCATOR_CONTIGUOUS_HPP
00033 #define PHX_ALLOCATOR_CONTIGUOUS_HPP
00034
00035 #include "Phalanx_ConfigDefs.hpp"
00036 #include "Teuchos_ArrayRCP.hpp"
00037 #include "Teuchos_TestForException.hpp"
00038
00039 namespace PHX {
00040
00046 template<typename AlignmentT>
00047 class ContiguousAllocator {
00048
00049 public:
00050
00051 ContiguousAllocator()
00052 {
00053 this->reset();
00054 }
00055
00056 ~ContiguousAllocator()
00057 { }
00058
00059 void reset() {
00060 setup_called_ = false;
00061 total_bytes_ = 0;
00062 offset_ = 0;
00063 chunk_ = Teuchos::null;
00064 }
00065
00067 void addRequiredChunk(std::size_t size_of_data_type,
00068 std::size_t num_elements)
00069 {
00070 if (setup_called_) {
00071 std::string msg = "ERROR - PHX::ContiguousAllocator::addRequiredByte() - The method addRequiredBytes() has been called after the setup() has been called! Please fix your logic.";
00072 TEST_FOR_EXCEPTION(true, std::logic_error, msg);
00073 }
00074
00075 std::size_t alignment_size = sizeof(AlignmentT);
00076 std::size_t residual = size_of_data_type % alignment_size;
00077 std::size_t element_size = size_of_data_type + residual;
00078
00079 total_bytes_ += num_elements * element_size;
00080 }
00081
00083 void setup()
00084 {
00085 chunk_ = Teuchos::arcp<char>(total_bytes_);
00086 setup_called_ = true;
00087 }
00088
00089 template<class DataT>
00090 Teuchos::ArrayRCP<DataT> allocate(std::size_t num_elements)
00091 {
00092 TEST_FOR_EXCEPTION(!setup_called_, std::logic_error,
00093 "setup() has not been called. The memory block has therefore not been allocated yet! Please call setup before calling allocate().");
00094
00095 std::size_t size_of_data_type = sizeof(DataT);
00096 std::size_t alignment_size = sizeof(AlignmentT);
00097 std::size_t residual = size_of_data_type % alignment_size;
00098 std::size_t element_size = size_of_data_type + residual;
00099
00100 int required_bytes = num_elements * element_size;
00101
00102 TEST_FOR_EXCEPTION(offset_ + required_bytes > total_bytes_,
00103 std::logic_error,
00104 "The requested number of bytes is larger than the size of the allocated contiguous block!");
00105
00106 char* raw_data = chunk_.get();
00107 char* offset_data = &raw_data[offset_];
00108 DataT* data = reinterpret_cast<DataT*>(offset_data);
00109
00110 Teuchos::ArrayRCP<DataT> array =
00111 Teuchos::arcpWithEmbeddedObjPostDestroy(data, 0, num_elements,
00112 chunk_, false);
00113 offset_ += required_bytes;
00114
00115
00116 for (std::size_t i=0; i < num_elements; ++i)
00117 new (&data[i]) DataT;
00118
00119 return array;
00120 }
00121
00122 int getTotalBytes() const
00123 {
00124 return total_bytes_;
00125 }
00126
00127 private:
00128
00129 bool setup_called_;
00130
00131 long int total_bytes_;
00132
00133 int offset_;
00134
00135 Teuchos::ArrayRCP<char> chunk_;
00136
00137 };
00138
00139 }
00140 #endif