GetFEM  5.5
dal_singleton.h
Go to the documentation of this file.
1 /* -*- c++ -*- (enables emacs c++ mode) */
2 /*===========================================================================
3 
4  Copyright (C) 2004-2026 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, see https://www.gnu.org/licenses/.
19 
20  As a special exception, you may use this file as it is a part of a free
21  software library without restriction. Specifically, if other files
22  instantiate templates or use macros or inline functions from this file,
23  or you compile this file and link it with other files to produce an
24  executable, this file does not by itself cause the resulting executable
25  to be covered by the GNU Lesser General Public License. This exception
26  does not however invalidate any other reasons why the executable file
27  might be covered by the GNU Lesser General Public License.
28 
29 ===========================================================================*/
30 
31 /**@file dal_singleton.h
32 @author Julien Pommier <Julien.Pommier@insa-toulouse.fr>
33 @date May 2004.
34 @brief A simple singleton implementation
35 
36 Singleton was made thread safe for OpenMP
37 However, now there is a singleton instance for every
38 thread (singleton is thread local). This replicates
39 the behaviour of singletons in distributed MPI-like
40 environment;
41 */
42 
43 #pragma once
44 
45 #include <vector>
46 #include <memory>
47 
48 #include "getfem_omp.h"
49 
50 
51 namespace dal {
52 
53  using bgeot::size_type;
54 
55  class singleton_instance_base {
56  public:
57  virtual ~singleton_instance_base() {};
58  virtual int level() const = 0;
59  };
60 
61  class singletons_manager {
63  size_type nb_partitions;
64  static singletons_manager& manager();
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  static void on_partitions_change();
71 
72  /**destroy singletons in increasing order*/
73  ~singletons_manager();
74 
75  private:
76  singletons_manager();
77  };
78 
79  template <typename T, int LEV>
80  class singleton_instance : public singleton_instance_base {
81 
82  static getfem::omp_distribute<T*>* initializing_pointer;
83 
84  static getfem::omp_distribute<T*>*& pointer() {
85  static auto p = new getfem::omp_distribute<T*>{};
86  return p;
87  }
88 
89  static T*& instance_pointer() {
90  return pointer()->thrd_cast();
91  }
92 
93  static T*& instance_pointer(size_t ithread) {
94  return (*pointer())(ithread);
95  }
96 
97  public:
98 
99  /**Instance from thread ithread*/
100  inline static T& instance(size_t ithread) {
101  pointer()->on_thread_update();
102  T*& tinstance_ = instance_pointer(ithread);
103  if (!tinstance_) {
104  tinstance_ = new T();
105  singletons_manager::register_new_singleton(
106  new singleton_instance<T,LEV>(), ithread);
107  }
108  return *instance_pointer(ithread);
109  }
110 
111  /** Instance from the current thread*/
112  inline static T& instance() {
113  return instance(this_thread());
114  }
115 
116  inline static size_type num_threads() {
117  return pointer()->num_threads();
118  }
119 
120  inline static size_type this_thread() {
121  return pointer()->this_thread();
122  }
123 
124  int level() const override {
125  return LEV;
126  }
127 
128  ~singleton_instance() {
129  if (!pointer()) return;
130  for(size_t i = 0; i != pointer()->num_threads(); ++i) {
131  auto &p_singleton = (*pointer())(i);
132  if(p_singleton){
133  delete p_singleton;
134  p_singleton = nullptr;
135  }
136  }
137  delete pointer();
138  pointer() = nullptr;
139  if (initializing_pointer) initializing_pointer = nullptr;
140  }
141  };
142 
143  template<typename T, int LEV> getfem::omp_distribute<T*>*
144  singleton_instance<T, LEV>::initializing_pointer = singleton_instance<T, LEV>::pointer();
145 
146  /** singleton class.
147 
148  usage:
149  @code
150  foo &f = singleton<foo>::instance();
151  const foo &f = singleton<foo>::const_instance();
152  @endcode
153  the LEV template arguments allows one to choose the order of destruction
154  of the singletons:
155  lowest LEV will be destroyed first.
156  */
157  template <typename T, int LEV=1> class singleton {
158  public:
159 
160  singleton(const singleton&) = delete;
161  singleton& operator=(const singleton&) = delete;
162 
163  /** Instance from the current thread*/
164  inline static T& instance() {
165  return singleton_instance<T,LEV>::instance();
166  }
167 
168  inline static const T& const_instance() {
169  return instance();
170  }
171 
172  inline static T& instance(size_t ithread) {
173  return singleton_instance<T,LEV>::instance(ithread);
174  }
175 
176  inline static const T& const_instance(size_t ithread){
177  return instance(ithread);
178  }
179 
180  /** number of threads this singleton is distributed on.*/
181  inline static size_type num_threads(){
182  return singleton_instance<T,LEV>::num_threads();
183  }
184 
185  /** this thread number according to the threading policy of the singleton*/
186  inline static size_type this_thread() {
187  return singleton_instance<T, LEV>::this_thread();
188  }
189 
190  protected:
191  singleton() = default;
192  ~singleton() = default;
193  };
194 
195 }/* 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:325
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:48
Dynamic Array Library.