GetFEM  5.4.3
dal_singleton.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2004-2020 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 <[email protected]>
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 distributed MPI-like
41 environment;
42 */
43 
44 #pragma once
45 
46 #include <vector>
47 #include <memory>
48 
49 #include "getfem_omp.h"
50 
51 
52 namespace dal {
53 
54  using bgeot::size_type;
55 
56  class singleton_instance_base {
57  public:
58  virtual ~singleton_instance_base() {};
59  virtual int level() const = 0;
60  };
61 
62  class singletons_manager {
64  size_type nb_partitions;
65  static singletons_manager& manager();
66 
67  public:
68  static void register_new_singleton(singleton_instance_base *p);
69  static void register_new_singleton(singleton_instance_base *p,
70  size_t ithread);
71  static void on_partitions_change();
72 
73  /**destroy singletons in increasing order*/
74  ~singletons_manager();
75 
76  private:
77  singletons_manager();
78  };
79 
80  template <typename T, int LEV>
81  class singleton_instance : public singleton_instance_base {
82 
83  static getfem::omp_distribute<T*>* initializing_pointer;
84 
85  static getfem::omp_distribute<T*>*& pointer() {
86  static auto p = new getfem::omp_distribute<T*>{};
87  return p;
88  }
89 
90  static T*& instance_pointer() {
91  return pointer()->thrd_cast();
92  }
93 
94  static T*& instance_pointer(size_t ithread) {
95  return (*pointer())(ithread);
96  }
97 
98  public:
99 
100  /**Instance from thread ithread*/
101  inline static T& instance(size_t ithread) {
102  pointer()->on_thread_update();
103  T*& tinstance_ = instance_pointer(ithread);
104  if (!tinstance_) {
105  tinstance_ = new T();
106  singletons_manager::register_new_singleton(
107  new singleton_instance<T,LEV>(), ithread);
108  }
109  return *instance_pointer(ithread);
110  }
111 
112  /** Instance from the current thread*/
113  inline static T& instance() {
114  return instance(this_thread());
115  }
116 
117  inline static size_type num_threads() {
118  return pointer()->num_threads();
119  }
120 
121  inline static size_type this_thread() {
122  return pointer()->this_thread();
123  }
124 
125  int level() const override {
126  return LEV;
127  }
128 
129  ~singleton_instance() {
130  if (!pointer()) return;
131  for(size_t i = 0; i != pointer()->num_threads(); ++i) {
132  auto &p_singleton = (*pointer())(i);
133  if(p_singleton){
134  delete p_singleton;
135  p_singleton = nullptr;
136  }
137  }
138  delete pointer();
139  pointer() = nullptr;
140  if (initializing_pointer) initializing_pointer = nullptr;
141  }
142  };
143 
144  template<typename T, int LEV> getfem::omp_distribute<T*>*
145  singleton_instance<T, LEV>::initializing_pointer = singleton_instance<T, LEV>::pointer();
146 
147  /** singleton class.
148 
149  usage:
150  @code
151  foo &f = singleton<foo>::instance();
152  const foo &f = singleton<foo>::const_instance();
153  @endcode
154  the LEV template arguments allows one to choose the order of destruction
155  of the singletons:
156  lowest LEV will be destroyed first.
157  */
158  template <typename T, int LEV=1> class singleton {
159  public:
160 
161  singleton(const singleton&) = delete;
162  singleton& operator=(const singleton&) = delete;
163 
164  /** Instance from the current thread*/
165  inline static T& instance() {
166  return singleton_instance<T,LEV>::instance();
167  }
168 
169  inline static const T& const_instance() {
170  return instance();
171  }
172 
173  inline static T& instance(size_t ithread) {
174  return singleton_instance<T,LEV>::instance(ithread);
175  }
176 
177  inline static const T& const_instance(size_t ithread){
178  return instance(ithread);
179  }
180 
181  /** number of threads this singleton is distributed on.*/
182  inline static size_type num_threads(){
183  return singleton_instance<T,LEV>::num_threads();
184  }
185 
186  /** this thread number according to the threading policy of the singleton*/
187  inline static size_type this_thread() {
188  return singleton_instance<T, LEV>::this_thread();
189  }
190 
191  protected:
192  singleton() = default;
193  ~singleton() = default;
194  };
195 
196 }/* end of namespace dal */
singleton class.
static size_type this_thread()
this thread number according to the threading policy of the singleton
static T & instance()
Instance from the current thread.
static size_type num_threads()
number of threads this singleton is distributed on.
Use this template class for any object you want to distribute to open_MP threads.
Definition: getfem_omp.h:326
Tools for multithreaded, OpenMP and Boost based parallelization.
size_t size_type
used as the common size type in the library
Definition: bgeot_poly.h:49
Dynamic Array Library.