Preemptive Threads and Singletons

Setting a class up as a singleton is not uncommon:

Shared Function SharedInstance() As MyClass
  If mSharedInstance Is Nil Then
    mSharedInstance = New MyClass
  End If
  Return mSharedInstance
End Function

mSharedInstance is a shared property, so you’d just call MyClass.SharedInstance to get to the singleton. It’s kind of like a module, but since it’s a class, it gets a constructor for initialization and can have additional instances if necessary.

With preemptive threads, since it can be possible to run the same line across multiple threads at the same time, the test and creation needs to be locked if I’m not mistaken:

Shared Function SharedInstance() As MyClass
  If mInstanceLock Is Nil Then
    mInstanceLock = New CriticalSection
  End If

  mInstanceLock.Enter
  If mSharedInstance Is Nil Then
    mSharedInstance = New MyClass
  End If
  mInstanceLock.Leave
  Return mSharedInstance
End Function

But… doesn’t this have the same problem? Detection and creation of the instance can now be synchronized between threads, but the lock used to do so is now vulnerable.

The best idea I’ve come up with is just a Call MyClass.SharedInstance on the main thread before any preemptive threads are started. Which kind of begs the question: why use a singleton instead of a module, if I have to call what is essentially an init routine anyway? A singleton is self-initializing, but I can’t think of a way to pull that off with preemptive threads.

I feel like I’m missing something simple though.

Most of my stuff has an initialization function that sets up shared properties, handlers, and/or self setup. I call the init function from App.Opening to make sure it is set up before anything else can run. This also allows me to have optional modules that can register themselves, their pages and properties, all from one place.

You could have a shared initialization function that sets up the CriticalSection or a global CriticalSection/Mutex that is used for initializing other CriticalSections?

I could yes. But that makes the components less self-contained. If I have a class that I want to reuse in a project, I can’t just bring it over and use it, I also have to bring it over and remember to initialize it. So my goal is to retain the self-initialization.

Im wondering if a try/catch on “mInstanceLock.Enter” could achieve what you are trying to do.

Both module and singleton have to be initialised somewhere.

Yeah. Achieving self initialization is typically done inside the getter function of a singleton, or inside a private init method of a module that gets called from every global or protected method. I typically prefer the singleton approach rather than sprinkling calls to init all over the place.