473,383 Members | 1,877 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,383 software developers and data experts.

Is Singleton collection of Singletons possible??

Let's say I'm writing a business app and I want there to be only one
instance of the Customer object for each particular customer (representing a
database record) being edited.

Would it be possible to extend the Singleton pattern to handle this?

Assuming that my Customer class follows the Singleton pattern (particularly
Skeet's 4th version) I'm thinking if I add

private static SomeCollectionType customers;

and then change the factory to something like

public static GetCustomer(Guid customerID)
{
// check collection and return existing instance if found
// create new instance and return if not
}

I think I have my mind around the static and singleton concepts, but need to
make sure.
Nov 15 '05 #1
11 2149
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Let's say I'm writing a business app and I want there to be only one
instance of the Customer object for each particular customer (representing a
database record) being edited.

Would it be possible to extend the Singleton pattern to handle this?
Sort of - it would then be called the Factory pattern though :)
Assuming that my Customer class follows the Singleton pattern (particularly
Skeet's 4th version) I'm thinking if I add

private static SomeCollectionType customers;

and then change the factory to something like

public static GetCustomer(Guid customerID)
{
// check collection and return existing instance if found
// create new instance and return if not
}

I think I have my mind around the static and singleton concepts, but need to
make sure.


That would be fine - but for thread-safety you should basically have a
lock which is acquired *every* time GetCustomer is called. The fourth
singleton pattern isn't really much use to you here. The second pattern
is much closer to what you'd need to use.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #2
Yeah but I would need the Factory to be a Singleton also or it defeats the
purpose. So I need a GetFactory() and then a GetCustomer() I guess.

As to the locking... help me sort this out in my head. The problem is two
threads could call GetCustomer() right? Since that isn't addressed by the
Singleton nature of the factory itself the locks are required.

So I could follow the 4th pattern for the factory itself and then use the
locks within GetCustomer(). Right? Not that the locking in the overall
pattern probably matters much at that point since I'm going to be locking
left and right in the other method anyway.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Let's say I'm writing a business app and I want there to be only one
instance of the Customer object for each particular customer (representing a database record) being edited.

Would it be possible to extend the Singleton pattern to handle this?


Sort of - it would then be called the Factory pattern though :)
Assuming that my Customer class follows the Singleton pattern (particularly Skeet's 4th version) I'm thinking if I add

private static SomeCollectionType customers;

and then change the factory to something like

public static GetCustomer(Guid customerID)
{
// check collection and return existing instance if found
// create new instance and return if not
}

I think I have my mind around the static and singleton concepts, but need to make sure.


That would be fine - but for thread-safety you should basically have a
lock which is acquired *every* time GetCustomer is called. The fourth
singleton pattern isn't really much use to you here. The second pattern
is much closer to what you'd need to use.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #3
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Yeah but I would need the Factory to be a Singleton also or it defeats the
purpose. So I need a GetFactory() and then a GetCustomer() I guess.
Well, the factory methods themselves needn't be part of an instance -
you don't need to have a separate class. Any reason not just to have a
static GetCustomer method?
As to the locking... help me sort this out in my head. The problem is two
threads could call GetCustomer() right?
Yes.
Since that isn't addressed by the
Singleton nature of the factory itself the locks are required.
Yes.
So I could follow the 4th pattern for the factory itself and then use the
locks within GetCustomer(). Right?
Yes, if you want to.
Not that the locking in the overall
pattern probably matters much at that point since I'm going to be locking
left and right in the other method anyway.


Right.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #4
Yes I think I see your point. There's no need for there to ever be an
instance of the factory, as it's only purpose is to expose the static
GetCustomer() (in a Singleton way, of course).

I think I understand that while I could be assured there is only one static
collection, multiple threads calling GetCustomer() could be adding, objects
to it, which would most likely result in a mess. In other words, it's the
fact that my main Singleton object is a collection type, which is by
definition continually changing, that's the problem.

But it appears maybe Microsoft is ahead of me. This is from the Thread
Safety section for HybridDictionary:
"Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.

This implementation does not provide a synchronized (thread-safe) wrapper
for a HybridDictionary, but derived classes can create their own
synchronized versions of the HybridDictionary using the SyncRoot property.

Enumerating through a collection is intrinsically not a thread-safe
procedure. Even when a collection is synchronized, other threads could still
modify the collection, which causes the enumerator to throw an exception. To
guarantee thread safety during enumeration, you can either lock the
collection during the entire enumeration or catch the exceptions resulting
from changes made by other threads."

So if my singleton factory inherited from this HybridDictionary and followed
the fourth pattern, am I good, since 1) the factory itself would be a
singleton and 2) the public static collection would is thread-safe? (The
above caveat about enumeration taken into account, of course)

Or are they just locking internally anyway when they say it is thread-safe?

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Yeah but I would need the Factory to be a Singleton also or it defeats the purpose. So I need a GetFactory() and then a GetCustomer() I guess.


Well, the factory methods themselves needn't be part of an instance -
you don't need to have a separate class. Any reason not just to have a
static GetCustomer method?
As to the locking... help me sort this out in my head. The problem is two threads could call GetCustomer() right?


Yes.
Since that isn't addressed by the
Singleton nature of the factory itself the locks are required.


Yes.
So I could follow the 4th pattern for the factory itself and then use the locks within GetCustomer(). Right?


Yes, if you want to.
Not that the locking in the overall
pattern probably matters much at that point since I'm going to be locking left and right in the other method anyway.


Right.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #5
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Yes I think I see your point. There's no need for there to ever be an
instance of the factory, as it's only purpose is to expose the static
GetCustomer() (in a Singleton way, of course).
Well, in a thread-safe way, effectively.
I think I understand that while I could be assured there is only one static
collection, multiple threads calling GetCustomer() could be adding, objects
to it, which would most likely result in a mess. In other words, it's the
fact that my main Singleton object is a collection type, which is by
definition continually changing, that's the problem.

But it appears maybe Microsoft is ahead of me. This is from the Thread
Safety section for HybridDictionary:
"Public static (Shared in Visual Basic) members of this type are safe for
multithreaded operations. Instance members are not guaranteed to be
thread-safe.
That's not particularly unique to HybridDictionary, of course. Most
classes in .NET are documented in that way...
So if my singleton factory inherited from this HybridDictionary and followed
the fourth pattern, am I good, since 1) the factory itself would be a
singleton and 2) the public static collection would is thread-safe? (The
above caveat about enumeration taken into account, of course)

Or are they just locking internally anyway when they say it is thread-safe?


I'm afraid I've lost the plot slightly at this point - but I'm sure
you'll have to do *some* locking yourself to get the behaviour you
want. A simple implementation of:

static Hashtable customers = new Hashtable();

static object padlock = new object();

static Customer GetCustomer (string id)
{
lock (padlock)
{
if (!customers.ContainsKey(id))
{
customers[id] = new Customer(id);
}
return (Customer) customers[id];
}
}

or something similar would be your best bet, I believe.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #6
Sorry I lost you - it's my confusion rubbing off probably. :) I realize
that thread-safe claim would be true of most if not all of the collection
classes.

I don't think your example below assures there is only one collection, does
it? Or did you just intentionally leave out those details?

My thinking is that since MS says the collections are thread-safe I wouldn't
need to worry about the locking if GetCustomer(). In the case of the
Hashtable there's a synchronized wrapper, so this is what I'm thinking: (Of
course, if all the syncronized version is doing is using locks anyway than
it probably doesn't matter.)

public class CustomerCollection
{

static CustomerCollection customers = new CustomerCollection();
static CustomerCollection syncedCustomers =
Hashtable.Synchronized(customers);

static CustomerCollection()
{
}

private CustomerCollection()
{
}

public static Customer GetCustomer(string id)
{
if (!syncedCustomers.ContainsKey(id))
{
syncedCustomers[id] = new Customer(id);
}
return (Customer) syncedCustomers[id];
}

}
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
I'm afraid I've lost the plot slightly at this point - but I'm sure
you'll have to do *some* locking yourself to get the behaviour you
want. A simple implementation of:

static Hashtable customers = new Hashtable();

static object padlock = new object();

static Customer GetCustomer (string id)
{
lock (padlock)
{
if (!customers.ContainsKey(id))
{
customers[id] = new Customer(id);
}
return (Customer) customers[id];
}
}

or something similar would be your best bet, I believe.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #7
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Sorry I lost you - it's my confusion rubbing off probably. :) I realize
that thread-safe claim would be true of most if not all of the collection
classes.

I don't think your example below assures there is only one collection, does
it? Or did you just intentionally leave out those details?
It ensures there's only one collection per AppDomain, certainly -
because it's only created when the static initializer runs.
My thinking is that since MS says the collections are thread-safe I wouldn't
need to worry about the locking if GetCustomer().


No, because you need to go through the process of:

1) Test if the customer is already there
2) If it is, return it
3) If not, create a new customer and put it in the collection

Another thread could come in and request the same ID between steps 1
and 3, meaning you end up with two customers for the same ID. Only each
individual step is thread-safe without locking - you need to
effectively do the whole operation atomically.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #8
Well, of course. But for thread-safeness it's the 3rd step that is of
significance. That is to say, setting aside my specific application, the
problem is two threads attempting to add the same ID. I take "A Hashtable
can support one writer and multiple readers concurrently. To support
multiple writers, all operations must be done through this wrapper only." to
mean the synchronized Hashtable itself wouldn't allow that, and I'd end up
with an ArgumentException. How do you take it? (That's assuming I use the
Add method which maybe is not the code you posted before as I recall.)

Now, that's not to say that using locking isn't better than dealing with the
exceptions, if that's where you'll go next. I'll have to evaluate that. I
just want to make sure I'm understanding these concepts correctly first
though.

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
My thinking is that since MS says the collections are thread-safe I wouldn't need to worry about the locking if GetCustomer().


No, because you need to go through the process of:

1) Test if the customer is already there
2) If it is, return it
3) If not, create a new customer and put it in the collection

Another thread could come in and request the same ID between steps 1
and 3, meaning you end up with two customers for the same ID. Only each
individual step is thread-safe without locking - you need to
effectively do the whole operation atomically.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #9
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
Well, of course. But for thread-safeness it's the 3rd step that is of
significance. That is to say, setting aside my specific application, the
problem is two threads attempting to add the same ID. I take "A Hashtable
can support one writer and multiple readers concurrently. To support
multiple writers, all operations must be done through this wrapper only." to
mean the synchronized Hashtable itself wouldn't allow that, and I'd end up
with an ArgumentException. How do you take it? (That's assuming I use the
Add method which maybe is not the code you posted before as I recall.)
No, you wouldn't end up with an ArgumentException - you'd end up with
each call locking all other calls out until it completed.
Now, that's not to say that using locking isn't better than dealing with the
exceptions, if that's where you'll go next. I'll have to evaluate that. I
just want to make sure I'm understanding these concepts correctly first
though.


The problem is that if two different threads can both reach step 2, you
create more than one object for the same ID, which is usually a bad
move.

With threading, I always take the "simple is best" approach: while
you're dealing with shared data, take out a lock. I think people
generally believe that locks are more expensive than they really are.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #10

"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om...

No, you wouldn't end up with an ArgumentException - you'd end up with
each call locking all other calls out until it completed. <snip> The problem is that if two different threads can both reach step 2, you
create more than one object for the same ID, which is usually a bad
move.

Doesn't that contradict the doc, which explicitly says it supports multiple
writers in a thread-safe way? For the Add method it says the
ArgumentExeption means "An element with the same key already exists in the
Hashtable".

Up through Steps 3a, nothing has yet been created in the Hashtable. At that
point the two threads only "think" they're going to add the same key.
According to the information in the doc, one of them will ultimately fail in
step 3b.
With threading, I always take the "simple is best" approach: while
you're dealing with shared data, take out a lock. I think people
generally believe that locks are more expensive than they really are.

I agree, which is why I will evaluate whether just adding the locking would
be simpler than dealing with the exceptions. I expect it will. At this
point I'm trying to figure out why we're understanding Microsoft's
explanation of this so differently. Maybe at this point we're just using
different symantecs.

The doc also says "Even when a collection is synchronized, other threads
could still modify the collection, which causes the enumerator to throw an
exception. To guarantee thread safety during enumeration, you can either
lock the collection during the entire enumeration or catch the exceptions
resulting from changes made by other threads."

Although it doesn't say so, I would expect the same problem to exist with
Contains() and ContainsKey() which I would expect are just enumerating
through under the hood. That being the case, I've got to handle several
possible exceptions and I think just locking myself is indeed way simpler.

Here's the steps again, for reference
1) Test if the customer is already there
2) If it is, return it
3) If not, (a) create a new customer and (b) put it in the collection

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Nov 15 '05 #11
Daniel Billingsley <db**********@NO.durcon.SPAAMM.com> wrote:
No, you wouldn't end up with an ArgumentException - you'd end up with
each call locking all other calls out until it completed. <snip>
The problem is that if two different threads can both reach step 2, you
create more than one object for the same ID, which is usually a bad
move.


Doesn't that contradict the doc, which explicitly says it supports multiple
writers in a thread-safe way?


Not at all.
For the Add method it says the
ArgumentExeption means "An element with the same key already exists in the
Hashtable".
Assuming you use Add rather than the indexer, that just means you'll
get an ArgumentException - which isn't a good thing, is it?
Up through Steps 3a, nothing has yet been created in the Hashtable. At that
point the two threads only "think" they're going to add the same key.
According to the information in the doc, one of them will ultimately fail in
step 3b.
Yes, but that's hardly a good way of working, IMO.
With threading, I always take the "simple is best" approach: while
you're dealing with shared data, take out a lock. I think people
generally believe that locks are more expensive than they really are.


I agree, which is why I will evaluate whether just adding the locking would
be simpler than dealing with the exceptions. I expect it will. At this
point I'm trying to figure out why we're understanding Microsoft's
explanation of this so differently. Maybe at this point we're just using
different symantecs.


Locking would be simpler, more elegant, and almost certainly about as
performant.
The doc also says "Even when a collection is synchronized, other threads
could still modify the collection, which causes the enumerator to throw an
exception. To guarantee thread safety during enumeration, you can either
lock the collection during the entire enumeration or catch the exceptions
resulting from changes made by other threads."

Although it doesn't say so, I would expect the same problem to exist with
Contains() and ContainsKey() which I would expect are just enumerating
through under the hood.


No, because they can take out the internal synchronization lock for the
whole of their operation.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Nov 15 '05 #12

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

14
by: lawrence | last post by:
To call I would do something like: $headline = McSelectJustOneField::callDatastore("cbHeadline"); Is this the correct use of the static keyword, to implement a Singleton design?
4
by: Eric | last post by:
Perhaps this question has been posed before (I'd be surprised if it hasn't) but I just gotta know... Is it possible to combine the Singleton and Factory Method design patterns in the same class?...
13
by: Stampede | last post by:
I woundered if the following would be possible: I want to create an abstract Singleton class, which implements the singleton behaviour with the limitation, that the unique object will not be...
21
by: Sharon | last post by:
I wish to build a framework for our developers that will include a singleton pattern. But it can not be a base class because it has a private constructor and therefore can be inherit. I thought...
2
by: Rick | last post by:
A coworker has brought up the following quote from a book as confirmation that we cannot use Singletons in ASP.Net application code, at least at the ASP.Net tier. I am looking for references to...
4
by: Simon Hazelton | last post by:
Is it possible in VB.net to have a single or singleton instance of a class per specific database record. I'm writing an auction site and have a problem with resolving proxy bids, effectively I...
9
by: Marcel Hug | last post by:
Hallo NG ! I Have a little question about inheritance of a singleton class. In my application i have a Database-Connection Lib, in which I would šlike to connect different databases of the same...
7
by: ThunderMusic | last post by:
Hi, I have a problem regarding singletons in C#. What I would like to do is the following ClassA is a singleton ClassB inherits from ClassA and is also a Singleton there cannot and instance of...
3
weaknessforcats
by: weaknessforcats | last post by:
Design Pattern: The Singleton Overview Use the Singleton Design Pattern when you want to have only one instance of a class. This single instance must have a single global point of access. That...
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.