Sign in to follow this  
Firecore

What is a singleton?

Recommended Posts

hi guys. sorry if this is a really noob question, but what exactly is a singleton? and where does it fit in a game? i came accross the word in one post, googled it but didnt really get any good results.

Share this post


Link to post
Share on other sites
Its an object which encapsulates and manages the instantiation of _ONLY_ one instance of itself. That's usually done through a "GetGlobalInstance()" static method in the object. It checks to see if the global instance has been instantiated yet, if not, it news it and returns that from then on.

You'd use it in a game anywhere you need access to the same global information but dont feel like passing the reference to that information around. For instance, a output logger.

You could pass around a reference to the logger object to every object who needs to log. Or you can make a global instance. If you do that, a singleton is a handy way of making sure that it gets instantiated the first time it's used.

Share this post


Link to post
Share on other sites
Something you should never use, according to most people here on GameDev.Net.

Singleton is a way to make a class "global" throughout the project, and is generally frowned upon by the OO community because it's basically an old fashioned hack to make C++ more like a C with classes language.

Share this post


Link to post
Share on other sites
Quote:
Original post by bzroom
Its an object which encapsulates and manages the instantiation of _ONLY_ one instance of itself.


Quote:
Original post by dbzprogrammer
Singleton is a way to make a class "global" throughout the project


It is both of these. A singleton is a class with global scope of which you can only ever have a single instance. They are generally evil constructs.

Share this post


Link to post
Share on other sites
@The OP: There is a lot of information available out there on the singleton pattern. You might start by reading some of the many singleton-related threads in the forum archives here (you'll learn what they are, and - one hopes - why not to use them).
Quote:
Original post by bzroom
It checks to see if the global instance has been instantiated yet, if not, it news it and returns that from then on.
This is nitpicking, but it doesn't have to be 'newed'; a reference to a local static object can be returned instead (in C++, at least - maybe you had a different language in mind).
Quote:
You'd use it in a game anywhere you need access to the same global information but dont feel like passing the reference to that information around.
Actually, in this case you'd just use a global object. You'd use a singleton when it's preferable (or at least appropriate) for an object to be globally accessable, and when it would be an error for more than one instance to be in existence at any one time. (Incidentally, I have yet to see an example case that meets both of these criteria.)

Share this post


Link to post
Share on other sites
Quote:
Original post by jyk
... You'd use a singleton when it's preferable (or at least appropriate) for an object to be globally accessable, and when it would be an error for more than one instance to be in existence at any one time. (Incidentally, I have yet to see an example case that meets both of these criteria.)


How about a memory manager which is used in a overloaded global new? This is the only instance(the singleton instance you could say :)) where I use it an it fits the pattern.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
How about a memory manager which is used in a overloaded global new? This is the only instance(the singleton instance you could say :)) where I use it an it fits the pattern.

Whaaa? Why would it be impossible to have multiple memory managers? You'd be passing the manager into the new clause anyway.

Share this post


Link to post
Share on other sites
Quote:
Original post by Firecore
so basically a singleton is a class which only allows you to make one instance of that class?

Well, it depends.

A singleton, as singletons are intended to be, is a class which would be impossible to instantiate more than once.

A singleton, as programmers who like to think they're programming in "pure OO" think of it, is a class which they only want to instantiate once.

Either way, there's a mechanism to return the same object over and over rather than creating another one, but this should be looked at as a limitation rather than a feature. If it's the primary reason for having a singleton, you should really just be using a regular global variable.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by dmail
How about a memory manager which is used in a overloaded global new? This is the only instance(the singleton instance you could say :)) where I use it an it fits the pattern.

Whaaa? Why would it be impossible to have multiple memory managers? You'd be passing the manager into the new clause anyway.


I totally agree. Another example is ResourceManagers. You can have multiple of those. Or ObjectManagers...
One trick is not to use the word "manager" in class names. I prefer the word "pool". So I have a ResourcePool and an ObjectPool, perhaps even a MemoryPool.

There are exceptions to the rule in my opinion that have to do with the ease of use of your code/classes. One example is to have a global logging class instance. You could also pass the logger to the constructor of every class, but this can be rather tedious.
On the other hand if you are writing unit tests it may be desirable to be able to pass separate loggers to different class instances.

In a sense the Singleton is in my opinion a lazy programmer's construction. Programmers who are too lazy pass a parameter around resort to the singleton for easy access of functionality.
But it never is that black and white. Generally, try to find a good balance between flexibility and ease of use, and be aware that having a Singleton might hamper your flexibility/design in the future.

Share this post


Link to post
Share on other sites
Quote:
Original post by Sneftel
Quote:
Original post by dmail
How about a memory manager which is used in a overloaded global new? This is the only instance(the singleton instance you could say :)) where I use it an it fits the pattern.

Whaaa? Why would it be impossible to have multiple memory managers? You'd be passing the manager into the new clause anyway.

No I would not be passing the memory manager instance into the new operator, the reason I use this is in debug mode to track memory leaks. Therefore I want the code to work without adjustments and to seem invisible to the user of the code.
Generally it would not be impossible to have more than one memory manager, yet think of it like the heap instance.

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
Generally it would not be impossible to have more than one memory manager, yet think of it like the heap instance.


In short:
1 → It's possible to have more than one memory manager.
2 → A singleton represents objects which can only have a single instance.
1 + 2 ⇒ A singleton does not represent a memory manager.

In this particular case, a global variable is enough, possibly one which is initialized and deinitialized in main(), too.

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by dmail
Generally it would not be impossible to have more than one memory manager, yet think of it like the heap instance.


In short:
1 → It's possible to have more than one memory manager.
2 → A singleton represents objects which can only have a single instance.
1 + 2 ⇒ A singleton does not represent a memory manager.

In this particular case, a global variable is enough, possibly one which is initialized and deinitialized in main(), too.


Notice I say generally, not that you can in my instance and thank you for telling me how to suck eggs I know what a singleton is and what is required to make it a singleton. This board has a real distaste for singletons which is to a certain degree valid, yet everybody goes over the top.
If the instance was initialized in main then it would not be invisible to the user!
1 + 3 = wrong conclusion in my opinion.

I do wonder if the people of this forum would tell Andrei Alexandrescu that he is wrong to use a singleton?

Share this post


Link to post
Share on other sites
Quote:
Original post by dmail
If the instance was initialized in main then it would not be invisible to the user!


How do you guarantee that the object will be created before it's first used, and destroyed after it is last used?

Quote:
Notice I say generally, not that you can in my instance and thank you for telling me how to suck eggs I know what a singleton is and what is required to make it a singleton.


So, you argued that your memory manager cannot have more than one instance, without explaining why your memory manager is so special (since in general a memory manager doesn't have this one-instance restriction), and you wonder why people disagree? After all, you did say:

Quote:
How about a memory manager which is used in a overloaded global new?


I have no problem seeing why people got confused. After all, you said that "a memory manager" is a candidate for a singleton, which is incorrect unless you have a very special memory manager in mind—a mind which the other participants cannot read, to the best of my knowledge. The mature thing here would be to admit that your original statement was badly worded and appeared too general, and explain why your memory manager is so special that it is a singleton.

Your initial post had all the appearance of coming from someone who creates singletons because he doesn't need more than one, as opposed to needing not to have more than one, which is pretty much the reason why people corrected your mistake. If your mistake was in fact just a badly worded post and you actually agree with the correct definition of a singleton, well, I guess everyone will apologize and the thread will go on.

Quote:
I do wonder if the people of this forum would tell Andrei Alexandrescu that he is wrong to use a singleton?


If Andrei Alexandrescu was wrong to use a singleton, then I have no doubt that people in this forum would tell him that he is wrong. I certainly would.

On the other hand, there are many situations where you can use a singleton without it being wrong, and I have certainly done it several times because it was the right thing to do. But in most cases where it is used, it's just unnecessary additional work with no practical result besides preventing you from doing something which you wouldn't have done anyway.

[Edited by - ToohrVyk on March 21, 2008 7:52:50 AM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Structural
In a sense the Singleton is in my opinion a lazy programmer's construction. Programmers who are too lazy pass a parameter around resort to the singleton for easy access of functionality.


I see it as the other way around. Passing around a parameter every time I call a function is cumbersome. Has nothing to do with being a lazy programmer, but more the usability of the final product. I can understand, say, if you just called an initialize function that passed in a reference to the singleton equivalent object, thus giving a class access to the functionality, but semantically you are doing the same thing. You created a single non-static object and you are now passing it around to whatever class needs it. Conceptually, that is no different than having a static class and you call myClass::getInstance()->callSomeFunction(). The latter just makes more sense from a design standpoint, because it encapsulates the functionality away from the user, reducing their need to know what is going on in the function itself.

Share this post


Link to post
Share on other sites
Quote:

I see it as the other way around. Passing around a parameter every time I call a function is cumbersome. Has nothing to do with being a lazy programmer, but more the usability of the final product. I can understand, say, if you just called an initialize function that passed in a reference to the singleton equivalent object, thus giving a class access to the functionality, but semantically you are doing the same thing. You created a single non-static object and you are now passing it around to whatever class needs it. Conceptually, that is no different than having a static class and you call myClass::getInstance()->callSomeFunction(). The latter just makes more sense from a design standpoint, because it encapsulates the functionality away from the user, reducing their need to know what is going on in the function itself.


Conceptually they are totally different. By passing a reference to each function, you give the function caller full control over the function. It could create a temporary object, and pass it to that function. It could call the function twice with different objects.

By using a Singleton, you hard code the value that is passed. The caller cannot change it, the caller *might not be even aware of it*. This is not good design.

Your game is only going to have a single world, right? Therefore, it should be a Singleton, yes? Not so. My game used to have a single world. I did the hard thing - I passed references around. "Hard" is subjective here, there are only a handful of areas of my code that care about the world, so really it was easy. Later on, I had a situation where I wanted two "world" instances to be available at once. I had no problems: I had already set the design such that there was no hardcoded hidden parameter passed anywhere. Had I been lazy and went with a Singleton, I would have had to do a lot of refactoring. Enough refactoring that I may have decided not to have gone with my idea that I wanted two world objects for.

That isn't even mentioning the debugging nightmare that is a globally available object, where you cannot predict where its state is changing.

I have never seen a case where a Singleton is the most appropriate design. There are some cases where I would argue that a global is an *acceptable* design. Which is fine, but don't add the artificial one-instance restriction unless you have an extremely good excuse, or you enjoy refactoring.

Share this post


Link to post
Share on other sites
My professor explained it as this:

In a large project, a singleton is used to make sure an object is instantiated just once. (as said before) But the keyword here is "large project" where you don't want multiple people instantiating multiple instances. What I took away from it is that the Singleton is used as a safety mechanism.

I still don't understand it fully but one of my assignments was this:

I used a singleton which instantiated a factory object. Then I used the factory object to create some shapes to be rendered in directx. So now, no matter how many times you try to create a new factory, it's going to return the original one. This might be good if your factory holds information about each sphere that has been instantiated.

I haven't put any of this into anything practical yet, so I'm sorry if my understanding of the singleton pattern is "off". If so please correct me

Share this post


Link to post
Share on other sites
Quote:
Original post by induster
I used a singleton which instantiated a factory object. Then I used the factory object to create some shapes to be rendered in directx. So now, no matter how many times you try to create a new factory, it's going to return the original one. This might be good if your factory holds information about each sphere that has been instantiated.

I haven't put any of this into anything practical yet, so I'm sorry if my understanding of the singleton pattern is "off". If so please correct me
The problem with this is that you don't take into consideration the idea of object factory's purpose. A good way to think of it is, "who has responsibility of this object or who's going to be using it". Who has responsibility for the factory object? By making it a singleton it's like saying no one has responsibility of it or that it has responsibility for itself. In say a game an entity factory might be part of an EntityManager where it's used to instantiate objects given a string. You have to think very hard as to whether you need it to be a singleton.

Honestly (and I've said this before), if you are making a game or large project one main class should contain all the managers which in turn are passed references to the main class. This allows everything to access anything that main contains which is normally all you want. Have a memoryManager well it's just a single instance in the main class. Also (and this won't happen if you legitimately require a singleton) you are programming and decide you need two memoryManager's then you can change it with little hassle compared to a singleton.

(I've never actually found a reason for using one, but I'm sure there might be a reason).

Share this post


Link to post
Share on other sites
Quote:
Passing around a parameter every time I call a function is cumbersome. Has nothing to do with being a lazy programmer, but more the usability of the final product.
A couple of comments on this. First of all, passing around references to a local object rather than making the object global forces you to think carefully about who really needs access to the object, and who doesn't. This is a good thing, IMO. If, for example, you make your sound manager/pool/cache object a singleton, then your renderer is going to have direct access to the sound manager. How much sense does that make?

As far as 'usability' goes, consider:
// Singleton:
void Render() const {
Renderer::Get().RenderSomeStuff(...);
}

// Parameter:
void Render(Renderer& renderer) const {
renderer.RenderSomeStuff(...);
}
The latter is, IMO, more flexible and reusable. I'm not sure how you define 'usability', but the latter example seems more 'usable' to me, generally speaking.
Quote:
I can understand, say, if you just called an initialize function that passed in a reference to the singleton equivalent object, thus giving a class access to the functionality, but semantically you are doing the same thing.
I might be misunderstanding you here, but it doesn't seem like the same thing to me. If you use a singleton, every object shares access to the same global object. If you pass in a reference which is then stored locally, you have more options available to you in terms of how objects relate to each other. Regardless of which of these methods you prefer, I think it's pretty clear that they're not equivalent.
Quote:
You created a single non-static object and you are now passing it around to whatever class needs it. Conceptually, that is no different than having a static class and you call myClass::getInstance()->callSomeFunction().
Again, it is different. In the first case, the object is created locally, and only the objects that are granted access to it have access to it. In the second case, anyone can access the object. IMO, the conceptual difference is pretty clear.
Quote:
The latter just makes more sense from a design standpoint, because it encapsulates the functionality away from the user, reducing their need to know what is going on in the function itself.
I think I see what you're getting at, but remember that now you have a very rigid dependency within the function, which is a problem in and of itself.

Share this post


Link to post
Share on other sites
Some random points which I feel point to the C++ standard's committee thinking multipletons are not the answer:

1) Option to overload new/delete on a per-class level
2) Option to switch allocator type on all standard library containers via template argument
3) Options to pass allocator instances on all standard library containers via constructor.

Share this post


Link to post
Share on other sites
Singletons aren't necessarily bad, they're just usually used improperly.

The thing to remember about them is that the key is that they limit instantiation, *not* that they are globally accessible.

You should use a singleton when *really bad things* will happen if two of the same object exist at the same time.

As an example, an object representing a config file might be a good candidate. If two objects exist, both of which represent the same config file, it's very possible that saving both of them will result in one set of the changes getting wiped out. By making sure that any time you get an object representing a particular config file, you always have the same object, you can prevent a good number of these potential issues.

Things like resource managers aren't really good candidates for being singletons. Generally, the author might like to think of there only being one of them, but there's no real harm in having multiples. If you're using a singleton just to avoid parameter passing, you should seriously rethink it.

Share this post


Link to post
Share on other sites
Quote:
Original post by kyoryu
The thing to remember about them is that the key is that they limit instantiation, *not* that they are globally accessible.
You should use a singleton when *really bad things* will happen if two of the same object exist at the same time.
As an example, an object representing a config file might be a good candidate. If two objects exist, both of which represent the same config file, it's very possible that saving both of them will result in one set of the changes getting wiped out. By making sure that any time you get an object representing a particular config file, you always have the same object, you can prevent a good number of these potential issues.

class Config
{
public:
Config(const std::string& path) : mPath(path)
{
if( sSet.find(path) != sSet.end() ) throw std::string("Config file already open ") + path;
sSet.insert(path);
}
~Config()
{
sSet.erase(mPath);
}
// user functions
private:
Config() : mPath("") {}
Config(const Config& c) : mPath("") {}
private:
const std::string mPath;
static std::set<std:.string> sSet;
};

I should really learn to use boost::noncopyable, but that aside - that code describes the basic idea.

If you need several references to the same file, you probably want something like a pool with shared_ptr and weak_ptr's like:
class ConfigPool
{
public:
boost::shared_ptr<Config> Get(const std::string& path);
private:
std::map<std::string, boost::weak_ptr<Config> > mOpenConfigs;
};

See, no need for singletons :)

Share this post


Link to post
Share on other sites
Quote:
Original post by sirGustav
boost::shared_ptr<Config> Get(const std::string& path);

See, no need for singletons :)
This is effectively a singleton, albeit a broken one. There is a subtle problem with this approach, which can bite you very painfully. I know that because I've been bitten before.

At first, your approach will work exactly the way a singleton should: it generates an instance of an object (and only one), and passes that to whoever needs it. User code doesn't have to care where it comes from, it is "just there".
So far so good, however, when the last reference to the shared_ptr goes out of scope, the instance will be deleted, and the next call to Get() will retrieve a different, newly created object.
In some cases, this does not matter, in some cases, this has undesired side effects (not only performance), and in some cases, it can be the cause of a hard to track crash.
The problem is, if you get the case where it causes a crash, you don't even know what hit you.

Share this post


Link to post
Share on other sites
Quote:
Original post by rip-off
I have never seen a case where a Singleton is the most appropriate design. There are some cases where I would argue that a global is an *acceptable* design. Which is fine, but don't add the artificial one-instance restriction unless you have an extremely good excuse, or you enjoy refactoring.


A Singleton does not require lots of refactoring—the worst that could happen is that you remove the one-instance-only restriction once it's not useful anymore. However, hard-coded references to global symbols require refactoring to make them parametric, but there is nothing about the singleton pattern which forces you to reference it from everywhere in your code—most of my singleton-using code involves referencing it in main and then passing it by reference everywhere.

Quote:
Original post by abso
I see it as the other way around. Passing around a parameter every time I call a function is cumbersome. Has nothing to do with being a lazy programmer, but more the usability of the final product.


This is the crux of the issue, with the key concept being parametrability. Any human tool contains hard-coded elements and customizable elements, though the ration between the two varies. A tool with a lot of customizable elements is difficult to use, because you have to customize it every time you use it—this involves the possibility of error and the requirement to think about how to use that tool. A tool with very few customizable elements, while being easy to use, has a very narrow scope: there are only a few things you can change about its behavior, and you have to use another tool if it doesn't fit.

Consider this example where I make almost everything parametrable: values, types, functions...

// Get the maximum of a set of integers
int max(int *buf, size_t s)
{
int m = std::numeric_limits<int>::min();
while (s-- > 0) m = std::max(*buf++, m);
return m;
}

// Make the type of the elements parametric
// (You can use it on 'float' now)
template<typename T>
T max(T *buf, size_t s)
{
if (s-- == 0) return T();
T m = *buf++;
while (s-- > 0) m = std::max(*buf++, m);
return m;
}

// Make the type of the input sequence parametric
// (You can use it on 'std::list' elements now)
template<typename It>
typename std::iterator_traits<It>::value_type
max(It begin, It end) {
typedef typename std::iterator_traits<It>::value_type T;
if (begin == end) return T();
T m = *buf++;
while (s-- > 0) m = std::max(*buf++, m);
return m;
}

// Make the applied operation parametric
// (You can now compute the sum)
template<typename It, typename F>
typename std::iterator_traits<It>::value_type
accumulate(It begin, It end, F f) {
typedef typename std::iterator_traits<It>::value_type T;
if (begin == end) return T();
T m = *buf++;
while (s-- > 0) m = f(*buf++, m);
return m;
}

// Make the initial value parametric
// (this is now a valid 'fold' operation)
template<typename It, typename F>
typename std::iterator_traits<It>::value_type
fold(It begin, It end, F f,
typename std::iterator_traits<It>::value_type m)
{
while (s-- > 0) m = f(*buf++, m);
return m;
}




Now, for every parameter in a tool, there are three levels of specification:

  • Per-use: the user can select a new value for the parameter every time he uses the tool. A typical example is the std::sqrt function: every time you call the function, you can specify a new parameter value.

    This is extremely powerful, but quite cumbersome if you need to specify the same parameters every time... which is why people often use:

  • Per-instance: the user creates an instance of the tool, and provides the value of the parameter to the instance. This is very interesting, because you don't have to repeatedly specify the same parameters, yet you are allowed a choice. A typical example is std::mem_fun_ref, which allows you to specify the function to be called (once) and the object it should be called (several times, once per object).

    The downside is that, while the creator of the instance can select the parameter values, the user can't. Also, this can also be cumbersome, since there are many possible parameters which will simply never change at all in any practical situation... which is why people also resort to:

  • Hard-coded values: this parameter was set when the tool was developed, and cannot be changed by the user. A typical example is the value of PI/180.0f when converting degrees to radians: while making this value a parameter to the function would allow you to specify a better-precision value for the number, it simply won't happen in any practical situation.


When you notice that your tool is too narrow, you will have to add one or more parameters. This is a necessary process which necessarily involves refactoring. The real question is, if you don't know yet exactly what your tool will be used for, how narrow should you make it? The decision of whether to make something a hard-coded, per-instance or per-use parameter is generally made by choosing between two evils: adding a feature which you don't need is a waste of time and the earlier you add a feature, the easier it is. Ideally, you'd never write a feature you don't need, and you'd add features you need as soon as you can implement them, but we live in a non-ideal world with fuzzy or changing requirements, so this is impossible. And thus, you have to strike a balance: How probable is it for this parameter to be required? How difficult will it be to make it parametric right now? How difficult will it be to make it parametric later?

  • Hard-coded immutable values are extremely easy to turn into parameters: these are types, modules, constants and stateless functions. Because they are immutable, using them always happens in a vacuum, and as such you don't have to care about anything but the function you're refactoring when you make these things parametric.

  • Hard-coded mutable values are extremely difficult to turn into parameters: these are global variables, singletons, monostates and stateful functions. Because they are mutable, they create a runtime dependency with other parts of your program, and you must then determine how the parametrization of that value will impact those other parts of your program before applying your changes. This not only spreads the work to initially unrelated code (such as changing the renderer when you're refactoring the sound system) but it also creates the possibility of error if you fail to notice an interaction.


Given the cost difference between the two, almost everyone argues that it's better to make mutable values parametric right away, and make immutable values parametric only if the need arises. Note that this is by no means a concept related only to object-oriented programming: parametric or hard-coded specifications of immutable and mutable values are just as important for procedural, generic and functional programming (though I admit that purely function programming, having no mutable state, doesn't care about that difference).

Quote:
You created a single non-static object and you are now passing it around to whatever class needs it.


Your problem is not that you have a singleton in your code, and converting the singleton to a single non-static object to try and avoid this problem will not have any effect whatsoever. The issue is that you designed several classes as needing a single object—if your classes cannot work with another object (for instance a temporary dummy object you create for the purpose of a quick simulation or to save/load from file), then you have an implicit hard-coded specification of a mutable object. The right way to correct the dependency problem is to design a class in a way which does not assume that you will pass it The Object, as opposed to any object with this interface.

Share this post


Link to post
Share on other sites
Quote:
Original post by samoth
Quote:
Original post by sirGustav
boost::shared_ptr<Config> Get(const std::string& path);

See, no need for singletons :)
This is effectively a singleton, albeit a broken one.

It is a pool, not a singleton. A singleton is:
Quote:
GoF said
Singleton: Ensure a class only has one instance, and provide a global point of access to it.


Quote:
There is a subtle problem with this approach, which can bite you very painfully. I know that because I've been bitten before.

At first, your approach will work exactly the way a singleton should: it generates an instance of an object (and only one), and passes that to whoever needs it. User code doesn't have to care where it comes from, it is "just there".
So far so good, however, when the last reference to the shared_ptr goes out of scope, the instance will be deleted, and the next call to Get() will retrieve a different, newly created object.
In some cases, this does not matter, in some cases, this has undesired side effects (not only performance), and in some cases, it can be the cause of a hard to track crash.
The problem is, if you get the case where it causes a crash, you don't even know what hit you.


True that may be a problem, or not, depending what you are doing with your class. As I tend to apply this on a somewhat similar problem(asset management) I am wondering where it actually bit you, and what that undesired effect might be? Ignoring the performance, since that can be easily dealt with, the only problem that I can see is if you are relying on that the pointer should be the same, either it is used as a id or you are using naked pointers somewhere else.

Please correct me if I made some error, my mind is kinda tired atm :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this