如何在main之前预加载数据

How to preload data before main

本文关键字:加载 数据 main      更新时间:2023-10-16

我的目标是快速处理各种竞争条件,如果在两个不同的线程中同时调用给定的函数,这些条件可能会导致问题。我的快速解决方法是通过在main()之前调用函数来保证函数已经初始化。这是我想出的解决方案,但我觉得我很可能在重新发明轮子。MSVC2010 STL中是否已有可用选项?(还没有提升)或者,在这种情况下,是否有更好的方法可以快速处理这些问题,而不必为每个函数添加重要的线程安全代码?

template <typename T, T func>
struct PreLoaderHelper
{
    PreLoaderHelper()
    {
        wcout << L"Preload helper constructor" << endl;
        func();
    }
};
template <typename T, T func>
struct PreLoader
{
    static PreLoaderHelper<T, func> _helper;
};
template <typename T, T func>
PreLoaderHelper<T, func> PreLoader<T, func>::_helper;
#define PRELOAD(fn) template struct PreLoader<decltype(&fn), fn>; 
void foo() { wcout << L"inside foo" << endl; }
void bar() { wcout << L"inside bar" << endl; }
vector<wstring> & foobar() 
{ 
    static vector<wstring> sPresidents;
    if(sPresidents.size() == 0)
    {
        sPresidents.push_back(L"George Washington");
        sPresidents.push_back(L"John Addams");
        sPresidents.push_back(L"Thomas Jefferson");
    }
    return sPresidents;
}
wstring foofoo(const wstring &) { wcout << L"inside foofoo" << endl; return L"foofoo";}
PRELOAD(foo);
PRELOAD(bar);
PRELOAD(foobar);
PRELOAD(foo);
int main()
{
    return 0;
}

第一个问题:你以前真的要打电话给他们吗进入main?为什么不直接把它们称为首要任务呢,在启动任何线程之前?

否则:经典的习惯用法是在初始化器中使用它们转换为静态变量。通常的方法是从构造函数;如果您有额外的数据初始化,这无疑是最好的方式。如果不是,像这样简单的东西

static bool initialized = (function(), true);

会成功的。

从形式上讲,这只能保证它们将被初始化在使用了同一翻译单元中的任何其他内容之前,但实际上,这将保证函数被调用在main之前,或者在加载DLL期间,如果它在DLL中除了带main的那个。

您可以这样做:

int dummy = (foo(), (void)0, bar(), 0);
int main() 
{
    // foo() and bar() have already been called
}

此外,C++11保证以下变体只会导致一次无种族的调用:

void call_foo()
{
    static int dummy = (call_foo(), 0);
}
void some_thread_function() { call_foo(); }

如果您使用C++11,请记住:

  1. 静态函数变量初始化是线程安全的
  2. 您可以使用列表初始化语义

尝试:

std::vector<std::wstring>& plop1()
{
    // Thread safe
    // Guaranteed to be done once
    // No setup required
    // No cost if not used.
    static std::vector<std::wstring> sPresidents =
    {   
        L"George Washington",
        L"John Addams",
        L"Thomas Jefferson"
    };  
    return sPresidents;
}

对于您的情况,我强烈建议使用关键部分进行适当的同步。进入和退出关键部分不会添加太多代码,并且可以优雅地处理这种情况。

如果您不想继续使用在main()之前初始化函数的原始方法,可以使用全局变量初始化,因为它发生在main函数调用之前。有一篇关于这种方法的好文章

http://blog.fishingcactus.com/index.php/2009/01/28/fixing-c-static-and-global-variable-initialization/#sthash.pmBtrYD8.dpbs