Jump to page: 1 2 3
Thread overview
Singleton Pattern with struct
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Maxim Fomin
Jan 24, 2013
Jacob Carlborg
Jan 24, 2013
Maxim Fomin
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Maxim Fomin
Jan 24, 2013
Era Scarecrow
Jan 24, 2013
Maxim Fomin
Jan 24, 2013
Era Scarecrow
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Ali Çehreli
Jan 24, 2013
Maxim Fomin
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Ali Çehreli
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Artur Skawina
Jan 24, 2013
ParticlePeter
Jan 24, 2013
Ali Çehreli
Jan 24, 2013
Artur Skawina
Jan 24, 2013
Artur Skawina
Jan 24, 2013
ParticlePeter
January 24, 2013
Hi,

I am trying to figure out the singleton pattern with a struct instead of a class:
[code]
struct Singleton  {

private :
	this( int a = 0 ) {} ;
	static Singleton * s ;

public :
	@disable this() ;
	static ref Singleton instance()  {
		if ( s is null )
			s = new Singleton( 0 ) ;
		return * s ;
	}
	
	int val = 0 ;
}
[/code]

This compiles, but when I use it:
[code]
	auto s = Singleton.instance ;
	writeln( s.val ) ;

	Singleton.instance.val = 2 ;
	writeln( s.val ) ;
[/code]

I get:
0
0

Where is my mistake ?

Cheers, PP !
January 24, 2013
On Thursday, 24 January 2013 at 14:11:10 UTC, ParticlePeter wrote:
> Hi,
>
> I am trying to figure out the singleton pattern with a struct instead of a class:
> [code]
> struct Singleton  {
>
> private :
> 	this( int a = 0 ) {} ;
> 	static Singleton * s ;
>
> public :
> 	@disable this() ;
> 	static ref Singleton instance()  {
> 		if ( s is null )
> 			s = new Singleton( 0 ) ;
> 		return * s ;
> 	}
> 	
> 	int val = 0 ;
> }
> [/code]
>
> This compiles, but when I use it:
> [code]
> 	auto s = Singleton.instance ;
> 	writeln( s.val ) ;
>
> 	Singleton.instance.val = 2 ;
> 	writeln( s.val ) ;
> [/code]
>
> I get:
> 0
> 0
>
> Where is my mistake ?
>
> Cheers, PP !

Even if Singleton.instance returns by ref, s object is still stack-allocated struct, which is not affected by further modification of private pointer.

import core.stdc.stdio : printf;

struct Singleton  {

private :
        this( int a = 0 ) {} ;
        static Singleton * s ;

public :
        @disable this() ;
        static ref Singleton instance()  {
                if ( s is null )
                        s = new Singleton(0) ;
                return * s ;
        }

        int val = 0 ;
}

void main()
{
	auto s = Singleton.instance ;
        printf( "%d\n", s.val ) ; //0

        Singleton.instance.val = 2 ;
        printf( "%d\n",  s.val ) ; // also 0
	printf( "%d\n", Singleton.instance.val); // is 2 as expected
}
January 24, 2013
On 2013-01-24 15:43, Maxim Fomin wrote:

> Even if Singleton.instance returns by ref, s object is still
> stack-allocated struct, which is not affected by further modification of
> private pointer.

The struct is allocated using "new".

-- 
/Jacob Carlborg
January 24, 2013
> Even if Singleton.instance returns by ref, s object is still stack-allocated struct, which is not affected by further modification of private pointer.

But where and when is ( a second  ? ) Singleton created or duplicated ? The only ctor is in the static instance ( it is called only once according to my debugger ) and allocates a Singleton instance on the Heap ( as far as I understand "new Struct" ). The return statement does return a reference ( to a pointer, even that shouldn't be necessary ) so I would expect ... well a reference and not a copy. So where does the second object come from ?
January 24, 2013
On Thursday, 24 January 2013 at 15:05:15 UTC, Jacob Carlborg wrote:
> On 2013-01-24 15:43, Maxim Fomin wrote:
>
>> Even if Singleton.instance returns by ref, s object is still
>> stack-allocated struct, which is not affected by further modification of
>> private pointer.
>
> The struct is allocated using "new".

This is about "auto s = " in main, not about "new" in method. Type of s is Singleton, not Singleton* or "ref Singleton".

Singleton s = Singleton.instance; // is compiled when
Singleton* s = Singleton.instance; // is not - Error: cannot implicitly convert // expression (instance()) of type Singleton to Singleton*
January 24, 2013
Got it, thanks, I changed the instance method to:
[code]
	static Singleton * instance()  {
		if ( s is null )
			s = new Singleton( 0 ) ;
		return s ;
	}
[\code]

and everything works as expected.

Cheers, PP !

January 24, 2013
On Thursday, 24 January 2013 at 15:50:34 UTC, ParticlePeter wrote:
> Got it, thanks, I changed the instance method to:
> [code]
> 	static Singleton * instance()  {
> 		if ( s is null )
> 			s = new Singleton( 0 ) ;
> 		return s ;
> 	}
> [\code]
>
> and everything works as expected.
>
> Cheers, PP !

Yes, but this can be broken by:

import core.stdc.stdio : printf;

struct Singleton  {

private :
        this( int a = 0 ) {} ;
        static Singleton * s ;

public :
        @disable this() ;
        static Singleton* instance()  {
                if ( s is null )
                        s = new Singleton(0) ;
                return s ;
        }

        int val = 0 ;
}

void main()
{
        Singleton s = * Singleton.instance;
        printf( "%d\n", s.val ) ; //
        Singleton.instance.val = 2 ;
        printf( "%d\n", s.val ) ; //0
}

Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
January 24, 2013
On Thursday, 24 January 2013 at 16:07:36 UTC, Maxim Fomin wrote:
> Yes, but this can be broken by:

> void main()
> {
>         Singleton s = * Singleton.instance;
>         printf( "%d\n", s.val ) ; //
>         Singleton.instance.val = 2 ;
>         printf( "%d\n", s.val ) ; //0
> }
>
> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.

 I'm not sure but this seems like one of the few appropriate places i would just make a normal struct and just use a global variable. True there could 'be' multiple instances of these singletons, but only ever making one ensures it would work right so long as you cannot copy it. Wasn't disabling this(this) and opAssign the way to ensure that didn't happen?

 Course if you didn't and you relied on the instance one, and you cannot copy then you could only pass by reference or be required to use .instance every time you needed it. Seems a bit excessive.


 Hmmm. You could separate the data and remove the pointer... then use alias this.

[code]
  struct Singleton {
    static SingletonData single;
    alias single this;
    @disable this(this);
    //disable copy/assignment? Not that it would matter...
    //copying nothing does nothing, as there's nothing here.

    private static struct SingletonData {
      //methods and data here.
    }
  }
[/code]
January 24, 2013
On Thursday, 24 January 2013 at 16:17:34 UTC, Era Scarecrow wrote:
> On Thursday, 24 January 2013 at 16:07:36 UTC, Maxim Fomin wrote:
>> Yes, but this can be broken by:
>
>> void main()
>> {
>>        Singleton s = * Singleton.instance;
>>        printf( "%d\n", s.val ) ; //
>>        Singleton.instance.val = 2 ;
>>        printf( "%d\n", s.val ) ; //0
>> }
>>
>> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.
>
>  I'm not sure but this seems like one of the few appropriate places i would just make a normal struct and just use a global variable. True there could 'be' multiple instances of these singletons, but only ever making one ensures it would work right so long as you cannot copy it. Wasn't disabling this(this) and opAssign the way to ensure that didn't happen?
>
>  Course if you didn't and you relied on the instance one, and you cannot copy then you could only pass by reference or be required to use .instance every time you needed it. Seems a bit excessive.
>
>
>  Hmmm. You could separate the data and remove the pointer... then use alias this.
>
> [code]
>   struct Singleton {
>     static SingletonData single;
>     alias single this;
>     @disable this(this);
>     //disable copy/assignment? Not that it would matter...
>     //copying nothing does nothing, as there's nothing here.
>
>     private static struct SingletonData {
>       //methods and data here.
>     }
>  [/code]

I agree, but disabling ctors makes creating module-level object tricky. Static struct initialization might help.
January 24, 2013
> Yes, but this can be broken by:
>
> import core.stdc.stdio : printf;
>
> struct Singleton  {
>
> private :
>         this( int a = 0 ) {} ;
>         static Singleton * s ;
>
> public :
>         @disable this() ;
>         static Singleton* instance()  {
>                 if ( s is null )
>                         s = new Singleton(0) ;
>                 return s ;
>         }
>
>         int val = 0 ;
> }
>
> void main()
> {
>         Singleton s = * Singleton.instance;
>         printf( "%d\n", s.val ) ; //
>         Singleton.instance.val = 2 ;
>         printf( "%d\n", s.val ) ; //0
> }
>
> Here s is explicitly defined to be a struct object, not pointer (reference), so main.s is independent of further modification of Singleton.instance.

O.k. good to know, I'll try to avoid this. But one thing is still not clear,
This method here ( my first approach ) does return a reference to an object on the heap, right ?

static ref Singleton instance()  {
	if ( s is null )
		s = new Singleton( 0 ) ;
	return * s ;
}

so when I use it with:
auto another_s = Singleton.instance ;

Why is the s inside the struct and another_s not identical ?
Afaik that is the purpose of the ref keyword ?





« First   ‹ Prev
1 2 3