Use of function local statics

As part of my moving code from Host to HostInfo, I moved some function-local statics to global class-member statics. The reason for this is that MSVC doesn’t support thread-safe function local statics until VS2014, which is still only in technology preview, whereas LLVM, clang, and by extension LLDB support building as far back as VS2012.

Greg submitted r216080 to convert these global statics back to function-local statics, but this had a bug in it which broke things for all platforms, so I reverted it in r216123. A simple fix would have just been to address the bug, but my original transition from function-local statics to global statics was intentional due to the fact that any use of them on a non-primitive type is undefined behavior on MSVC.

So, I want to see if people have a strong preference one way or the other. If the issue is just silencing the compiler warning that clang gives about global constructors, then we can do that in CMake and/or the Xcode project. On the other hand, I understand that global static constructors increase application startup times. Is this a concern for anyone? If so, I can try to come up with a solution. I think if we try to keep the use of statics to a minimum, and make sure that they are generally simple types (e.g std::string, which simply does a malloc), then there should be no noticeable performance impact on startup.

Thoughts?

For our build submissions here at Apple we need to keep the number of global constructors to a minimum. We need to apply for exceptions for each global constructor that is added to a shared library or framework. This is the main reason for the change I made. global constructors are fine for apps and they get to make that decision, but for shared libraries, they should be avoided if possible.

I would suggest using std::once for any issues you run into:

static std::once_flag g_once_flag;
std::call_once(g_once_flag, [](){
    // Insert code here to run once in a thread safe way
});

std::call_once would solve the problem, but it’s also going to be ugly putting that all over the place. Another potential solution is to do something like this:

// HostInfoBase.h
class HostInfoBase
{
public:
static void Initialize();

private:
static HostInfoFields *m_fields;
};

// HostInfoBase.cpp

struct HostInfoFields

{
uint32_t m_number_cpus;
std::string m_lldb_shared_library_path;
// etc
};

HostInfoFields *HostInfoBase::m_fields = nullptr;

void HostInfoBase::Initialize()
{
m_fields = new HostInfoFields();
}

// lldb-main.cpp
int main(int argc, char **argv)
{
HostInfo::Initialize();
}

Thoughts?

BTW, another problem with std::call_once is that, like thread-safe function local statics as well, any kind of thread synchronization is undesirable if it can be avoided.

We already have global place for intialization:

lldb_private::Initialize ()

This is in lldb.cpp. Feel free to add a HostInfoBase::Initialize() to this function. This will solve your problems.

Greg

Thanks. I will submit another patch first (which adds more global statics), and then fix this in a follow-up patch. It’s easier to do it that way rather than submit the fix first and deal with the merge conflict that would arise.