piranha  0.10
init.hpp
1 /* Copyright 2009-2017 Francesco Biscani (bluescarni@gmail.com)
2 
3 This file is part of the Piranha library.
4 
5 The Piranha library is free software; you can redistribute it and/or modify
6 it under the terms of either:
7 
8  * the GNU Lesser General Public License as published by the Free
9  Software Foundation; either version 3 of the License, or (at your
10  option) any later version.
11 
12 or
13 
14  * the GNU General Public License as published by the Free Software
15  Foundation; either version 3 of the License, or (at your option) any
16  later version.
17 
18 or both in parallel, as here.
19 
20 The Piranha library is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
22 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24 
25 You should have received copies of the GNU General Public License and the
26 GNU Lesser General Public License along with the Piranha library. If not,
27 see https://www.gnu.org/licenses/. */
28 
29 #ifndef PIRANHA_INIT_HPP
30 #define PIRANHA_INIT_HPP
31 
32 #include <cstdlib>
33 #include <iostream>
34 
35 #include <piranha/detail/init_data.hpp>
36 #include <piranha/detail/mpfr.hpp>
37 
38 namespace piranha
39 {
40 
41 inline namespace impl
42 {
43 
44 // The cleanup function.
45 inline void cleanup_function()
46 {
47  std::cout << "Freeing MPFR caches.\n";
48  ::mpfr_free_cache();
49  std::cout << "Setting shutdown flag.\n";
50  piranha_init_statics<>::s_shutdown_flag.store(true);
51 }
52 }
53 
55 
63 // A few notes about the init function. The basic idea is that we want certain things to happen
64 // when the program is shutting down but (crucially) *before* destruction of static objects starts.
65 // The language guarantees that anything registered with std::atexit() runs before the destruction of
66 // the statics, provided that the registration happens *after* the initialization of static objects.
67 // The complication here is that, even if we run this function as first thing in main(), we are still
68 // not 100% sure all statics have been initialised, because of potentially deferred dynamic init:
69 //
70 // http://en.cppreference.com/w/cpp/language/initialization#Deferred_dynamic_initialization
71 //
72 // The saving grace here seems to be in this quote:
73 //
74 // "If the initialization of a variable is deferred to happen after the first statement of main/thread function, it
75 // happens before the first odr-use of any variable with static/thread storage duration defined in the same translation
76 // unit as the variable to be initialized."
77 //
78 // In the init() function we are using indeed a static variable, the s_init_flag, and its use should guarantee the
79 // initialisation of all other statics. That's my understanding anyway. I am not 100% sure how this all maps to the
80 // init of pyranha, let's just keep the eyes open regarding this potential issue.
81 inline void init()
82 {
83  if (piranha_init_statics<>::s_init_flag.test_and_set()) {
84  // If the previous value of the init flag was true, it means we already called
85  // init() previously. Increase the failure count and exit.
86  ++piranha_init_statics<>::s_failed;
87  return;
88  }
89  std::cout << "Initializing piranha.\n";
90  if (std::atexit(cleanup_function)) {
91  std::cerr << "Unable to register cleanup function with std::atexit().\n";
92  std::cerr.flush();
93  std::abort();
94  }
95  if (!::mpfr_buildopt_tls_p()) {
96  // NOTE: logging candidate, we probably want to push
97  // this to a warning channel.
98  std::cerr << "The MPFR library was not built thread-safe.\n";
99  std::cerr.flush();
100  }
101 }
102 }
103 
104 #endif
Root piranha namespace.
Definition: array_key.hpp:52
void init()
Main initialisation function.
Definition: init.hpp:81