t-sakashita / rokko

Integrated Interface for libraries of eigenvalue decomposition
Boost Software License 1.0
10 stars 2 forks source link

C++11を使用したsingletonの作成方法 #606

Open t-sakashita opened 1 year ago

t-sakashita commented 1 year ago

C++11のMagic Staticsを用いたsingletonの作成方法を検討。 ポインタを使わなくて済む。 スレッドセーフな方法。

https://stackoverflow.com/questions/137975/what-are-drawbacks-or-disadvantages-of-singleton-pattern https://stackoverflow.com/questions/44525097/what-is-the-right-way-of-setting-member-pointers-to-null-in-a-singleton-class https://codereview.stackexchange.com/questions/173929/modern-c-singleton-template

t-sakashita commented 1 year ago

http://www.nuonsoft.com/blog/2017/08/10/implementing-a-thread-safe-singleton-with-c11-using-magic-statics/ https://codereview.stackexchange.com/questions/252318/magic-static-in-singleton-template

t-sakashita commented 1 year ago

https://blog.mbedded.ninja/programming/languages/c-plus-plus/magic-statics/

t-sakashita commented 1 year ago

とりあえず、戻り値はポインタのままとして、以下のように変更してみた。

  static factory* instance() {
    static factory instance;
    return &instance;
  }

以下が不要となる。

  static inline factory* instance_;

そのため、pyrokko.cppの以下の宣言が意味をなさなくなる。

#define PYROKKO_DEFINE_FACTORY(T)               \
template<> \
T*  T::instance_;

PYROKKO_DEFINE_FACTORY(rokko::detail::sd_solver_factory)
PYROKKO_DEFINE_FACTORY(rokko::detail::pd_solver_factory)

PYROKKO_DEFINE_FACTORY(rokko::detail::ps_solver_factory)
PYROKKO_DEFINE_FACTORY(rokko::detail::ps_mapping_1d_factory)
PYROKKO_DEFINE_FACTORY(rokko::detail::ps_mapping_1d_factory_num)
PYROKKO_DEFINE_FACTORY(rokko::detail::ps_crs_factory)

miniij.cppの実行は正常終了。 だが、minij.pyの実行で、#391 と同様のエラーが発生する。

t-sakashita commented 1 year ago

staticなクラス変数instance_を削除した場合、pythonラッパーにおいて、sd_solver_factoryを実体化する方法が分からない。

rokko::detail::sd_solver_factory::instance()を呼び出してみる。

template<>
rokko::detail::sd_solver_factory& rokko::detail::sd_solver_factory::instance();

PYBIND11_MODULE(pyrokko, m) {

コンパイルエラー:

[100%] Building CXX object rokko/CMakeFiles/pyrokko.dir/pyrokko.cpp.o
/Users/sakashitatatsuya/development/rokko/rokko/pyrokko.cpp:205:71: error: explicit specialization of 'instance' after instantiation
  rokko::detail::sd_solver_factory& rokko::detail::sd_solver_factory::instance();
                                                                      ^
/Users/sakashitatatsuya/development/rokko/rokko/serial_dense_ev.hpp:344:47: note: implicit instantiation first required here
    : solver_impl_(detail::sd_solver_factory::instance().make_product(solver_name)) {}
                                              ^
t-sakashita commented 1 year ago

https://stackoverflow.com/questions/11962918/local-static-variable-is-instantiated-multiple-times-why https://stackoverflow.com/questions/4193639/inline-function-linkage/4193698#4193698

t-sakashita commented 1 year ago

https://stackoverflow.com/questions/15062767/heap-dynamic-vs-static-memory-allocation-for-c-singleton-class-instance

t-sakashita commented 1 year ago

factory.hppを、static local variableをstd::unique_ptrで定義するのが、一番筋が良い。

  static inline factory& instance() {
    static const std::unique_ptr<factory> instance_(std::make_unique<factory>());
    return *instance_.get();
  }

関数のinline宣言は不要かも。

minij.pyの実行で、#391 と同様に、ソルバが見つからないというエラーが発生する。 その理由は、pythonラッパーにおいて、sd_solver_factoryを実体化できていないためだろう。

t-sakashita commented 1 year ago

static inline std::unique_ptr<factory> instance_をmagic Staticsで生成すると、このinstance_はクラス外から見えなくなるので、他のヘッダファイルdeclare_factory_instance.hppで宣言できない。 instance_の代わりに、static inline int largest_priority_をクラス外で宣言してみた。

#define ROKKO_DECLARE_FACTORY_INSTANCE(T) \
template<> \
int  T::largest_priority_;

Mac+clangで、minij.pyを実行すると、固有値ソルバが一つも登録されていなかった。