Groups | Blog | Home
all groups > dotnet distributed apps > august 2005 >

dotnet distributed apps : "Singleton" Like Pattern Implementation Suggestions Needed


Rick
8/17/2005 7:46:01 PM
I'm currently developing a distribution .Net Applicaiton utilizing .Net
Remoting for client to server side communication (server side is where all
business rules and workflow is created and controlled). The server side
remoting objects which the clients proxy to are just workflow objects that
then interact with a biz tier. I'm expecting anywhere from 1 to "n" number
of clients utilizing the same server side components for their processing
needs (server side engines all hit the same db).

I'm faced with a situation where i need to increment a counter (of sorts) on
my server side but this needs to follow a "singleton" like pattern. The
application is financial and I need to make sure I do NOT issue duplicate
Check Numbers for a given bank account when i'm producing a check document
(obviously this is a big no-no). On initialization of the bank account
(before i begin to even think about writing checks off of it), I have the
next check number to use (again though, in a real life scenario I could have
two clients who both initialize their own instance of that bank account
object and then try to write checks off of that account).

I can't utilize a traditional singleton object since I could have "n"
clients all trying to write a check off of the same bank account at the same
time. I'm fearing letting the DB handle the check numbering when i persist
the check documents. I'm now searching for other aveneues to implement this
singleton like pattern. Some things i've thought about:

1. COM+ Singleton Object (JIT activate, min and max pool size = 1). On
instantiation, I create a hash table to house the bank account id and next
check number to use. I then can query the object and if that bank account id
exists in the hash table, return back the next check number. If it doesn't,
add the bank account id to the hash table and then update the next number to
use.
2. .Net Caching -- doesn't seem like a great implementation, but could
somehow rig this to work
3. DB Handles Numbering when the check document is persisted -- performance
implications of this?
4. ???
5. ???

If you have any ideas or suggestions, please let me know.

Thanks,

-Rick
Leon Welicki
8/18/2005 1:15:02 AM
Hi Rick,

You can use a Singleton combined with the Double-Check Lock idiom. This way
you can ensure that only one instance of the Singleton exists.

Then, you can serialize the access to the method of singleton object that
issues the check number using the lock sentence (or Monitor). This way, you
won´t give the same number to differente callers (all invocations will be
serialized).

Here are some pointers that may be of help:

"Lock Statement and Thread Synchronization (C# Programmers Reference)"
http://msdn2.microsoft.com/library/ms173179(en-us,vs.80).aspx

"The Monitor Class"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemthreadingmonitorclasstopic.asp

"A Special Dr. GUI: Don´t Lock on Type Objects"
http://msdn.microsoft.com/library/default.asp?url=/archive/en-us/dnaraskdr/html/askgui06032003.asp

"Implementing the Singleton Pattern in C#"
http://www.yoda.arachsys.com/csharp/singleton.html

"Implementing the Singleton Pattern in C#"
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatterns/html/DesSingleton.asp

"Is the C# lock statement FIFO? (first come first serve)"
http://www.dotnet247.com/247reference/msgs/49/246350.aspx

"Safe Thread Synchronization"
http://msdn.microsoft.com/msdnmag/issues/03/01/NET/

"The "Double-Checked Locking is Broken" Declaration"
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html

Hope this helps,

Regards,
Leon Welicki

[quoted text, click to view]
Nigel Norris
8/19/2005 12:00:00 AM

[quoted text, click to view]

Why? It seems the only way to do it if you need guarantees that each number
is used exactly once. For that case you have to increment the check number
as part of the same DB transaction as writing the check. Other solutions may
be able to guarantee that numbers are not re-used, but it is harder to
ensure that all numbers are used (no gaps due to 'dropped' numbers).

If you do use a Singleton-type approach (Remoting supports a Singleton
service type, BTW) you still have to be very careful to ensure that you
don't re-use numbers after your server crashes, especially if you've dished
out numbers to clients. Getting the DB to do it really sounds the easiest
way.

----
Nigel Norris



Nigel Norris
8/19/2005 12:00:00 AM
Double-checked locking is an 'optimization' that you don't even need to
consider for your case. Just adopt one of the simpler patterns that will
work fine.

---
Nigel Norris.

[quoted text, click to view]

Rick
8/19/2005 6:37:04 AM
Leon,

Thanks for the response....Unfortunately with everything i've read (the
links you've provided and other links) it seems as though the Double-Check
Lock is not a recommended pattern (yes MSDN has recommended it, but i've read
a bunch of other material which seem to think it's crazy that MSDN
recommended that approach.

Are there any other possible ways to accomplish what i've set out to do?

Thanks,

-Rick

[quoted text, click to view]
Rick
8/19/2005 8:03:05 AM
It's funny you say that Nigel, because that's how i quickly implemented it so
far. I just fear at times leaving logic in the db as we've consistently
tried to remove all biz logic from the DB and have it live up in the Biz
Tier. That's where my fears lie because now i put a HUGE piece of logic in
the db.

A remoting singleton (thought about this before) won't work because I don't
expose the object that will do the numbering via remoting. I have a
workflow-like tier which is exposed via remoting to clients. That remoting
tier is then what is used to control the flow throughout the server side
(hitting the biz tier, etc...). I can't expose the workflow object that
calls the biz tier object which does numbering either as numbering is only 1
part of a HUGE process that occurs. I don't want to inhibit other clients
from using that workflow object as in some instances, I might not even need
to number checks since all money will be moving electronically.

Again, thanks for your response. For now I'm going to keep the numbering
occuring in the DB (like you've suggested and like i've already implemented)
but continue to look for other avenues to bring this up to the biz tier.

Thanks,

-Rick




[quoted text, click to view]
Leon Welicki
8/19/2005 2:01:02 PM
Hi Rick,

The double check lock should theoretically work on .net and is very easy to
implement. The following piece of code shows how to implement it in C#:

public sealed class Singleton
{
private static volatile Singleton instance = null;
private static readonly object padlock = new object();

private Singleton() {;}

public static Singleton Instance
{
get
{
if (instance == null)
{
lock(padlock)
{
if (instance == null)
instance = new Singleton();
}
}
return instance;
}
}
}

The volatile keyword is used to ensure that there is no optimizer reordering
of the code.

Another option that has not the problem of the double check lock is using
static fields to host the sole instance. In this case, you won´t be able to
use lazy instantiation for the singleton´s sole instance, but if that´s not
an issue you could use the following code:

// .NET Singleton
sealed class Singleton
{
private Singleton() {}
public static readonly Singleton Instance = new Singleton();
}

Hope this helps,
Regards,
Leon

[quoted text, click to view]
AddThis Social Bookmark Button