Jump to content

Singleton Design Pattern


Recommended Posts

Has anyone implemented a better example of the singleton pattern than the one that ships with LV. I really don't like the use of a library to hide the class. It requires a method in the library and then one on the class to actually do the work. This seems redundant, I would prefer to see the details of the queue hidden in the class and not require the use of the library.

Any ideas??

Link to comment

Hi

I'm a GDS fan (no wounder biggrin.gif ), so I just right click in the Project Tree amd selectes New->GOOP Class (Using The Endevo's Reference based provider).

Then I just select a singelton class type, it's so easy :-)

post-941-125918066954_thumb.png

post-941-125918074263_thumb.png

..one advantage I like about this template (or any GDS class templates) is that if there is a new version of the class template I've used, the GDS toolkit can automatically update the class to the new template.

Cheers,

Mikael

Link to comment

Ok. I really want to know: Why do you need Singleton? What are you using it for? I implemented the example that ships with LabVIEW because lots of people wanted to see some implementation for it. But I honestly am not sure why you want it in LabVIEW. In C++ it makes perfect sense, but not so much in LabVIEW. At least, that's my opinion. Now, you can ask why I would think a construct would be useful in one language and useless in another... I have an answer, but I'd rather not share it at the moment. First I'd like to know what you're doing with these Singleton classes. I have yet to be convinced that it is a useful pattern in LabVIEW.

Link to comment

post-941-12592272902_thumb.png

Singleton or not…

I often use Singleton classes, it might be because I’m lazy wiring the class wire through all my application.

Here is a brief description of why I use singletons.

This is how my standard implementation of my manufacturing rigs looks like.

I use a top level VI, and some singleton classes and a bunch of instrument driver classes.

Let’s look at the current rig I’m working on.

This rig should:

1. Place, align and glue 3 optical components on the DUT.

2. Every component is held by a motorized stage with 4-5 axis.

3. Every stage has about 7-10 additional digital IOs

4. There is an over all vision system with 2 cameras with different lighting controls.

5. There is an additional optical measurement system I’m using for alignment.

In total it’s about 50 IOs in the system from simple position sensors, pneumatic values to 13 motorized stages, cameras, glue dispense systems and other more advanced measurement system.

So where should I start when implementing a large system like this?

I start by looking at the system from an operator’s perspective, what can I see?

I see 3 separate motor stages.

I see a camera and lighting arm, holding 2 cameras and some lamps.

So I decide to create 3 classes, one for every motor stage, this is because they look completely different and hold different components.

I name the classes after what component they are holding.

So one stage will be called “Mirror”-class, and I choose to use a singleton class here.

So why do I use a singleton class?

I know that I will only use one of these objects in my application, but the main reason is that I don’t want to clutter the block diagram of my Main VI, that is going to use this object ;-)

This “Mirror”-class will aggregate all instrument objects it needs, e.g. 4 motion control motors.

This class will encapsulate all functions I might need to perform on the Mirror component.

I will have a public method (a method that my main VI will call) named “Pick up and place mirror at initial location”, and also one called “Cure Mirror Glue”.

These methods will be a bit abstract and I let the method figure out how to perform these actions.

That way I get a good abstraction level, and it’s easy to follow the application flow in my Main VI.

I never allow my main VI to access the instruments direct, so I’m forced to go through an abstraction layer.

By using this approach, I can break down the complex system into smaller solvable parts, in my case I use classes.

And for this project I use only singleton classes in my application component layer that abstracts the driver layer from the main VI.

post-941-12592273265_thumb.png

Cheers,

Mikael

Link to comment
  • 2 weeks later...

I can think of several good uses of a singleton class. For starters the application can have a log file. We will want to add entries to the log file anywhere in the application, including in parallel tasks. Now, let's say we give the user the ability to change the name of the log, modify attributes which control what to log, or even if the log itself generates new files based on time or size. I have just named several parameters that control the log that must be shared by all instances of the log. If this needs to be shared why not have a singleton of the class. After all, there is only one log file. Using the current data flow only classes that exist as soon as the wire splits the attributes are duplicated and a change on one branch of the wire will not affect an instance on another branch. In addition to a log any time we have a single instance of something in the system such as a piece of hardware, a network connection or other physical interface we have good candidates for singletons. There are ways to kind of achieve this in LabVIEW such as your example but it would be easier on the programmer if this could be handled automatically if the instance of the class is declared a singleton.

Link to comment

I think the use of the queue for the singleton object is a good choice. I have implemented it is a two-element queue instead and had two copies of the same data in the queue. Locking the queue involved dequeueing one element. Canceling the lock involved reading the remaining entry and writing it back to the queue. I used the lossy enqueue to write new value to the singleton object.

I have used singleton objects when the object will have global affect based on changes from any location in the program. Offhand I can think of logging, error management, security, resource interface/daemon and configuration settings as times I have or might use a singleton object.

Link to comment
I have implemented it is a two-element queue instead and had two copies of the same data in the queue.
Then this wasn't a singleton. By definition, a singleton class allows only one copy of the data to exist anywhere in memory ever. It should be impossible to create a second copy. If you can create a second copy, it's not a Singleton. That's just a reference to an object.
Link to comment

Then this wasn't a singleton. By definition, a singleton class allows only one copy of the data to exist anywhere in memory ever. It should be impossible to create a second copy. If you can create a second copy, it's not a Singleton. That's just a reference to an object.

I read his description as an internal implementation of a singleton object. As long as any class wire accesses the same chunk 'o data it is essentially a singleton regardless of the internal implementation. The two copies on the queue just provide a convenient way for him to cancel a lock without having to requeue the data, as you would have to do with a single element queue.

I encountered the word 'fewton' on wikipedia yesterday (it indeed is a 'singletone'-style object that has a limited number of maximum instances >1).

I searched... no joy.

I thought a fewton was something you slept on. :-)

Sleep? More like a medieval torture device.

Link to comment

It is on the german wikipedia in the article about design patterns (right after singleton)

http://de.wikipedia.org/wiki/Erzeugungsmuster

In the artcle about Singleton, another variant is mentioned: the Multiton.

Another ressource is the following implementation of the Fewtone (german text, but implementation is java/english)

http://www.junit-buch.de/doc/fewton.html

I also found some real examples why you want to have a Fewton. If you have a limited ressource available (network bandwidth), you want to limit the number of processes (number of downloads, torrents ...) that access these, but to a number >1.

Felix

Link to comment

Any ideas??

All right... here's an object I created (LV 2009) to help test out my Interface Framework and make sure it can handle various ways data can be stored. It implements the following techniques to achieve different kinds of data persistence:

ByVal Data - Plain old vanilla Labview

ByRef Data - Data Value Reference

ByRef Data - Unnamed Queue

Static Data - Global Variable

Static Data - Named Queue

Static Data - Functional Global

You can look to see how I implemented them. Beware: I didn't bother to include any locking behavior as I don't need it for what I'm doing. Race conditions will likely pop up all over the place if you use these exact implementations. I'll happily answer any questions, but if you shoot yourself in the foot you can't say you weren't warned. smile.gif

Did I mention I really like vanilla?

I also found some real examples why you want to have a Fewton. If you have a limited ressource available (network bandwidth), you want to limit the number of processes (number of downloads, torrents ...) that access these, but to a number >1.

I can see why you'd want a limited number of certain kinds of objects. Is this limitation something they try to build directly into the class? If so, that seems like an overly-complex way to go about it. Much easier to just create a regular old by-val object to manage a single process and then create a distributor object that has an array of n process objects and sends them off to clients that request them.

Numeric Test Object.zip

Link to comment

Don't forget that the vanilla way in most text based OOP languages is the by-ref design. These cowboys like to shoot around with pointers instead of keeping all safe on the wire.

If I were to create a Fewton'O'Eight, I also would consider a queue, create 8 objects and store them in the queue. Whenever a request is received, dequeue one of these objects. Whenever a object is returned, enqueue it again. I think this approach is simpler than the array (because the objects are not ordered).

Felix

Link to comment

These cowboys like to shoot around with pointers instead of keeping all safe on the wire.

I know... apparently their mommas never taught them it's not polite to point. wink.gif

I think [using queues] is simpler than the array

Yep, you're right.

One potential downside of using a distributor class is that it's relies on cooperative clients that send the object back to the distributor when they are done with it. If a client hangs or forgets to return it you end up losing at least one, and potentially more, of your process objects. If you have a large application with many clients requesting process objects, forgetting to return one of them would show up as slowly decreasing performance over time as the application runs.

I've been wondering if there's a good way to prevent that from happening. I can't think of any way for the distributor object to forcefully recall an object without relying on client-side implementation. If the process objects are active objects you could implement a self-destruct mechanism that operates either from an internal watchdog timer or on a message from the distributor. Once the object has been destroyed the distributor could create a new process object and put it on the internal queue. I haven't prototyped this so I don't know how messy it would get or if it's even feasible.

I'm not sure how well a self-destruct message would work with vanilla objects. In principle you wouldn't want to create a replacement process object until you've confirmed that the old process object was destroyed, but the client controls the object's execution and it's possible that object will never execute again.

If I were to create a Fewton'O'Eight...

My point was that whereas a singleton is something that is built into the class itself, a fewton that is implemented using a distributor is an artifact of the way the objects are being managed. It could be a useful term to describe the programmer's intent, but I believe it is incorrect to describe a class as a fewton. (Unless, of course, the class itself limited the number of objects that could be created. I have no idea what that would look like in Labview though.)

Link to comment

I really don't like the use of a library to hide the class.

Incidentally, the singleton example that ships with Labview is a good example of a distributor that manages n vanilla byref objects for clients. The examples I posted are ways to build singleton behavior into a class itself. In general following the distributor pattern provides more flexibility; you can always make a byref object into a singleton but you can't make a singleton into a byref object.

Link to comment

In LV 2009, this is how I would recommend that the Singleton pattern be implemented:

Very nice. star.gif

Is this going to be included as a shipped example in 2010?

(I'm curious, is that implementation something you've been sitting on for a while waiting to see if the community would 'discover' it or did you actually have to sit down and think about it for a while?)

Link to comment
(I'm curious, is that implementation something you've been sitting on for a while waiting to see if the community would 'discover' it or did you actually have to sit down and think about it for a while?)
It's been in my head in theory, but I hadn't had time to type it out. I declined to make it a shipping example in LV 2009 because the DVRs were new and I needed to see how they'd be accepted (or not) by the community. Including it (a cleaned up, more commented version of it) in 2010 is probable if the folks here think it solves the issues.
Link to comment

It's been in my head in theory, but I hadn't had time to type it out. I declined to make it a shipping example in LV 2009 because the DVRs were new and I needed to see how they'd be accepted (or not) by the community. Including it (a cleaned up, more commented version of it) in 2010 is probable if the folks here think it solves the issues.

I like it. One issue I see that doesn't really seem to have a workaround is inheritance. I don't see how it could be done with this model, at least not easily.

Link to comment

I like it. One issue I see that doesn't really seem to have a workaround is inheritance. I don't see how it could be done with this model, at least not easily.

If you mean "make the Singleton inherit from another class", that should work just fine.

If you mean "inherit from the Singleton", that's correct. This particular implementation is not intended to support inheriting from the Singleton. Singletons don't generally have inheritance in my experience -- there's supposed to only be one of them. If you want inheritance, there are variations on this theme that can be applied. All of them involve passing in some sort of "key" that says which Singleton you would like to use or moving to a "get and lock, then operate, then unlock" paradigm. But these are generally undesirable for singletons since even asking the question "which of several singletons do you want?" is somewhat ridiculous, since singleton should mean "there is only one."

Link to comment

If you mean "make the Singleton inherit from another class", that should work just fine.

If you mean "inherit from the Singleton", that's correct. This particular implementation is not intended to support inheriting from the Singleton. Singletons don't generally have inheritance in my experience -- there's supposed to only be one of them. If you want inheritance, there are variations on this theme that can be applied. All of them involve passing in some sort of "key" that says which Singleton you would like to use or moving to a "get and lock, then operate, then unlock" paradigm. But these are generally undesirable for singletons since even asking the question "which of several singletons do you want?" is somewhat ridiculous, since singleton should mean "there is only one."

The application I'm thinking of is an error logger. Within each application there should only ever be one instance of the error logger and I don't want to pass an error logger wire through every vi in my application, hence the singleton makes sense.

I would have a generic error logger class that would work in 90% of my applications. Perhaps that other 10% of the time I want to do add something else to the file or do something slightly different but almost all of the basic functions are the same. It wouldn't make sense to duplicate everything. I think it would make sense to be able to make a child class for that occasion. With this implementation, there doesn't appear to be any easy way to do that.

Is there a better way to go than inheritance to achieve this?

But these are generally undesirable for singletons since even asking the question "which of several singletons do you want?" is somewhat ridiculous, since singleton should mean "there is only one."

That doesn't seem so ridiculous to me. What if your program uses a DMM and at any given time there is only 1 DMM in the system. It would make sense to use a singleton. Now say that DMM could be one of 3 types, it could be Keithley, NI or some other brand. But each performs the same basic functions. It would make sense to have a subclass for each meter that inherits from the generic DMM.

Am I thinking about this the wrong way? I'm kind of new to using classes but to me this seems to make sense. How would you solve a similar problem?

Edited by Stagg54
Link to comment

Just inherit from the class to be used and make it singleton in the last step.

In case of DMMs, you even can inherit two times from XX-DMM to make it XX-DMM1 and XX-DMM2 if there are two present in your system (they most propably will be connected differntly to your DUT or whatever you do with them.

Felix

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.