]> https://gitweb.dealii.org/ - dealii.git/commitdiff
Add the SwappableVector from the wave program.
authorWolfgang Bangerth <bangerth@math.tamu.edu>
Wed, 3 May 2000 13:23:46 +0000 (13:23 +0000)
committerWolfgang Bangerth <bangerth@math.tamu.edu>
Wed, 3 May 2000 13:23:46 +0000 (13:23 +0000)
git-svn-id: https://svn.dealii.org/trunk@2787 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/lac/include/lac/swappable_vector.h [new file with mode: 0644]
deal.II/lac/include/lac/swappable_vector.templates.h [new file with mode: 0644]
deal.II/lac/source/swappable_vector.cc [new file with mode: 0644]

diff --git a/deal.II/lac/include/lac/swappable_vector.h b/deal.II/lac/include/lac/swappable_vector.h
new file mode 100644 (file)
index 0000000..af2e7a3
--- /dev/null
@@ -0,0 +1,283 @@
+//----------------------------  swappable_vector.h  ---------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 1999, 2000 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//----------------------------  swappable_vector.h  ---------------------------
+#ifndef __deal2__swappable_vector_h
+#define __deal2__swappable_vector_h
+
+
+#include <lac/vector.h>
+
+#ifdef DEAL_II_USE_MT
+#  include <base/thread_management.h>
+#endif
+
+#include <string>
+
+
+
+/**
+ * This class is a wrapper to the #Vector# class which allows to swap
+ * out the data to a file and reload it later on. It handles the
+ * management of the name of the file where the data is to be stored
+ * temporarily and removes the file is necessary at the end of the
+ * lifetime of the vector.
+ *
+ * There are functions to swap the data to a file, and to reload
+ * it. There is also a function #alert# that can be used to signal to
+ * an object of this class that the data will be needed shortly, so
+ * the object can initiate that the data be loaded already. While in
+ * non-multithreading mode, this function has no effect since #reload#
+ * has to be called afterwards anyway. On the other hand, in
+ * multithreading mode, the data is preloaded in the background using
+ * a thread on its own, and may already be available at the time when
+ * #reload# is called. If it is not available, #reload# waits until
+ * the detached thread has loaded the data.
+ *
+ * @author Wolfgang Bangerth, 1999, 2000
+ */
+template <typename number>
+class SwappableVector : public Vector<number>
+{
+  public:
+                                    /**
+                                     * Constructor. Does nothing
+                                     * apart from calling the
+                                     * constructor of the underlying
+                                     * class.
+                                     */
+    SwappableVector ();
+
+                                    /**
+                                     * Copy constructor. Copies the
+                                     * data if #v# contains some, but
+                                     * does not do so if #v# is empty
+                                     * or has its data swapped
+                                     * out. In the latter case, warn
+                                     * about that. In particular do
+                                     * not take over ownership of any
+                                     * files that #v# might own (as,
+                                     * for example, #C++#'s
+                                     * #auto_ptr# objects would do).
+                                     */
+    SwappableVector (const SwappableVector &v);
+
+                                    /**
+                                     * Destructor. If this class
+                                     * still owns a file to which
+                                     * temporary data was stored,
+                                     * then it is deleted.
+                                     */
+    virtual ~SwappableVector ();
+    
+                                    /**
+                                     * Copy operator. Do mostly the
+                                     * same as the copy constructor
+                                     * does; if necessary, delete
+                                     * temporary files owned by this
+                                     * object at first.
+                                     */
+    SwappableVector & operator = (const SwappableVector &);
+
+                                    /**
+                                     * Swap out the data of this
+                                     * vector to the file of which
+                                     * the name is given. It is
+                                     * assumed that the file can be
+                                     * overwritten if it exists, and
+                                     * ownership of this file is
+                                     * assumed by this object. The
+                                     * file is deleted either upon
+                                     * calling #kill_file#, or on
+                                     * destruction of this object.
+                                     *
+                                     * The content of the vector is
+                                     * cleared and it size is reset
+                                     * to zero.
+                                     *
+                                     * If this object owns another
+                                     * file, for example when
+                                     * #swap_out# but no #kill_file#
+                                     * has previously been called,
+                                     * then that is deleted first.
+                                     */
+    void swap_out (const string &filename);
+
+                                    /**
+                                     * Reload the data of this vector
+                                     * from the file to which it has
+                                     * been stored previously using
+                                     * #swap_out#. Since the file is
+                                     * not deleted after reloading,
+                                     * you can call #reload# multiple
+                                     * times, in between you may do
+                                     * everything with the vector,
+                                     * including changing its size.
+                                     *
+                                     * This function resets the size
+                                     * of the vector to the number of
+                                     * elements there were upon
+                                     * calling #swap_out# before.
+                                     */
+    void reload ();
+
+                                    /**
+                                     * Calling this function can be
+                                     * used to alert this vector that
+                                     * it will need to reload its
+                                     * data soon. It has no effect if
+                                     * the data of the vector is
+                                     * already present, and it has no
+                                     * effect in single-thread mode
+                                     * as well, but in multithread
+                                     * mode, it spawns another thread
+                                     * that reads the data in
+                                     * parallel to the usual
+                                     * execution of the program, such
+                                     * that when #reload# is called,
+                                     * the data may eventually be
+                                     * available already. It might
+                                     * therefore be wirthwhile to
+                                     * call this function some time
+                                     * in advance, if you know that
+                                     * the data will be needed, and
+                                     * loading takes some time, for
+                                     * instance if the file to which
+                                     * the data was written is not in
+                                     * a local tmp directory.
+                                     *
+                                     * Calling this function multiple
+                                     * times before calling #reload#
+                                     * is allowed and has no effect
+                                     * for subsequent calls. Calling
+                                     * this function while the data
+                                     * is still or already in memory
+                                     * is allowed and has no effect.
+                                     */
+    void alert ();
+    
+
+                                    /**
+                                     * Remove the file to which the
+                                     * data has been stored the last
+                                     * time. After this, the object
+                                     * does not own any file any
+                                     * more, so of course you can't
+                                     * call #reload# no more.
+                                     *
+                                     * If this object does not own a
+                                     * file, for example since
+                                     * #swap_out# was not called, or
+                                     * because #kill_file# has been
+                                     * called previously, then this
+                                     * function does nothing.
+                                     */
+    void kill_file ();
+
+                                    /**
+                                     * Return the name of the file to
+                                     * which the data was stored the
+                                     * last time you called
+                                     * #swap_out#. If #swap_out# was
+                                     * not called, or if in between
+                                     * #kill_file# was called, then
+                                     * the filename is an empty
+                                     * string.
+                                     */
+    const string & get_filename () const;
+   
+                                    /**
+                                     * Exception.
+                                     */ 
+    DeclException0 (ExcSizeZero);
+                                    /**
+                                     * Exception.
+                                     */ 
+    DeclException0 (ExcSizeNonzero);
+                                    /**
+                                     * Exception.
+                                     */ 
+    DeclException1 (ExcInvalidFilename,
+                   string,
+                   << "The filename <" << arg1
+                   << "> is not a valid one here.");
+                                    /**
+                                     * Exception.
+                                     */ 
+    DeclException0 (ExcInvalidCopyOperation);
+    
+  private:
+                                    /**
+                                     * Name of the file to which data
+                                     * was swapped out. If no data is
+                                     * presently swapped out
+                                     * (i.e. before calling
+                                     * #swap_out# and after
+                                     * #kill_file#), the string is
+                                     * empty, indicating no ownership
+                                     * of files.
+                                     */
+    string filename;
+
+#ifdef DEAL_II_USE_MT
+                                    /**
+                                     * If in multithread mode, then
+                                     * the #alert# function has
+                                     * functionality, but needs to
+                                     * coordinate with the #reload#
+                                     * function. This is done through
+                                     * the following lock.
+                                     */
+    ACE_Thread_Mutex lock;
+
+                                    /**
+                                     * Declare a thread manager that
+                                     * is used to spawn threads in
+                                     * #alert# detached.
+                                     */
+    static ACE_Thread_Manager thread_manager;
+#endif
+
+                                    /**
+                                     * Flag by which the #alert#
+                                     * function signifies that the
+                                     * data has been preloaded
+                                     * already. This flag is always
+                                     * #false# in non-MT mode.
+                                     */
+    bool data_is_preloaded;
+
+                                    /**
+                                     * Internal function that
+                                     * actually reloads the
+                                     * vector. Called from #reload#
+                                     * and #alert#.
+                                     *
+                                     * The parameter specifies
+                                     * whether the function shall set
+                                     * #data_is_preloaded# or
+                                     * not. The calling functions
+                                     * can't sometimes do this
+                                     * themselves, since they call
+                                     * this function detached, so
+                                     * this function has to signal
+                                     * success itself if this is
+                                     * required.
+                                     */
+    void reload_vector (const bool set_flag);
+};
+
+
+
+/*----------------------------   swappable_vector.h     ---------------------------*/
+/* end of #ifndef __deal2__swappable_vector_h */
+#endif
+/*----------------------------   swappable_vector.h     ---------------------------*/
diff --git a/deal.II/lac/include/lac/swappable_vector.templates.h b/deal.II/lac/include/lac/swappable_vector.templates.h
new file mode 100644 (file)
index 0000000..6f825bb
--- /dev/null
@@ -0,0 +1,260 @@
+//----------------------------  swappable_vector.templates.h  ---------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 1999, 2000 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//----------------------------  swappable_vector.templates.h  ---------------------------
+#ifndef __deal2__swappable_vector_templates_h
+#define __deal2__swappable_vector_templates_h
+
+
+#include <lac/swappable_vector.h>
+#include <fstream>
+#include <iostream>
+
+
+
+#ifdef DEAL_II_USE_MT
+                                // allocate static variable
+template <typename number>
+ACE_Thread_Manager SwappableVector<number>::thread_manager;
+#endif
+
+
+
+
+template <typename number>
+SwappableVector<number>::SwappableVector ()
+               :
+               data_is_preloaded (false)
+{};
+
+
+
+template <typename number>
+SwappableVector<number>::SwappableVector (const SwappableVector<number> &v) :
+               Vector<number>(v),
+                filename (),
+                data_is_preloaded (false)
+{
+  Assert (v.filename == "", ExcInvalidCopyOperation());
+};
+
+
+
+template <typename number>
+SwappableVector<number>::~SwappableVector ()
+{
+                                  // if the vector was stored in a
+                                  // file previously, and that has
+                                  // not been deleted in the
+                                  // meantime, then we kill that file
+                                  // first, before killing the vector
+                                  // itself
+
+  if (filename != "")
+    kill_file ();
+};
+
+
+
+template <typename number>
+SwappableVector<number> &
+SwappableVector<number>::operator= (const SwappableVector<number> &v)
+{
+                                  // if necessary, first delete data
+  if (filename != "")
+    kill_file ();
+
+                                  // if in MT mode, block all other
+                                  // operations
+#ifdef DEAL_II_USE_MT
+  lock.acquire ();
+#endif
+  
+  Vector<number>::operator = (v);
+  data_is_preloaded = false;
+  
+#ifdef DEAL_II_USE_MT
+  lock.release ();
+#endif
+  
+  
+  return *this;
+};
+
+
+
+template <typename number>
+void SwappableVector<number>::swap_out (const string &name)
+{
+                                  // if the vector was stored in
+                                  // another file previously, and
+                                  // that has not been deleted in the
+                                  // meantime, then we kill that file
+                                  // first
+  if (filename != "")
+    kill_file ();
+  
+  filename = name;
+  
+  Assert (size() != 0, ExcSizeZero());
+
+                                  // if in MT mode, block all other
+                                  // operations
+#ifdef DEAL_II_USE_MT
+  lock.acquire ();
+#endif
+  
+                                  //  check that we have not called
+                                  //  #alert# without the respective
+                                  //  #reload# function
+  Assert (data_is_preloaded == false, ExcInternalError());
+  
+  ofstream tmp_out(filename.c_str());
+  block_write (tmp_out);
+  tmp_out.close ();
+       
+  reinit (0);
+
+#ifdef DEAL_II_USE_MT
+  lock.release ();
+#endif
+};
+
+
+
+template <typename number>
+void SwappableVector<number>::reload () 
+{
+                                  // if in MT mode: synchronise with
+                                  // possibly existing #alert# calls
+#ifdef DEAL_II_USE_MT
+  lock.acquire ();
+#endif
+                                  // if data was already preloaded,
+                                  // then there is no more need to
+                                  // load it
+  if (data_is_preloaded == false)
+                                    // reload data. note that this
+                                    // function also releases the
+                                    // lock
+    reload_vector (false);
+  else
+    {
+                                      // clear flag since no more
+                                      // needed
+      data_is_preloaded = false;
+
+                                      // release lock. the lock is
+                                      // also released in the other
+                                      // branch of the if-clause
+#ifdef DEAL_II_USE_MT
+      lock.release ();
+#endif
+    };
+};
+
+
+
+template <typename number>
+void SwappableVector<number>::alert ()
+{
+                                  // note: this function does nothing
+                                  // in non-MT mode
+#ifdef DEAL_II_USE_MT
+  
+                                  // synchronise with possible other
+                                  // invokations of this function and
+                                  // other functions in this class
+  lock.acquire ();
+  
+                                  // calling this function multiple
+                                  // times does no harm:
+  if ( (data_is_preloaded == true) ||
+                                  // calling this function while the
+                                  // vector is active does no harm
+                                  // either
+       (size() != 0))
+    lock.release ();
+  else
+                                    // data has not been preloaded so
+                                    // far, so go on!
+    Threads::spawn (thread_manager,
+                   Threads::encapsulate (&SwappableVector<number>::reload_vector)
+                   .collect_args(this, true));
+                                  // note that reload_vector also
+                                  // releases the lock
+#endif
+};
+
+
+
+template <typename number>
+void SwappableVector<number>::reload_vector (const bool set_flag)
+{
+  Assert (filename != "", ExcInvalidFilename (filename));
+  Assert (size() == 0, ExcSizeNonzero());
+  
+  ifstream tmp_in(filename.c_str());
+  block_read (tmp_in);
+  tmp_in.close ();
+
+                                  // release the lock that was
+                                  // acquired by the calling
+                                  // functions
+#ifdef DEAL_II_USE_MT
+                                  // set the flag if so required
+  if (set_flag)
+    data_is_preloaded = true;
+  lock.release ();
+#endif
+};
+
+
+
+template <typename number>
+void SwappableVector<number>::kill_file () 
+{
+                                  // if in MT mode, wait for other
+                                  // operations to finish first
+                                  // (there should be none, but who
+                                  // knows)
+#ifdef DEAL_II_USE_MT
+  lock.acquire();
+#endif
+
+  Assert (data_is_preloaded == false, ExcInternalError());
+  
+  if (filename != "")
+    {
+      int status = remove (filename.c_str());
+      AssertThrow (status == 0, ExcInternalError());
+  
+      filename = "";
+    };
+
+#ifdef DEAL_II_USE_MT
+  lock.release ();
+#endif
+};
+
+
+
+template <typename number>
+const string &
+SwappableVector<number>::get_filename () const 
+{
+  return filename;
+};
+
+
+
+
+#endif // __deal2__swappable_vector_templates_h
diff --git a/deal.II/lac/source/swappable_vector.cc b/deal.II/lac/source/swappable_vector.cc
new file mode 100644 (file)
index 0000000..cf19788
--- /dev/null
@@ -0,0 +1,19 @@
+//----------------------------  swappable_vector.cc  ---------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 1999, 2000 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//----------------------------  swappable_vector.cc  ---------------------------
+
+
+#include <lac/swappable_vector.templates.h>
+
+// explicit instantiations
+template class SwappableVector<double>;
+template class SwappableVector<float>;

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.