Singleton pattern for multi-processing on Pharo 10.0 ( Smalltalk )

131 views Asked by At

I can't pass the test below.

"SingletonTest"
testCurrent
        
    | semaphore object1 object2 |
    Singleton initialize.

    semaphore := Semaphore new.

    [ 
    Processor yield.
    object1 := Singleton current.
    semaphore signal ] fork.

    object2 := Singleton current.

    semaphore wait.
    self assert: object1 identicalTo: object2

Here is my first implementation which is failed.

"Singleton class"
current

    Transcript
        show: 'start';
        cr. 
    current := current ifNil: [ 
                   Transcript
                       show: 'creating..';
                       cr.
                   self new ].
    ^ current

initialize

    isProcessing := false.
    current := nil

I have tried to pass the test by using a naive exclusion control but the result was same. Here is my second implementation.

"Singleton class"
current

    [ isProcessing ] whileTrue: [  ].
    isProcessing := true.
    current := current ifNil: [ 
                   (Delay forSeconds: 2) wait.
                   self new ].
    isProcessing := false.
    ^ current

initialize

    isProcessing := false.
    current := nil

How can I pass the test? I'm looking forward to hearing your tips!

1

There are 1 answers

9
James Foster On

Your code for #'initialize' resets the current so that is why you are getting two different values. Try deleting all but the first call to #'initialize'.

Note also that race conditions are tricky things. In the first implementation of #'current' you have a two-second delay in which you could create two instances of Singleton. In the second implementation you could have two threads find isProcessing to be false and find current to be nil so both wait for two seconds and create it.

To guarantee that you get only one instance, you should set up the instance during your setup code or protect the creation with a Semaphore.