RSS 2.0

Personal Info:

Joe Send mail to the author(s) is a lead architect on an OS incubation project at Microsoft, and was the architect for Parallel Extensions to .NET. He is an author and frequent speaker.

Blogroll:
Other
News
 C|Net
 Kuro5hin
 The Register
Technology
 <?xmlhack?>
 Daily WTF
 DevX
 Hacknot
 Java Today
 Microsoft Top 10 Downloads
 MSDN
 MSDN: "Longhorn"
 MSDN: XML Developer Center
 Slashdot
 Techdirt
 theserverside.com
 W3C
 Web Pages That Suck
 XML Cover Pages
 XML Journal
 xml.com
Technology Blogs
 Aaron Skonnard [PluralSight]
 Adam Bosworth [Google]
 Andy Rich [MS/C++]
 Arpan Desai [MS/XML]
 BCL Team [MS]
 Bill Clementson [Lisp]
 Bill de hÓra
 Bruce Eckel [J]
 Bruce Tate [J]
 Casey Chestnut
 Cedric Beust [Google]
 Chris Anderson [MS/Avalon]
 Chris Lyon [MS]
 Christian Weyer
 Clemens Vasters [newtelligence]
 Craig Andera [PluralSight]
 Dan Sugalski [Parrot]
 Daniel Cazzulino
 Dave Chappel
 Dave Roberts [Lisp]
 Dave Thomas [PragProg]
 Dave Winer
 Dion Almaer [J]
 Don Demsak
 Doug Purdy [MS/Indigo]
 Drew Marsh
 Eric Gunnerson [MS]
 Eric Rudder [MS]
 Eric Sink
 Fritz Onion [PluaralSight]
 Gavin King [J/Hibernate]
 Grady Booch [IBM]
 Hervey Wilson [MS/Indigo]
 Hillel Cooperman [MS/Shell]
 Howard Lewis Ship [J/Apache]
 Ingo Rammer [PluralSight]
 James Gosling [J/Sun]
 James Strachan [J/Groovy]
 Jason Matusow [MS/OSS]
 Jeffrey Schlimmer [MS/Indigo]
 Joe Beda [Google]
 Joel Spoelsky
 Jon Udell
 Josh Ledgard [MS/Evang]
 Joshua Allen [MS]
 Lambda
 Larry Osterman [MS]
 Maoni Stephens [MS/CLR]
 Mark Fussell [MS/XML]
 Martin Fowler
 Martin Gudgin [MS/Indigo]
 Me
 Michael Howard [MS]
 Miguel de Icaza [Mono]
 Mike Clark
 Omri Gazitt [MS/Indigo]
 Pat Helland [MS/PAG]
 Pinku Surana
 Raymond Chen [MS]
 Rich Lander [MS/CLR]
 Rob Howard
 Rob Relyea [MS/Avalon]
 Robert Cringely
 S. Somasegar [MS/DevDiv]
 Sam Gentile
 Scoble [MS/Evang]
 Scott Guthrie [MS/WebNet]
 Scott Hanselman
 Sean McGrath [J]
 Simon Fell
 Stanley Lippman [MS/C++]
 Steve Maine
 Steve Swartz [MS/Indigo]
 Steve Vinoski
 Steven Clarke [MS/Usability]
 Stuart Halloway
 Ted Leung
 Ted Neward [DM]
 Tim Bray [Sun]
 Tim Ewald [Mindreef]
 Tim O'Reilly
 Werner Vogels [Amazon]
 Wintellect
 Yasser Shohoud [MS/Indigo]
Top 20
 Brad Abrams [MS/CLR]
 Chris Brumme [MS/CLR]
 Chris Sells [MS/Ultra]
 Cyrus Najmabadi [MS/C#]
 Dominic Cooney [MS/XAF]
 Don Box [MS/Ultra]
 Don Syme [MS/R]
 Guido van Rossum [Python]
 Herb Sutter [MS/C++]
 Ian Griffiths
 Jason Zander [MS/CLR]
 Jim Hugunin [MS/CLR]
 Joel Pobar [MS/CLR]
 Krzysztof Cwalina [MS/CLR]
 Patrick Logan
 Paul Graham
 Rico Mariani [MS/CLR]
 Rory Blyth [MS/DN]
 Sam Ruby
 Wesner Moise
VC/Business Blogs
 Ed Sim
 Fred Wilson
 Jonathan Schwartz [J/Sun]
 Lawrence Lessig [Stanford]
 Mark Cuban
 Michael Hyatt
 Pierre Omidyar
 Ross Mayfield
 VentureBlog
 Weekly Read
Wine, Food & Tea
 The Silk Road of Wine
 Vinography: a wine blog
 Wine Whys

Disclaimer:
The content of this site are my own personal opinions and do not represent my employer's view in anyway.

© 2010, Joe Duffy

 
 Monday, February 28, 2005

Based on a recent question from Brad, I decided to write up a little post on the topic of event handlers. Specifically, that objects registered to receive events are rooted, meaning that they won't be eligible for GC even if you drop them on the floor. Through some trickery with weak references, you can work around this (if you need to).

So, what's the issue?

Once you register an object as a sink for events in C#, the source object generating the events will keep a reference to it. When the source becomes unreachable, your sink will also become unreachable (assuming that's the only live reference to the sink). An alternative way to make your sink unreachable is to manually unregister it, asking that the source give up its reference. But this means that until either one of these things happen, your object won't be eligible for garbage collection. This probably won’t be surprising for most folks, but for finalizable objects which own resources it does mean you need to be very careful to unregister your sink when it needs to die. Even for objects which don't hold on to such resources, you might be building up a list of unused objects after a while, akin to stashing away references in a collection and forgetting to prune it when you're done.

For example, given source and sink set of types:

class Source

{

    public event EventHandler<EventArgs> Tick;

 

    public void OnTick()

    {

        EventHandler<EventArgs> t = Tick;

        if (t != null)

            t(this, new EventArgs());

    }

}

 

interface ISink

{

    void HandleTick(object sender, EventArgs e);

}

And client code which defines a sink implementation:

class MySink : ISink, IDisposable

{

    private IntPtr someHandle;

 

    static int counter;

    int id = counter++;

 

    public MySink()

    {

        // create someHandle

    }

 

    ~MySink()

    {

        // clean up someHandle

        Console.WriteLine("!{0} finalized", id);

    }

 

    public void Dispose()

    {

        // clean up someHandle

        GC.SuppressFinalize(this);

        Console.WriteLine("~{0} disposed", id);

    }

 

    public void HandleTick(object sender, EventArgs e)

    {

        // use someHandle

        Console.WriteLine("{0}: Received", id);

    }

}

The owner of an instance of MySink might not realize what consequences registering the sink for messages will have, namely that it will cause it to become rooted. For example, this simple code does the trick:

Source src = /*...*/;

MySink sk = new MySink();

src.Tick += sk.HandleTick;

Given that this type owns unmanaged resources, the user really needs to remember to unregister it when they’re done with it.

And this is a problem because…?

This actually seems like it's the desired/intended behavior for somebody registering for events in most cases. Frequently, a sink object will be created, registered for an event, and then its reference dropped and left on its own to process the incoming messages. I.e. its only purpose in life is to respond to events. It might seem surprising that somebody would register an object and forget to ever unregister it, but I suspect this happens all the time. This is one of those subtle bugs which could manifest over time in a long running application (e.g. a web app), where unmanaged memory just continues to rise and rise until ASP.NET recycles itself. Especially if there’s some AppDomain-wide event registration and routing mechanism.

So, for those situations where we don’t want the event source to keep us alive, what are we to do?

Enter “Weak Event Handlers”

We have this nifty feature called weak references (exposed by the WeakReference class), enabling you to hold on to a reference without keeping it pinned from GC collection. If there are no strong references to an object and the GC runs, it'll sweep these up. This means that the underlying object referred to by the weak reference won't be valid any longer. (For those from the Java camp, be careful—one of the first mistakes I made when moving to the CLR was thinking that weak references == soft references. Soft references are only collected as a last resort, making them perfect for caching. Weak references are always collected if no strong references exist at the time of a GC, so you might have to think carefully about using them. This is one great reason to avoid GC.Collect() in production applications (among many others).)

We can go ahead and use this feature to wrap up our event handler delegates. Then we just hand the wrapper instead of the raw delegate off to event registration, thus preventing the event source from keeping our object alive. So, let’s get started.

First we introduce a general purpose WeakEventHandler<T> class:

class WeakEventHandler<T> where T : EventArgs

{

 

    private WeakReference weakRef;

    private EventHandler<T> handler;

 

    public WeakEventHandler(EventHandler<T> d)

    {

        weakRef = new WeakReference(d);

        handler = new EventHandler<T>(Invoke);

    }

 

    public EventHandler<T> Handler

    {

        get { return handler; }

    }

 

    private void Invoke(object sender, T e)

    {

        EventHandler<T> d = (EventHandler<T>)weakRef.Target;

        if (d != null)

            d(sender, e);

        else

            // hmm! what to do here?

    }

 

}

So now somebody can construct a weak event handler, and register that instead. Once the target of the delegate loses its roots, it’s eligible for GC. For example, the three line snippet from above becomes:

Source src = /*...*/;

MySink sk = new MySink();

src.Tick += new WeakEventHandler<EventArgs>(sk.HandleTick).Handler;

(Note that I initially wanted to subclass Delegate to make a WeakDelegate type, and simply override the internal storage in order to make a general purpose “weak delegate.” Unfortunately, Delegate and MulticastDelegate are treated specially by the CLI (see Partition II), meaning that I couldn’t do this straightforwardly. I’m going to look into it further, but I’m not sure exactly what this would entail.)

But now won't my WeakEventHandler stay alive?

Yep, it does. This is admittedly leaps and bounds better than keeping a finalizable object rooted, but we can probably clean things up a little. Notice the “// hmm! what to do here?” line above?—we can actually put some code in here that intelligently unregisters the weak handler from the source. It requires a bit of generalization, but here’s a shot at it. (Note that this approach requires an event to be triggered to initiate the cleanup, so for events with particularly long delays in between instances, this might not be a great solution.) 

First, let’s update our WeakEventHandler<T> class to accept an unregister delegate. This will be invoked in cases where our underlying object has been collected, and hence the weak wrapper should be removed from the event source’s registration list; from this point forward, our previous code just ignores all future requests to fire the event anyhow:

delegate void UnregisterHandler<T>(WeakEventHandler<T> handler) where T : EventArgs;

 

class WeakEventHandler<T> where T : EventArgs

{

 

    private WeakReference weakRef;

    private EventHandler<T> handler;

    private UnregisterHandler<T> unregister;

 

    public WeakEventHandler(EventHandler<T> d) : this(d, null)

    {

    }

 

    public WeakEventHandler(EventHandler<T> d, UnregisterHandler<T> u)

    {

        weakRef = new WeakReference(d);

        handler = new EventHandler<T>(Invoke);

        unregister = u;

    }

 

    public EventHandler<T> Handler

    {

        get { return handler; }

    }

 

    private void Invoke(object sender, T e)

    {

        EventHandler<T> d = (EventHandler<T>)weakRef.Target;

        if (d != null)

            d(sender, e);

        else if (unregister != null)

            unregister(this);

    }

 

}

Then, we just update our source to have an Unregister method. As a matter of fact, now that we have this weak handler goop, let’s encapsulate it inside a new Register method. This means that (unfortunately) we won’t be using the C# syntax for event registration, but compared with having users grok the weak handler mechanism, I personally find it much more palatable:

class Source

{

    public event EventHandler<EventArgs> Tick;

 

    public void OnTick()

    {

        EventHandler<EventArgs> t = Tick;

        if (t != null)

            t(this, new EventArgs());

    }

 

    public void Register(ISink sk)

    {

        Tick += new WeakEventHandler<EventArgs>(sk.HandleTick, Unregister).Handler;

    }

 

    private void Unregister(WeakEventHandler<EventArgs> eh)

    {

        Tick -= eh.Handler;

    }

}

Now the three lines of code change to:

Source src = /*...*/;

MySink sk = new MySink();

src.Register(sk);

Should I actually do this?

Just because you can use this doesn't mean you should. :) It seems like a reasonable strategy to make sure you don't shoot yourself in the foot too badly, but if you're relying on weak wrappers to do the unregistration and cleanup for you, it seems like all you're really doing is working around bugs. This is a bit like forgetting to call Dispose on an object and having a finalizer kick in just to make sure you don't leak. Further, you probably shouldn't use this if all you do is register for an event and drop the reference. In this case, the GC could kick in as early as the nanosecond after you drop the reference, meaning your registration was useless.

With that said, I think it's perfectly reasonable to use this to debug and detect bugs in your code. For example, if you fired an assert instead of unregistering the weak handler, you might be able to detect where in your program you forget to unregister sink objects. Just some thoughts. I'd love to hear any feedback on where you might find this useful.

Testing, Testing, 1, 2, 3...

This little snippet of test code demonstrates the whole thing. Here’s the full source in case anybody wants to play around with it without having to scour this post to pull together all the code.

class Program

{

 

    static void Main()

    {

        Program p = new Program();

        p.Execute();

    }

 

    private Source src = new Source();

 

    public void Execute()

    {

        for (int j = 0; j < 1000; j++)

        {

            for (int i = 0; i < 1000; i++)

            {

                src.Register(new MySink());

            }

 

            src.OnTick();

            GC.Collect();

        }

    }

 

}

2/28/2005 2:12:21 PM (Pacific Standard Time, UTC-08:00)  #    Comments [7]
Tracked by:
http://www.docuverse.com/blog/donpark/EntryViewPage.aspx?guid=ddab5348-61d3-4771... [Pingback]
"buy womens shoes" (buy womens shoes) [Trackback]
"buy shoes" (buy shoes cheap) [Trackback]
"buy valium online" (buy valium online) [Trackback]
"buy xanax online" (buy xanax online) [Trackback]
"cheap tramadol" (cheap tramadol) [Trackback]
"nike womens shoes" (nike womens shoes) [Trackback]
"valium" (valium) [Trackback]
"buy tramadol online" (buy tramadol online) [Trackback]
"phentermine" (phentermine) [Trackback]
"briana banks" (briana banks) [Trackback]
"buy valium" (buy valium) [Trackback]
http://www.google.com/search?q=xddwjixm [Pingback]
http://www.google.com/search?q=aihywwtz [Pingback]
http://arts4ed.org/wwwboard/messages/7279.htm [Pingback]
http://www.twv.com.tw/virtual/god/talk/messages/83092.html [Pingback]
http://warlinks.com/yabbfiles/hydrocodoneonline.htm [Pingback]
http://ramw.org/img/upload/buyphentermine.htm [Pingback]
http://acccn.com.au/db_backup/buycarisoprodol.htm [Pingback]
http://cogiscan.com/pdf/img/buyphentermineonline.htm [Pingback]
http://theorderoftime.com/game/wiki/images/whatisviagra.htm [Pingback]
http://cogiscan.com/pdf/img/orderorderviagra.htm [Pingback]
http://www.google.com/search?q=tlpjwcwk [Pingback]
http://www.google.com/search?q=nwzzuwwr [Pingback]
http://www.google.com/search?q=agndxusn [Pingback]
http://www.allknightaccess.com/betatesting/transcode/buycialisonline.htm [Pingback]
http://aitr.org/ev/images/soma.htm [Pingback]
http://bedandbreakfast-gent.be/picturesBB/old/diabetes.htm [Pingback]
http://illegalaliens.us/merchandise/images/alprazolam-online.htm [Pingback]
http://spacecasestv.com/bboard/attachments/diazepam.htm [Pingback]
http://illegalaliens.us/merchandise/images/buy-cialis.htm [Pingback]
http://kipaddotta.com/Web_store/Pgpfiles/online-pharmacy.htm [Pingback]
http://libertarianactivism.com/simplegroupware/bin/carisoprodol.htm [Pingback]
http://www.cbk.rotterdam.nl/openbarekunst/materiaal/old/propecia.htm [Pingback]
http://bbiverson.com/fmimages/online-soma.htm [Pingback]
http://nugraphic.com/docs/pharmacy.htm [Pingback]
http://sdmrm.org/calendar/pharmacy.htm [Pingback]
http://illegalaliens.us/merchandise/images/prozac.htm [Pingback]
http://firstpresbyterian.org/documentation/fioricet.htm [Pingback]
http://profootballcentral.com/carp/viagra-sale.htm [Pingback]
http://illegalaliens.us/merchandise/images/meridia.htm [Pingback]
http://rayhane.com/blog/ecrire/images/hoodia.htm [Pingback]
http://libertarianactivism.com/simplegroupware/bin/viagra.htm [Pingback]
http://www.cbk.rotterdam.nl/openbarekunst/materiaal/old/meridia.htm [Pingback]
http://jccc.on.ca/site/cms/dev/files/vicodin.htm [Pingback]
http://www.wwtf.at/Uploads/imgs/generic-viagra.htm [Pingback]
http://www.cbk.rotterdam.nl/openbarekunst/materiaal/old/doctor.htm [Pingback]
http://firstpresbyterian.org/documentation/buyviagra.htm [Pingback]
http://libertarianactivism.com/simplegroupware/bin/drug.htm [Pingback]
http://bedandbreakfast-gent.be/picturesBB/old/drug.htm [Pingback]
http://rascast.com/wwwboard/messages/39380.htm [Pingback]
http://myplugins.info/itfixit/cache/fioricet.htm [Pingback]
http://www.4uu.de/templates/hoodia.htm [Pingback]
http://ridgehistoricalsociety.org/forum/images/avatars/zoloft.htm [Pingback]
http://dynamic-cast.com/imwse/generic-viagra.htm [Pingback]
http://www.seniorsnet.ca/cache/fitness.htm [Pingback]
http://www.primas.at/images/bla/viagra2.htm [Pingback]
http://www.4uu.de/templates/what-is-diazepam.htm [Pingback]
http://www.dartmoorletterboxing.org/blog/viagra-cheap.htm [Pingback]
http://cabins-r.us/html_pages/costlowphentermine.htm [Pingback]
http://www.futerox.com/portfloio_images/big/valium.htm [Pingback]
http://www.prosserchamber.org/generator/files/hoodia.htm [Pingback]
http://articlesubmitterpro.com/blog/maillist/fitness.htm [Pingback]
http://www.futerox.com/portfloio_images/big/health.htm [Pingback]
http://alfa9.co.uk/forum/images/avatars/ordersoma.htm [Pingback]
http://www.google.com/search?q=zooavmnf [Pingback]
http://www.google.com/search?q=roqbmzgk [Pingback]
http://www.google.com/search?q=wzttloop [Pingback]
http://www.google.com/search?q=yxjjttxd [Pingback]
"Online phentermine without contacting doctor." (Phentermine no doctor no prescr... [Trackback]
http://diditwith.net/PermaLink,guid,aacdb8ae-7baa-4423-a953-c18c1c7940ab.aspx [Pingback]
"Brand ultram order ultram tramadol pain medicine." (Order tramadol.) [Trackback]

3/1/2005 9:14:13 AM (Pacific Standard Time, UTC-08:00)
Great post Joe.

I'm eagerly anticipating v2 of the framework to ship!

Keep it coming!
12/8/2006 4:24:04 PM (Pacific Standard Time, UTC-08:00)

[URL=http://lg-cellular-phone.schadez.info]lg cellular phone[/URL]
[URL=http://free-prepaid-cellular-phone.zeiter.info]free prepaid cellular phone[/URL]
[URL=http://sony-ericsson-cellular-phone.zeiter.info]sony ericsson cellular phone[/URL]
[URL=http://cellular-phone-number-lookup.zeiter.info]cellular phone number lookup[/URL]
5/29/2007 3:39:17 AM (Pacific Daylight Time, UTC-07:00)
http://pompinoa.odp.tarnobrzeg.pl pompino a
http://fotografico.az.pl/cutenwxi/ cute cameriera strip
http://fotografico.az.pl/maratgxx/ mara venier upskirt
http://fotografico.az.pl/taglioawmi/ taglio bionde dildo
http://bedbreakfastmarsala.odp.tarnobrzeg.pl bed breakfast marsala
http://trattamentoesteticoviso.odp.tarnobrzeg.pl trattamento estetico viso
http://arbonnenetworkmarketing.odp.tarnobrzeg.pl arbonne network marketing
http://fotografico.az.pl/samsonitepdmr/ samsonite abbigliamento
http://fotografico.az.pl/californianufu/ california law lemon
http://ediliziaportale.odp.tarnobrzeg.pl edilizia portale
http://risibilecowgirlazione.odp.tarnobrzeg.pl risibile cowgirl azione
http://fotografico.az.pl/nonsensicalnfbp/ nonsensical agente di polizia spogliarello
2/4/2008 6:05:08 AM (Pacific Standard Time, UTC-08:00)
Cool, the post.

Thanks for the information.
8/26/2008 4:59:36 AM (Pacific Daylight Time, UTC-07:00)
There is always another way around with a handler, but the main problem is that we need to fix the time consuming problem and choose the most efficient way.
10/2/2008 7:48:31 AM (Pacific Daylight Time, UTC-07:00)
This doesn't work. The incoming handler gets GC'd
Ant
12/15/2008 5:51:40 PM (Pacific Standard Time, UTC-08:00)
In [url=http://www.wowgold1000.com]wow gold[/url] players [url=http://www.wowgold1000.com]buy wow gold[/url] create [url=http://www.wowgold1000.com]cheap wow gold[/url] a character [url=http://www.wowgold1000.com]world of warcraft gold[/url] and [url=http://www.wowgold800.com/fast-wow-gold.html]fast wow gold[/url] adventure [url=http://www.wowgold1000.com/age-of-conan-gold.html]age of conan gold[/url] through [url=http://www.wowgold1000.com/aoc-gold.html]aoc gold[/url] the [url=http://www.wowgold1000.com/ffxi-gil/]ffxi gil[/url], [url=http://www.wowgold1000.com/buy-warhammer-gold.html]warhammer gold[/url] missions, [url=http://www.wowgold1000.com/buy-rs-gold.html]runescape gold[/url] blowing [url=http://www.wowgold1000.com/buy-tibia-gold.html]tibia gold[/url] things [url=http://www.wowgold1000.com/buy-swg-credits.html]swg credits[/url] up [url=http://www.wowgold1000.com/buy-lotro-gold.html]lotro gold[/url] and [url=http://www.wowgold1000.com/buy-2moons-dil.html]2moons dil[/url],[url=http://www.wowgold1000.com/maple-story-mesos/]maple story mesos[/url] bullets, to [url=http://www.wowgold1000.com/eve-isk/]eve isk[/url] name [url=http://www.wowgold1000.com/lineage-2-adena/]lineage 2 adena[/url] but a [url=http://www.wowgold1000.com/eq-plat/]eq2 plat[/url] few [url=http://www.wowgold800.com]wow power leveling[/url] things. Generally [url=http://www.wowgold1000.com/wow-power-leveling.html]wow power leveling[/url], if you’ve [url=http://www.wowgold1000.com/power-leveling.html]power leveling[/url] seen [url=http://www.wowgold800.com]world of warcraft power leveling[/url] it in [url=http://www.wowgold800.com]wow leveling[/url] a matrix [url=http://www.wowgold800.com]power leveling[/url] film [url=http://www.wowgoldvip.com/news_list.asp]wow gold[/url] chances [url=http://www.wowgoldvip.com]buy wow gold[/url] are [url=http://www.wowgoldvip.com]cheap wow gold[/url] you can [url=http://www.wowgoldvip.com]world of warcraft gold[/url] do it [url=http://www.wowgoldvip.com/wow-power-leveling.asp]wow power leveling[/url] in the [url=http://www.wowgoldvip.com/powerleveling.asp]power leveling[/url] game. This [url=http://www.wowgoldme.com]wow gold[/url] is [url=http://www.wowgoldme.com]cheap wow gold[/url] excellent news [url=http://www.wowgoldme.com]buy wow gold[/url] for the vast [url=http://www.powerleveling365.com]power leveling[/url] mob [url=http://www.powerleveling365.com]wow powerleveling[/url] of people [url=http://www.powerleveling365.com]wow power leveling[/url] who [url=http://www.powerleveling365.com]cheap power leveling[/url] have [url=http://www.wowgoldchina.com]wow gold[/url] always [url=http://www.wowgoldchina.com]buy wow gold[/url] wanted to [url=http://www.wowgoldchina.com]cheap wow gold[/url] experience [url=http://www.wowgoldchina.com]world of warcraft gold[/url] the [url=http://www.powerlevelingus.com]power leveling[/url] matrix [url=http://www.powerlevelingus.com]wow powerleveling[/url] and do [url=http://www.powerlevelingus.com]wow power leveling[/url] their [url=http://www.powerlevelingus.com]cheap power leveling[/url] part [url=http://www.igxee.com]power leveling[/url] in helping [url=http://www.igxee.com]wow powerleveling[/url] the [url=http://www.igxee.com]wow power leveling[/url] people [url=http://www.igxee.com]cheap power leveling[/url] of Zion. Or [url=http://wow.igwww.com]wow gold[/url] even [url=http://wow.igwww.com]buy wow gold[/url] for those [url=http://wow.igwww.com]cheap wow gold[/url] people [url=http://wow.igwww.com]world of warcraft gold[/url] who [url=http://www.cheap-wow-gold.de]wow gold[/url] were secretly [url=http://www.cheap-wow-gold.de]wow geld[/url] sympathetic [url=http://www.cheap-wow-gold.de]wow gold kaufen[/url] to the [url=http://www.cheap-wow-gold.de]billig wow gold[/url] Machines, or those [url=http://www.wow-paypal.com]wow gold[/url] who found [url=http://www.wow-paypal.com]cheap wow gold[/url] the Merovingian [url=http://www.wow-paypal.com]buy wow gold[/url] charming [url=http://www.bolts-nuts.com]bolts nuts[/url] and were [url=http://www.nbtrade.org]nut and bolt[/url] secretly rooting for his Exiles throughout the film. [url=http://www.thewowgold.net/billizard/index.php]wow gold[/url]
Name
E-mail
Home page

Comment (HTML not allowed)  

Enter the code shown (prevents robots):

 

Recent Entries:

Search:

Browse by Date:
<March 2010>
SunMonTueWedThuFriSat
28123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Browse by Category:

Notables:

Currently Up To:

Reading...

Listening...

Watching...