Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

11991 Posts in 1587 Topics- by 3508 Members - Latest Member: PienueDut

26. May 2012, 09:39:23 am
Xith3D CommunityGeneral CategoryGeneral Discussion (Moderators: Marvin Fröhlich, 'n ddrylliog)Singleton Pattern
Pages: [1]
Print
Author Topic: Singleton Pattern  (Read 1451 times)
qbproger
developers
Becoming dependent
***
Offline Offline

Posts: 217


View Profile
« on: 10. December 2008, 02:04:54 pm »

I know I've seen the singleton pattern used around Xith a bit.  I found these two articles interesting about the pattern:

http://www.infoq.com/articles/code-optimization-singleton
http://crazybob.org/2007/01/lazy-loading-singletons.html

qb
Logged

Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #1 on: 12. December 2008, 04:13:36 pm »

The second article by Crazy Bob looks interesting. Though for me the solution looks as if it was still not thread safe. But since it seems to have become a common way, I guess, it actually is Smiley. Thanks for the hint, dude.

Marvin
Logged
qbproger
developers
Becoming dependent
***
Offline Offline

Posts: 217


View Profile
« Reply #2 on: 13. December 2008, 03:06:19 am »

No Problem.

Yea, I found the link to the second one in the comments of the first article.  I liked the second article more also.

I'm pretty sure it is thread safe because <class init> runs only 1 time for each class even if 2 threads are accessing it.

qb
Logged

starscream
Enjoying the stay
*
Offline Offline

Posts: 25


View Profile
« Reply #3 on: 14. December 2008, 08:33:57 am »

I can not see the problem.

Why not using this:

static {
    instance == new Singleton();
}

public static Singleton getInstance() {
  return instance;
}

The instance will be created while classloading, but his should be fine, because the class will only be loaded if the singleton is used.
Is there a problem using this?
Logged
qbproger
developers
Becoming dependent
***
Offline Offline

Posts: 217


View Profile
« Reply #4 on: 14. December 2008, 02:00:17 pm »

Yea, that's probably how I'd implement it.  I don't see a problem with it...
Logged

Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #5 on: 15. December 2008, 01:18:43 am »

If you don't have any static methods, that can be used without the need for the singleton instance, this simpler solution should be 100% fine.

Marvin
Logged
Mathias 'cylab' Henze
Fierce Warrior
****
Offline Offline

Posts: 540

1064620
View Profile WWW
« Reply #6 on: 15. December 2008, 10:24:15 am »

The instance will be created while classloading, but his should be fine, because the class will only be loaded if the singleton is used.
Is there a problem using this?

This is the non-lazy-loading variant of the singleton pattern. It is ok as long as you are sure, you always need the singleton or the resource costs of having an the singleton instantiated can be neglected. Also some time you need a singleton to be lazy because of certain preconditions have to be achieved before the instantiation (like for example registration of resources or environment-settings influencing the singletons behaviour).

Other than that, if you design an API, singletons should be avoided, because of the sideeffects they introduce. The singletons in xith are there for historic reasons and because they make certain parts of the engine more convenient.
Logged

cowwoc
Just dropped in

Offline Offline

Posts: 14


View Profile
« Reply #7 on: 27. February 2009, 01:07:35 am »

Any chance we can drop singletons in favor of some IoC? That is:

TextureBag textureBag = TextureBag.getInstance();

// becomes

@Inject
TextureBag textureBag;

... I don't have a problem with singletons in general but I've noticed that the XIN documentation showed "setting" singletons and retrieving them later:

Code:
Bag.setInstance(foo);
...
Bag.getInstance();

That looked very ugly and dangerous from a thread-safety point of view.

Gili

The instance will be created while classloading, but his should be fine, because the class will only be loaded if the singleton is used.
Is there a problem using this?

This is the non-lazy-loading variant of the singleton pattern. It is ok as long as you are sure, you always need the singleton or the resource costs of having an the singleton instantiated can be neglected. Also some time you need a singleton to be lazy because of certain preconditions have to be achieved before the instantiation (like for example registration of resources or environment-settings influencing the singletons behaviour).

Other than that, if you design an API, singletons should be avoided, because of the sideeffects they introduce. The singletons in xith are there for historic reasons and because they make certain parts of the engine more convenient.
Logged
Marvin Fröhlich
Xith Lord
Administrator
Guru
*****
Offline Offline

Posts: 4381


May the 4th, be with you...


View Profile
« Reply #8 on: 27. February 2009, 02:03:56 am »

Could you please describe that @Inject annotation a little more? It doesn't seem to be part of the standard Java annotation set.

Setting those singletons shouldn't be a problem, since you will set the singleton at loading time and use it after loading time. You will never have to re-set it when it is once set.

Marvin
Logged
Mathias 'cylab' Henze
Fierce Warrior
****
Offline Offline

Posts: 540

1064620
View Profile WWW
« Reply #9 on: 02. March 2009, 12:39:32 pm »

Any chance we can drop singletons in favor of some IoC? That is:

TextureBag textureBag = TextureBag.getInstance();

// becomes

@Inject
TextureBag textureBag;
There is currently no plan to use a DI/IoC container in xith. While I agree with you that it would be nice, it would require a radical change in the engine API. I do however use Pico with custom injectors in my game to implement game states:

Code:
public class Menu implements GameState
{
    private HUD gui;
    private BranchGroup scene;
    private RenderPass renderPass = null;
    private Panel mainPanel;
    private ModelAnimation[] avatarAnims;
    private MD2Model avatarModel;
    private GameContext context;

    // <editor-fold defaultstate="collapsed" desc="Dependencies">
    @Required
    public void setSceneGraph( SceneGraph sceneGraph )
    {
        this.sceneGraph = sceneGraph;
    }
    protected SceneGraph sceneGraph;

    @Required
    public void setCanvas( Canvas3D canvas )
    {
        this.canvas = canvas;
    }
    protected Canvas3D canvas;

    @Required
    public void setGameManager( GameManager gameManager )
    {
        this.gameManager = gameManager;
    }
    protected GameManager gameManager;

    @Required
    public void setResourceLocator( ResourceLocator resourceLocator )
    {
        this.resourceLocator = resourceLocator;
    }
    protected ResourceLocator resourceLocator;

    @Required
    public void setInputSystem( InputSystem inputSystem )
    {
        this.inputSystem = inputSystem;
    }
    protected InputSystem inputSystem;

    @Optional
    public void setController( Controller controller )
    {
        this.controller = controller;
    }
    protected Controller controller;

    @Required
    public void setScheduler( OperationScheduler scheduler )
    {
        this.scheduler = scheduler;
    }
    protected OperationScheduler scheduler;

    @Required
    public void setMd2Loader( MD2Loader md2Loader )
    {
        this.md2Loader = md2Loader;
    }
    protected MD2Loader md2Loader;

    @Required
    public void setLevelManager( LevelManager levelManager )
    {
        this.levelManager = levelManager;
    }
    protected LevelManager levelManager;
    // End dependencies </editor-fold>

    @Initializer
    public void initialize()
    {
        try
        {
            scene = new BranchGroup();
            setupBackGround();
            setupGui();
        }
        catch( Exception exception )
        {
            exception.printStackTrace();
        }
    }
       
    public void enter( GameContext context )
    {
        this.context= context;
        sceneGraph.addHUD( gui );
        scheduler.addAnimatableObject( avatarModel  );
        renderPass = sceneGraph.addPerspectiveBranch( scene );
        sceneGraph.getView().lookAt( -30,30,-30, -10,10,-10, 0,1,0 );
    }

    public void leave( GameContext context )
    {
        scheduler.removeAnimatableObject( avatarModel );
        sceneGraph.removeHUD( gui );
        sceneGraph.removeBranchGraph( scene );
        sceneGraph.removeRenderPass( renderPass );
    }
    // (...)
}

So my main class more or less only consists of registering components to the container:

Code:
        MutablePicoContainer container = new DefaultPicoContainer( new Caching().wrap( new CombinedInjection() ) );
        container.change( Characteristics.CACHE );
        container.addComponent( this );
        container.addComponent( Shutdown.class );
        container.addComponent( container );
        container.addComponent( env );
        container.addComponent( physEng );
        container.addComponent( collEng );
        container.addComponent( gfxManager );
        container.addComponent( resLoc );
        container.addComponent( md2Loader );
        container.addComponent( inputSystem );
        container.addComponent( getOperationScheduler() );
        container.addComponent( env.getCanvas() );
        container.addComponent( activeController );
        container.addComponent( EntityManager.class );
        container.addComponent( GameManager.class );
        container.addComponent( LevelManager.class );
        container.addComponent( Editor.class );
        container.addComponent( Intro.class );
        container.addComponent( Menu.class );
        container.addComponent( Settings.class );
        container.addComponent( LevelEngine.class );
        container.addComponent( Outro.class );
        container.addComponent( TestJAXB.class );
        container.addComponent( ThreadManager.class );

        gameManager = container.getComponent( GameManager.class );
        gameManager.switchTo( Intro.class );

I want to make a blog article about this soon.

That looked very ugly and dangerous from a thread-safety point of view.
Xith is designed to be single threaded while rendering. You can do your math in an off-render-thread but have to make sure yourself to get the results to the rendering thread in a thread safe manner. Usually you use ScheduledOperations for this.


Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic