GetFEM++  5.3
dal_singleton.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2004-2017 Julien Pommier
5 
6  This file is a part of GetFEM++
7 
8  GetFEM++ is free software; you can redistribute it and/or modify it
9  under the terms of the GNU Lesser General Public License as published
10  by the Free Software Foundation; either version 3 of the License, or
11  (at your option) any later version along with the GCC Runtime Library
12  Exception either version 3.1 or (at your option) any later version.
13  This program is distributed in the hope that it will be useful, but
14  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
16  License and GCC Runtime Library Exception for more details.
17  You should have received a copy of the GNU Lesser General Public License
18  along with this program; if not, write to the Free Software Foundation,
19  Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
20 
21  As a special exception, you may use this file as it is a part of a free
22  software library without restriction. Specifically, if other files
23  instantiate templates or use macros or inline functions from this file,
24  or you compile this file and link it with other files to produce an
25  executable, this file does not by itself cause the resulting executable
26  to be covered by the GNU Lesser General Public License. This exception
27  does not however invalidate any other reasons why the executable file
28  might be covered by the GNU Lesser General Public License.
29 
30 ===========================================================================*/
31 
32 /**@file dal_singleton.h
33 @author Julien Pommier <Julien.Pommier@insa-toulouse.fr>
34 @date May 2004.
35 @brief A simple singleton implementation
36 
37 Singleton was made thread safe for OpenMP
38 However, now there is a singleton instance for every
39 thread (singleton is thread local). This replicates
40 the behaviour of singletons in distirbuted MPI-like
41 environment;
42 */
43 #ifndef DAL_SINGLETON
44 #define DAL_SINGLETON
45 
46 #include <vector>
47 #include <memory>
48 #include "getfem_omp.h"
49 
50 
51 namespace dal {
52 
53  class singleton_instance_base {
54  public:
55  virtual ~singleton_instance_base() {}
56  virtual int level() = 0;
57  };
58 
59 
60  class singletons_manager {
61  protected:
63  static singletons_manager& manager();
64  static singletons_manager& m;
65 
66  public:
67  static void register_new_singleton(singleton_instance_base *p);
68  static void register_new_singleton(singleton_instance_base *p,
69  size_t ithread);
70  ~singletons_manager();
71  private:
72  singletons_manager();
73  };
74 
75 
76 
77 
78  template <typename T, int LEV> class singleton_instance
79  : public singleton_instance_base {
80  static getfem::omp_distribute<T*>* instance_;
81  static getfem::omp_distribute<T*>* omp_distro_pointer() {
83  pointer = new getfem::omp_distribute<T*>();
84  return pointer;
85  }
86  static T*& instance_pointer() { return omp_distro_pointer()->thrd_cast(); }
87  static T*& instance_pointer(size_t ithread)
88  { return (*omp_distro_pointer())(ithread);}
89 
90  public:
91 
92  singleton_instance() {}
93 
94  /** Instance from the current thread*/
95  inline static T& instance() {
96  T*& tinstance_ = instance_pointer();
97  if (!tinstance_) {
98  tinstance_ = new T();
99  singletons_manager::register_new_singleton
100  (new singleton_instance<T,LEV>());
101  }
102  return *tinstance_;
103  }
104 
105  /**Instance from thread ithread*/
106  inline static T& instance(size_t ithread) {
107  T*& tinstance_ = instance_pointer(ithread);
108  if (!tinstance_) {
109  tinstance_ = new T();
110  singletons_manager::register_new_singleton
111  (new singleton_instance<T,LEV>(),ithread);
112  }
113  return *tinstance_;
114  }
115 
116  int level() { return LEV; }
117 
118  ~singleton_instance() {
119  if (instance_) {
120  for(size_t i = 0; i < getfem::num_threads(); i++) {
121  if((*instance_)(i)) {
122  delete (*instance_)(i);
123  (*instance_)(i) = 0;
124  }
125  }
126  }
127  delete instance_; instance_=0;
128  }
129  };
130 
131  /** singleton class.
132 
133  usage:
134  @code
135  foo &f = singleton<foo>::instance();
136  const foo &f = singleton<foo>::const_instance();
137  @endcode
138  the LEV template arguments allows one to choose the order of destruction
139  of the singletons:
140  lowest LEV will be destroyed first.
141  */
142  template <typename T, int LEV=1> class singleton {
143  public:
144 
145  /** Instance from the current thread*/
146  inline static T& instance() {
147  return singleton_instance<T,LEV>::instance();
148  }
149  inline static const T& const_instance() { return instance(); }
150 
151  inline static T& instance(size_t ithread) {
152  return singleton_instance<T,LEV>::instance(ithread);
153  }
154  inline static const T& const_instance(size_t ithread)
155  { return instance(ithread); }
156 
157 
158  protected:
159  singleton() {}
160  ~singleton() {}
161  private:
162  singleton(const singleton&);
163  singleton& operator=(const singleton&);
164  };
165 
166  template <typename T, int LEV>
167  getfem::omp_distribute<T*>* singleton_instance<T,LEV>::instance_
168  = singleton_instance<T,LEV>::omp_distro_pointer();
169 }
170 
171 #endif
172 
173 
use this template class for any object you want to distribute to open_MP threads. ...
Definition: getfem_omp.h:146
singleton class.
Tools for multithreaded, OpenMP and Boost based parallelization.
static T & instance()
Instance from the current thread.
Dynamic Array Library.