From ba397b9f9b6eec589accda0a7fa8c192adc398fc Mon Sep 17 00:00:00 2001 From: Martin Kronbichler Date: Wed, 18 Feb 2015 17:35:18 +0100 Subject: [PATCH] Put implementation (Growing)VectorMemory into .templates.h file This enables users to provide instantiations of the class for non-deal.II vector types and their use in Solver classes. Reported by Karl Ljungkvist. --- doc/news/changes.h | 9 + include/deal.II/lac/solver.h | 20 +- include/deal.II/lac/vector_memory.templates.h | 210 ++++++++++++++++++ source/lac/vector_memory.cc | 192 +--------------- 4 files changed, 241 insertions(+), 190 deletions(-) create mode 100644 include/deal.II/lac/vector_memory.templates.h diff --git a/doc/news/changes.h b/doc/news/changes.h index c1c72b0fe9..23518e1e70 100644 --- a/doc/news/changes.h +++ b/doc/news/changes.h @@ -350,6 +350,15 @@ inconvenience this causes.

Specific improvements

    +
  1. Fixed: The implementation of the class GrowingVectorMemory has been + moved from source/lac/vector_memory.cc to the new file + include/deal.II/lac/vector_memory.templates.h. This allows users to + create instantiations of GrowingVectorMemory for their own vector classes + in case they intend to use them for the deal.II solvers. +
    + (Martin Kronbichler, 2015/02/18) +
  2. +
  3. Changed: All members of MultithreadInfo are now static so it is no longer necessary to use the global instance multithread_info (now deprecated) or create your own instance (which does not work correctly diff --git a/include/deal.II/lac/solver.h b/include/deal.II/lac/solver.h index 49e5f51481..2388cd2aad 100644 --- a/include/deal.II/lac/solver.h +++ b/include/deal.II/lac/solver.h @@ -1,6 +1,6 @@ // --------------------------------------------------------------------- // -// Copyright (C) 1998 - 2014 by the deal.II authors +// Copyright (C) 1998 - 2015 by the deal.II authors // // This file is part of the deal.II library. // @@ -120,6 +120,24 @@ template class Vector; * swap(VECTOR &a, VECTOR &b) that exchanges the values of the two * vectors. * + * Finally, the solvers also expect an instantiation of + * GrowingVectorMemory. These instantiations are provided by the + * deal.II library for the built-in vector types, but must be explicitly added + * for user-provided vector classes. Otherwise, the linker will complain that + * it cannout find the constructors and destructors of GrowingVectorMemory + * that happen in the @p Solver class below. + * + * @code + * #include + * + * // Definition and implementation of vector class + * class UserVector { ... }; + * + * // Create explicit instantiation for the vector class + * template class VectorMemory; + * template class GrowingVectorMemory; + * @endcode + * * The preconditioners used must have the same interface as matrices, i.e. in * particular they have to provide a member function @p vmult which denotes * the application of the preconditioner. diff --git a/include/deal.II/lac/vector_memory.templates.h b/include/deal.II/lac/vector_memory.templates.h new file mode 100644 index 0000000000..2bc6391f11 --- /dev/null +++ b/include/deal.II/lac/vector_memory.templates.h @@ -0,0 +1,210 @@ +// --------------------------------------------------------------------- +// +// Copyright (C) 2007 - 2015 by the deal.II authors +// +// This file is part of the deal.II library. +// +// The deal.II library is free software; you can use it, redistribute +// it, and/or modify it under the terms of the GNU Lesser General +// Public License as published by the Free Software Foundation; either +// version 2.1 of the License, or (at your option) any later version. +// The full text of the license can be found in the file LICENSE at +// the top level of the deal.II distribution. +// +// --------------------------------------------------------------------- + +#ifndef __deal2__vector_memory_templates_h +#define __deal2__vector_memory_templates_h + + +#include + +DEAL_II_NAMESPACE_OPEN + + +template +typename GrowingVectorMemory::Pool GrowingVectorMemory::pool; + +template +Threads::Mutex GrowingVectorMemory::mutex; + +template +inline +GrowingVectorMemory::Pool::Pool() + : + data(0) +{} + + + +template +inline +GrowingVectorMemory::Pool::~Pool() +{ + // Nothing to do if memory was unused. + if (data == 0) return; + + // First, delete all remaining + // vectors. Actually, there should + // be none, if there is no memory + // leak + for (typename std::vector::iterator i=data->begin(); + i != data->end(); + ++i) + { + delete i->second; + } + delete data; +} + + +template +inline +void +GrowingVectorMemory::Pool::initialize(const size_type size) +{ + if (data == 0) + { + data = new std::vector(size); + + for (typename std::vector::iterator i= data->begin(); + i != data->end(); + ++i) + { + i->first = false; + i->second = new VECTOR; + } + } +} + + +template +inline +GrowingVectorMemory::GrowingVectorMemory (const size_type initial_size, + const bool log_statistics) + + : + total_alloc(0), + current_alloc(0), + log_statistics(log_statistics) +{ + Threads::Mutex::ScopedLock lock(mutex); + pool.initialize(initial_size); +} + + +template +inline +GrowingVectorMemory::~GrowingVectorMemory() +{ + AssertNothrow(current_alloc == 0, + StandardExceptions::ExcMemoryLeak(current_alloc)); + if (log_statistics) + { + deallog << "GrowingVectorMemory:Overall allocated vectors: " + << total_alloc << std::endl; + deallog << "GrowingVectorMemory:Maximum allocated vectors: " + << pool.data->size() << std::endl; + } +} + + + +template +inline +VECTOR * +GrowingVectorMemory::alloc () +{ + Threads::Mutex::ScopedLock lock(mutex); + ++total_alloc; + ++current_alloc; + // see if there is a free vector + // available in our list + for (typename std::vector::iterator i=pool.data->begin(); + i != pool.data->end(); ++i) + { + if (i->first == false) + { + i->first = true; + return (i->second); + } + } + + // no free vector found, so let's + // just allocate a new one + const entry_type t (true, new VECTOR); + pool.data->push_back(t); + + return t.second; +} + + + +template +inline +void +GrowingVectorMemory::free(const VECTOR *const v) +{ + Threads::Mutex::ScopedLock lock(mutex); + for (typename std::vector::iterator i=pool.data->begin(); + i != pool.data->end(); ++i) + { + if (v == (i->second)) + { + i->first = false; + --current_alloc; + return; + } + } + Assert(false, typename VectorMemory::ExcNotAllocatedHere()); +} + + + +template +inline +void +GrowingVectorMemory::release_unused_memory () +{ + Threads::Mutex::ScopedLock lock(mutex); + + std::vector new_data; + + if (pool.data != 0) + { + const typename std::vector::const_iterator + end = pool.data->end(); + for (typename std::vector::const_iterator + i = pool.data->begin(); i != end ; ++i) + if (i->first == false) + delete i->second; + else + new_data.push_back (*i); + + *pool.data = new_data; + } +} + + + +template +inline +std::size_t +GrowingVectorMemory::memory_consumption () const +{ + Threads::Mutex::ScopedLock lock(mutex); + + std::size_t result = sizeof (*this); + const typename std::vector::const_iterator + end = pool.data->end(); + for (typename std::vector::const_iterator + i = pool.data->begin(); i != end ; ++i) + result += sizeof (*i) + i->second->memory_consumption(); + + return result; +} + + +DEAL_II_NAMESPACE_CLOSE + +#endif diff --git a/source/lac/vector_memory.cc b/source/lac/vector_memory.cc index 96d0687b16..9e38ad9b39 100644 --- a/source/lac/vector_memory.cc +++ b/source/lac/vector_memory.cc @@ -1,6 +1,6 @@ // --------------------------------------------------------------------- // -// Copyright (C) 2007 - 2014 by the deal.II authors +// Copyright (C) 2007 - 2015 by the deal.II authors // // This file is part of the deal.II library. // @@ -13,7 +13,6 @@ // // --------------------------------------------------------------------- -#include #include #include #include @@ -25,195 +24,10 @@ #include #include -DEAL_II_NAMESPACE_OPEN - - -template -typename GrowingVectorMemory::Pool GrowingVectorMemory::pool; - -template -Threads::Mutex GrowingVectorMemory::mutex; - -template -inline -GrowingVectorMemory::Pool::Pool() - : - data(0) -{} - - - -template -inline -GrowingVectorMemory::Pool::~Pool() -{ - // Nothing to do if memory was unused. - if (data == 0) return; - - // First, delete all remaining - // vectors. Actually, there should - // be none, if there is no memory - // leak - for (typename std::vector::iterator i=data->begin(); - i != data->end(); - ++i) - { - delete i->second; - } - delete data; -} - - -template -inline -void -GrowingVectorMemory::Pool::initialize(const size_type size) -{ - if (data == 0) - { - data = new std::vector(size); - - for (typename std::vector::iterator i= data->begin(); - i != data->end(); - ++i) - { - i->first = false; - i->second = new VECTOR; - } - } -} - - -template -inline -GrowingVectorMemory::GrowingVectorMemory (const size_type initial_size, - const bool log_statistics) - - : - total_alloc(0), - current_alloc(0), - log_statistics(log_statistics) -{ - Threads::Mutex::ScopedLock lock(mutex); - pool.initialize(initial_size); -} - - -template -inline -GrowingVectorMemory::~GrowingVectorMemory() -{ - AssertNothrow(current_alloc == 0, - StandardExceptions::ExcMemoryLeak(current_alloc)); - if (log_statistics) - { - deallog << "GrowingVectorMemory:Overall allocated vectors: " - << total_alloc << std::endl; - deallog << "GrowingVectorMemory:Maximum allocated vectors: " - << pool.data->size() << std::endl; - } -} - - +#include -template -inline -VECTOR * -GrowingVectorMemory::alloc () -{ - Threads::Mutex::ScopedLock lock(mutex); - ++total_alloc; - ++current_alloc; - // see if there is a free vector - // available in our list - for (typename std::vector::iterator i=pool.data->begin(); - i != pool.data->end(); ++i) - { - if (i->first == false) - { - i->first = true; - return (i->second); - } - } - - // no free vector found, so let's - // just allocate a new one - const entry_type t (true, new VECTOR); - pool.data->push_back(t); - - return t.second; -} - - - -template -inline -void -GrowingVectorMemory::free(const VECTOR *const v) -{ - Threads::Mutex::ScopedLock lock(mutex); - for (typename std::vector::iterator i=pool.data->begin(); - i != pool.data->end(); ++i) - { - if (v == (i->second)) - { - i->first = false; - --current_alloc; - return; - } - } - Assert(false, typename VectorMemory::ExcNotAllocatedHere()); -} - - - -template -inline -void -GrowingVectorMemory::release_unused_memory () -{ - Threads::Mutex::ScopedLock lock(mutex); - - std::vector new_data; - - if (pool.data != 0) - { - const typename std::vector::const_iterator - end = pool.data->end(); - for (typename std::vector::const_iterator - i = pool.data->begin(); i != end ; ++i) - if (i->first == false) - delete i->second; - else - new_data.push_back (*i); - - *pool.data = new_data; - } -} - - - -template -inline -std::size_t -GrowingVectorMemory::memory_consumption () const -{ - Threads::Mutex::ScopedLock lock(mutex); - - std::size_t result = sizeof (*this); - const typename std::vector::const_iterator - end = pool.data->end(); - for (typename std::vector::const_iterator - i = pool.data->begin(); i != end ; ++i) - result += sizeof (*i) + i->second->memory_consumption(); - - return result; -} - - -// ------------------------------------------------------------- -// explicit instantiations +DEAL_II_NAMESPACE_OPEN #include "vector_memory.inst" -- 2.39.5