I've got a class that maintain instance from type class IOSharedDataQueue : public IODataQueue
which is IOKit object.
The class is decoupled and called from various methods of the main class, which is IOKit based class (derived from IOService
).
While trying to convert this class to singleton, I've added the getInstance
function with the following implementation :
myclass& myclass::getInstance()
{
static myclass instance;
return instance;
}
However, it seems that c++11 way of initialize singleton should work in IOKit compiler, and Xcode produces the following error :
This initialization requires a guard variable, which the kernel does not support
The thing is, that it works for classes that does't contain IOKIt based objects.
Perhaps anyone encounter this issue, I haven't seen any documentation of this limitation.
EDIT :
I've found out that if my class Does Not contain any IOResources object in any way, it can designed as a singleton with the guard variable.
However, I still want to be able to create some simple and contained wrappers to be used throughout my IOKit project without passing pointers.
IOKit objects are reference counted, and must always be instantiated with new
and destroyed by calling release()
. So regardless of the fact that thread-safe static initialisers aren't available in kexts, you shouldn't be statically allocating IOKit objects anyway. You can use an atomic pointer or a lock-based mechanism for instantiating your object on first call to the function, or create the instance at a fixed time.
An IOService as an explicit singleton is dubious anyway - are you sure you shouldn't be using IOResource based IOKit matching to create the single instance?
I'm suggesting something along the lines of:
static myclass* singleton_instance;
myclass* myclass::getInstance()
{
if (singleton_instance == nullptr)
{
myclass* new_instance = new myclass();
new_instance->init();
if (!OSCompareAndSwapPtr(nullptr, new_instance, &singleton_instance))
{
new_instance->release();
}
}
return singleton_instance;
}
// TODO: release singleton_instance when kext unloads