mirror of
https://github.com/NGSolve/netgen.git
synced 2025-01-12 06:00:33 +05:00
Fix static initialization order for UserFormatRegister map
A std::map is in an invalid state when just zero-initialized, and needs to be initialized by its constructor. As this initilization may be done after the first call to Register, a crash will typically happen. To fix this wrap all accesses to the map with a Meyers Singleton. Also remove the extra Array - most accesses are using the key, and the few format list iterations all sort the result afterwards anyway. Fixes #201.
This commit is contained in:
parent
975414c2fe
commit
78782dcd53
@ -16,19 +16,38 @@
|
|||||||
|
|
||||||
namespace netgen
|
namespace netgen
|
||||||
{
|
{
|
||||||
extern MeshingParameters mparam;
|
std::map<std::string, UserFormatRegister::UserFormatEntry>& UserFormatRegister::getFormats()
|
||||||
|
{
|
||||||
|
static std::map<std::string, UserFormatRegister::UserFormatEntry> formats = {};
|
||||||
|
return formats;
|
||||||
|
}
|
||||||
|
|
||||||
Array<UserFormatRegister::UserFormatEntry> UserFormatRegister::entries;
|
void UserFormatRegister::Register(UserFormatRegister::UserFormatEntry && entry)
|
||||||
std::map<string, int> UserFormatRegister::format_to_entry_index;
|
{
|
||||||
|
getFormats()[entry.format] = std::move(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool UserFormatRegister::HaveFormat(string format)
|
||||||
|
{
|
||||||
|
const auto formats = getFormats();
|
||||||
|
return formats.find(format) != formats.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
const UserFormatRegister::UserFormatEntry & UserFormatRegister::Get(string format)
|
||||||
|
{
|
||||||
|
return getFormats()[format];
|
||||||
|
}
|
||||||
|
|
||||||
|
extern MeshingParameters mparam;
|
||||||
|
|
||||||
void RegisterUserFormats (NgArray<const char*> & names,
|
void RegisterUserFormats (NgArray<const char*> & names,
|
||||||
NgArray<const char*> & extensions)
|
NgArray<const char*> & extensions)
|
||||||
|
|
||||||
{
|
{
|
||||||
for (const auto & entry : UserFormatRegister::entries)
|
for (const auto & entry : UserFormatRegister::getFormats())
|
||||||
{
|
{
|
||||||
names.Append (entry.format.c_str());
|
names.Append (entry.second.format.c_str());
|
||||||
extensions.Append (entry.extensions[0].c_str());
|
extensions.Append (entry.second.extensions[0].c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,32 +28,23 @@ struct UserFormatRegister {
|
|||||||
optional<FRead> read;
|
optional<FRead> read;
|
||||||
optional<FWrite> write;
|
optional<FWrite> write;
|
||||||
};
|
};
|
||||||
DLL_HEADER static Array<UserFormatEntry> entries;
|
static void Register(UserFormatEntry && entry);
|
||||||
DLL_HEADER static std::map<string, int> format_to_entry_index;
|
|
||||||
|
|
||||||
static void Register(UserFormatEntry && entry) {
|
static const bool HaveFormat(string format);
|
||||||
format_to_entry_index[entry.format] = entries.Size();
|
DLL_HEADER static const UserFormatEntry & Get(string format);
|
||||||
entries.Append( std::move(entry) );
|
|
||||||
}
|
|
||||||
|
|
||||||
static const bool HaveFormat(string format) {
|
|
||||||
return format_to_entry_index.count(format) > 0;
|
|
||||||
}
|
|
||||||
static const UserFormatEntry & Get(string format) {
|
|
||||||
return entries[format_to_entry_index[format]];
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename TFunc>
|
template<typename TFunc>
|
||||||
static void IterateFormats(TFunc func, bool need_read=false, bool need_write=false) {
|
static void IterateFormats(TFunc func, bool need_read=false, bool need_write=false) {
|
||||||
Array<string> import_formats;
|
Array<string> import_formats;
|
||||||
for(const auto & e: entries)
|
for(const auto & e: getFormats())
|
||||||
if((!need_read || e.read) && (!need_write || e.write))
|
if((!need_read || e.second.read) && (!need_write || e.second.write))
|
||||||
import_formats.Append(e.format);
|
import_formats.Append(e.second.format);
|
||||||
QuickSort(import_formats);
|
QuickSort(import_formats);
|
||||||
for(auto format : import_formats)
|
for(auto format : import_formats)
|
||||||
func(entries[format_to_entry_index[format]]);
|
func(Get(format));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLL_HEADER static std::map<std::string, UserFormatEntry>& getFormats();
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RegisterUserFormat {
|
struct RegisterUserFormat {
|
||||||
|
@ -700,7 +700,8 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
|
|||||||
|
|
||||||
string export_docu = "Export mesh to other file format. Supported formats are:\n";
|
string export_docu = "Export mesh to other file format. Supported formats are:\n";
|
||||||
Array<string> export_formats;
|
Array<string> export_formats;
|
||||||
for(auto & e : UserFormatRegister::entries)
|
for(auto & kv : UserFormatRegister::getFormats()) {
|
||||||
|
const auto e = kv.second;
|
||||||
if(e.write) {
|
if(e.write) {
|
||||||
string s = '\t'+e.format+"\t("+e.extensions[0];
|
string s = '\t'+e.format+"\t("+e.extensions[0];
|
||||||
for(auto & ext : e.extensions.Range(1, e.extensions.Size()))
|
for(auto & ext : e.extensions.Range(1, e.extensions.Size()))
|
||||||
@ -708,6 +709,7 @@ DLL_HEADER void ExportNetgenMeshing(py::module &m)
|
|||||||
s += ")\n";
|
s += ")\n";
|
||||||
export_formats.Append(s);
|
export_formats.Append(s);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
QuickSort(export_formats);
|
QuickSort(export_formats);
|
||||||
for(const auto & s : export_formats)
|
for(const auto & s : export_formats)
|
||||||
export_docu += s;
|
export_docu += s;
|
||||||
|
Loading…
Reference in New Issue
Block a user