如何在main之前预加载数据

时间:2013-02-21 22:47:58

标签: c++ multithreading synchronization

我的目标是快速处理可能导致问题的各种竞争条件,如果在同一时间内在2个单独的线程中调用给定的函数。我的快速修复是通过在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;
}

4 个答案:

答案 0 :(得分:3)

你可以这样做:

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(); }

答案 1 :(得分:3)

第一个问题:你以前真的要打电话给他们吗? 进入主?为什么不把它们称为主要的第一件事, 在开始任何线程之前?

否则:经典成语是在初始化器中使用它们 到一个静态变量。通常的方法是从a调用它们 构造函数;如果您有其他必须的数据 初始化,这无疑是最好的方式。如果不, 简单的事情:

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

会做到这一点。

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

答案 2 :(得分:2)

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

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

    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;
    }
    

答案 3 :(得分:0)

我强烈建议您根据具体情况使用关键部分进行正确的同步。进入和退出关键部分不会添加大量代码并优雅地处理这种情况。

如果您不想继续在main()之前初始化函数的原始方法,则可以在main函数调用之前使用全局变量初始化。

上有一篇关于这种方法的好文章

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