Reputation: 42642
Usually, when I try to initialize a static variable
class Test2 {
public:
static vector<string> stringList;
private:
static bool __init;
static bool init() {
stringList.push_back("string1");
stringList.push_back("string2");
stringList.push_back("string3");
return true;
}
};
// Implement
vector<string> Test2::stringList;
bool Test2::__init = Test2::init();
Although the initialization shall happen before main function (Hence, there can be no threads to simultaneous access the init), my concern is that :
I am using Windows XP, VC6 and VC2008 compiler.
Upvotes: 2
Views: 3912
Reputation: 2996
I asked a similar question a while back:
LoadLibrary and Static Globals
When it comes to DLLs, static initialization and the call to DllMain is bracketed by an internal critical section, so they are thread-safe. A second thread will wait until the first is done before it loads the DLL.
So in short, your static init is safe.
Upvotes: 1
Reputation: 96233
If you need access to these strings prior to main running, this may or may not appear to work depending on how the compiler/linker order initialization.
Better would be to either:
Upvotes: 0
Reputation: 4985
Check out my quick example that demonstrates that your container isn't thread safe.
#include <boost/thread.hpp>
#include <vector>
#include <string>
class NotThreadSafeContainer {
static std::vector<std::string> strings;
static bool is_initialized;
public:
NotThreadSafeContainer() {
if (!is_initialized) {
is_initialized = true;
strings.push_back("string1");
strings.push_back("string2");
strings.push_back("string3");
strings.push_back("string4");
strings.push_back("string5");
}
}
};
bool NotThreadSafeContainer::is_initialized = false;
std::vector<std::string> NotThreadSafeContainer::strings;
void thread_routine() {
while (true) {
// Wow! A container
NotThreadSafeContainer ts_container;
}
};
void main() {
// Uncomment this to remove thread desync errors
// boost::once_flag once_flag = 0;
// boost::call_once(once_flag, thread_routine);
// Start some threads
boost::thread t1(thread_routine);
boost::thread t2(thread_routine);
boost::thread t3(thread_routine);
NotThreadSafeContainer ts_container;
bool SET_BREAKPOINT_HERE;
}
Upvotes: 0
Reputation: 2311
Local static initialization is not thread safe. See http://blogs.msdn.com/oldnewthing/archive/2004/03/08/85901.aspx.
Global static initialization is usually thread safe. You code should work OK.
I normally use a separate init function, and use boost::call_once to ensure that it is called only once.
boost::once_flag boost_once_flag = BOOST_ONCE_INIT;
boost::call_once(init_static_var, boost_once_flag);
Upvotes: 2
Reputation: 57036
No code using identifier names with a double underscore can be considered safe for anything, as it violates the Standard's rules on names reserved for the implementation. The same is true for a name with a leading underscore followed by an uppercase letter, but other names beginning with an underscore may be used, as long as they're not in the global namespace. See the Standard, 17.4.3.1.2. These restrictions are continued in the latest Final Committee Draft for C++0x, under 17.6.3.3.2.
Upvotes: 2
Reputation: 106530
Is the following code thread safe, during static variable initialization?
That depends entirely upon your compiler. The standard says absolutely nothing about multithreading.
Is there any better way to static initialize stringlist, instead of using a seperate static function (init)?
First, you need to remove the __s (That's two underscores) in front of the name; any name beginning with __ is reserved according to the standard. (There are some situations where a single underscore is not allowed either -- it's best just to avoid leading underscores on names altogether)
That depends entirely on whether the vector needs to change during its runtime. If not, you're probably off just using a builtin array:
static const char *strings[] = {
"string1",
"string2",
"string3"
};
Upvotes: 7
Reputation: 60055
it is not thread-safe because several threads can call it simultaneously and you will have stringList initialized twice. Use thread synchronization.
Upvotes: 0