From 8bf2901ba6f353574ef1e43f2bd8a2a300b56879 Mon Sep 17 00:00:00 2001 From: bangerth Date: Sun, 1 Dec 2013 17:29:14 +0000 Subject: [PATCH] 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 --- deal.II/source/fe/fe_values.cc | 71 ++++++++++++++++++++++++---------- 1 file changed, 50 insertions(+), 21 deletions(-) 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 -- 2.39.5