From: Wolfgang Bangerth Date: Sun, 1 Dec 2013 17:29:14 +0000 (+0000) Subject: Avoid a memory allocation if possible, by re-using previously used memory. X-Git-Tag: v8.1.0~133 X-Git-Url: https://gitweb.dealii.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b61d74bfb9041a5fad914e25e8d90132b0cd0ca2;p=dealii.git Avoid a memory allocation if possible, by re-using previously used memory. git-svn-id: https://svn.dealii.org/trunk@31838 0785d39b-7218-0410-832d-ea1e28bc413d --- diff --git a/deal.II/source/fe/fe_values.cc b/deal.II/source/fe/fe_values.cc index a94336f669..a497fce3cb 100644 --- a/deal.II/source/fe/fe_values.cc +++ b/deal.II/source/fe/fe_values.cc @@ -3356,6 +3356,37 @@ FEValues::initialize (const UpdateFlags update_flags) } +namespace +{ + // Reset a std::auto_ptr. If we can, do not de-allocate the previously + // held memory but re-use it for the next item to avoid the repeated + // memory allocation. We do this because FEValues objects are heavily + // used in multithreaded contexts where memory allocations are evil. + template + void + reset_pointer_in_place_if_possible + (std::auto_ptr &present_cell, + const Iterator &new_cell) + { + // see if the existing pointer is non-null and if the type of + // the old object pointed to matches that of the one we'd + // like to create + if (present_cell.get() + && + (typeid(*present_cell.get()) == typeid(Type))) + { + // call destructor of the old object + static_cast(present_cell.get())->~Type(); + + // then construct a new object in-place + new(const_cast(static_cast(present_cell.get()))) Type(new_cell); + } + else + // if the types don't match, there is nothing we can do here + present_cell.reset (new Type(new_cell)); + } +} + template void FEValues::reinit (const typename Triangulation::cell_iterator &cell) @@ -3369,9 +3400,10 @@ void FEValues::reinit (const typename Triangulation: // care that old object gets // destroyed and also that this // object gets destroyed in the - // destruction of this class - this->present_cell.reset - (new typename FEValuesBase::TriaCellIterator (cell)); + // destruction of the current object + reset_pointer_in_place_if_possible::TriaCellIterator> + (this->present_cell, cell); + // this was the part of the work // that is dependent on the actual // data type of the iterator. now @@ -3403,10 +3435,9 @@ FEValues::reinit (const TriaIterator > ce // care that old object gets // destroyed and also that this // object gets destroyed in the - // destruction of this class - this->present_cell.reset - (new typename FEValuesBase::template - CellIterator > > (cell)); + // destruction of the current object + reset_pointer_in_place_if_possible::template CellIterator > > > + (this->present_cell, cell); // this was the part of the work // that is dependent on the actual @@ -3581,11 +3612,10 @@ FEFaceValues::reinit (const TriaIterator // care that old object gets // destroyed and also that this // object gets destroyed in the - // destruction of this class + // destruction of the current object this->maybe_invalidate_previous_present_cell (cell); - this->present_cell.reset - (new typename FEValuesBase::template - CellIterator > > (cell)); + reset_pointer_in_place_if_possible::template CellIterator > > > + (this->present_cell, cell); // this was the part of the work // that is dependent on the actual @@ -3608,10 +3638,10 @@ void FEFaceValues::reinit (const typename Triangulationmaybe_invalidate_previous_present_cell (cell); - this->present_cell.reset - (new typename FEValuesBase::TriaCellIterator (cell)); + reset_pointer_in_place_if_possible::TriaCellIterator> + (this->present_cell, cell); // this was the part of the work // that is dependent on the actual @@ -3756,11 +3786,10 @@ void FESubfaceValues::reinit (const TriaIteratormaybe_invalidate_previous_present_cell (cell); - this->present_cell.reset - (new typename FEValuesBase::template - CellIterator > > (cell)); + reset_pointer_in_place_if_possible::template CellIterator > > > + (this->present_cell, cell); // this was the part of the work // that is dependent on the actual @@ -3785,10 +3814,10 @@ void FESubfaceValues::reinit (const typename Triangulationmaybe_invalidate_previous_present_cell (cell); - this->present_cell.reset - (new typename FEValuesBase::TriaCellIterator (cell)); + reset_pointer_in_place_if_possible::TriaCellIterator> + (this->present_cell, cell); // this was the part of the work // that is dependent on the actual