Date: Wed, 28 Jun 2023 00:47:36 +0100
I think the most efficient implementation of a "construct on demand"
object would work as follows:
https://godbolt.org/z/dx6YTKnnj
And here it is copy-pasted:
#include <atomic> // atomic
#include <optional> // optional
#include <mutex> // once_flag, call_once, mutex, lock_guard
#include <iostream> // Just for testing: 'cout'
#include <thread> // Just for testing: 'jthread'
struct T {
T(void) { std::cout << "Constructing. . .\n"; }
~T(void) { std::cout << "Destroying. . .\n" ; }
void Speak(void) { std::cout << "Hi!\n"; }
};
std::optional<T> g_optional;
/* forward declaration of function */ T &Func_PreInit(void);
std::atomic<T &(*)(void)> g_funcptr{ &Func_PreInit };
static std::mutex g_mutex_for_optional;
T &Func_Init(void)
{
std::cout << "> > > Func_Init\n";
std::lock_guard mylock(g_mutex_for_optional);
return g_optional.value();
}
std::once_flag g_flag_for_optional{};
T &Func_PreInit(void)
{
std::cout << "> > > Func_PreInit\n";
std::call_once(g_flag_for_optional, []()
{
std::lock_guard mylock(g_mutex_for_optional);
g_optional.emplace();
});
g_funcptr.store( &Func_Init );
std::lock_guard mylock(g_mutex_for_optional);
return g_optional.value();
}
#define g_obj (g_funcptr.load()())
int main(void)
{
g_obj.Speak();
std::jthread mythread( [](){ g_obj.Speak(); } );
g_obj.Speak();
}
object would work as follows:
https://godbolt.org/z/dx6YTKnnj
And here it is copy-pasted:
#include <atomic> // atomic
#include <optional> // optional
#include <mutex> // once_flag, call_once, mutex, lock_guard
#include <iostream> // Just for testing: 'cout'
#include <thread> // Just for testing: 'jthread'
struct T {
T(void) { std::cout << "Constructing. . .\n"; }
~T(void) { std::cout << "Destroying. . .\n" ; }
void Speak(void) { std::cout << "Hi!\n"; }
};
std::optional<T> g_optional;
/* forward declaration of function */ T &Func_PreInit(void);
std::atomic<T &(*)(void)> g_funcptr{ &Func_PreInit };
static std::mutex g_mutex_for_optional;
T &Func_Init(void)
{
std::cout << "> > > Func_Init\n";
std::lock_guard mylock(g_mutex_for_optional);
return g_optional.value();
}
std::once_flag g_flag_for_optional{};
T &Func_PreInit(void)
{
std::cout << "> > > Func_PreInit\n";
std::call_once(g_flag_for_optional, []()
{
std::lock_guard mylock(g_mutex_for_optional);
g_optional.emplace();
});
g_funcptr.store( &Func_Init );
std::lock_guard mylock(g_mutex_for_optional);
return g_optional.value();
}
#define g_obj (g_funcptr.load()())
int main(void)
{
g_obj.Speak();
std::jthread mythread( [](){ g_obj.Speak(); } );
g_obj.Speak();
}
Received on 2023-06-27 23:47:48