全局配置的最佳实践

时间:2017-09-29 11:09:45

标签: c++ openmp config yaml-cpp

我有几个c ++程序都在<android.support.v7.widget.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" android:background="?attr/colorPrimary" app:popupTheme="@style/AppTheme.PopupOverlay"> <fragment android:id="@+id/place_autocomplete_fragment" android:name="com.google.android.gms.location.places.ui.PlaceAutocompleteFragment" android:layout_width="match_parent" android:layout_height="match_parent" /> </android.support.v7.widget.Toolbar> 中读取YAML配置文件。我编写了一个从文件中读取配置的函数

/etc/foo/config.yml

(使用YAML::Node load_config(); 库)。

我希望这个配置在我的程序的yaml-cpp函数的开头加载一次,然后在任何地方都可以访问作为某种全局变量。

目前,我的许多功能都有额外参数,这些参数只是从配置文件中读取的值。通过这种全局配置可以避免这种情况,使我的函数定义和调用更加简单和可读。

旁注:我也在使用OpenMP进行分发计算,这意味着所有并行进程都必须可以访问配置。

有人可以给出一个很小的例子,说明在正确的方式下这会是什么样子吗?

谢谢!

1 个答案:

答案 0 :(得分:1)

这是单向的。它是schwartz计数器管理全局单例的一种变体(例如,std::cout本身)

// globals.hpp
#include <istream>

struct globals_object
{
    globals_object()
    {
        // record number of source files which instanciate a globals_object
        ++init_count_;
    }

    ~globals_object()
    {
        // The last source file cleans up at program exit
        if(--init_count_ == 0)
        {
            if (pimpl_)
            {
                delete pimpl_;
            }
        }
    }

    // internal implementation   
    struct impl
    {
        void load(std::istream& is)
        {
            // do loading code here
        }

        int get_param_a() const {
            return a_;
        }

        int a_;
    };

    // (re)load global state    
    void load(std::istream&& is)
    {
        if (pimpl_) delete pimpl_;
        pimpl_ = new impl;
        pimpl_->load(is);
    }

    // public parameter accessor    
    int get_param_a() const {
        return get_impl().get_param_a();
    }

private:    
    static int init_count_;
    static impl* pimpl_;
    static impl& get_impl()
    {
        return *pimpl_;
    }
};
// one of these per translation unit
static globals_object globals;


// globals.cpp

// note - not initialised - will be zero-initialised
// before global constructors are called 
// you need one of these in a cpp file
int globals_object::init_count_;
globals_object::impl* globals_object::pimpl_;


// main file

// #include "globals.hpp"
#include <fstream>

int main()
{
    globals.load(std::ifstream("settings.yml"));

}


// any other file

// #include "globals.hpp"
#include <iostream>

void foo()
{
    std::cout << globals.get_param_a() << std::endl;
}