Created
April 27, 2009 10:12
-
-
Save atifaziz/102424 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Compile using: | |
// csc /target:winexe /noconfig /define:DEBUG FinalizerDemo.cs /r:System.dll /r:System.Windows.Forms.dll | |
// Self-contained demonstration code for: | |
// http://stackoverflow.com/questions/792660/is-gc-suppressfinalize-guaranteed | |
using WikiPad; | |
using System; | |
using System.Windows.Forms; | |
public class Program | |
{ | |
public static void Main(string[] args) | |
{ | |
Application.EnableVisualStyles(); | |
Application.SetCompatibleTextRenderingDefault(false); | |
var form = new Form(); | |
var button = new Button | |
{ | |
Text = "Work, baby, work!", | |
Dock = DockStyle.Fill | |
}; | |
button.Click += delegate | |
{ | |
if (args.Length > 0 && args[0].Equals("notusing", StringComparison.OrdinalIgnoreCase)) | |
{ | |
CurrentCursorScope.EnterWait(); // the wrong way that will | |
System.Threading.Thread.Sleep(1000); // trigger warning on exit | |
} | |
else | |
{ | |
using (CurrentCursorScope.EnterWait()) // the right way | |
System.Threading.Thread.Sleep(1000); | |
} | |
}; | |
form.Controls.Add(button); | |
Application.Run(form); | |
GC.WaitForPendingFinalizers(); | |
} | |
} | |
#region License, Terms and Author(s) | |
// | |
// Schnell - Wiki widgets | |
// Copyright (c) 2007 Atif Aziz. All rights reserved. | |
// | |
// Author(s): | |
// Atif Aziz, http://www.raboof.com | |
// | |
// This library is free software; you can redistribute it and/or modify it | |
// under the terms of the GNU Lesser General Public License as published by | |
// the Free Software Foundation; either version 2.1 of the License, or (at | |
// your option) any later version. | |
// | |
// This library is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
// License for more details. | |
// | |
// You should have received a copy of the GNU Lesser General Public License | |
// along with this library; if not, write to the Free Software Foundation, | |
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
// | |
#endregion | |
namespace WikiPad | |
{ | |
#region Imports | |
using System; | |
using System.Diagnostics; | |
#endregion | |
// | |
// NOTE: To use SingletonScope and ISingletonScopeHelper with value | |
// types, use Nullable<T>. For example, if the type of value to scope | |
// is ThreadPriority then use ISingletonScopeHelper<ThreadPriority?> | |
// and SingletonScope<ThreadPriority?>. | |
// | |
// | |
// In debug builds, this type is defined as a class so a finalizer | |
// can be used to detect an undisposed scope. | |
// | |
/// <summary> | |
/// Designed to change a singleton and scope that change. After exiting | |
/// the scope, the singleton is restored to its value prior to entering | |
/// the scope. | |
/// </summary> | |
#if !DEBUG | |
internal struct SingletonScope<T, H> | |
#else | |
internal sealed class SingletonScope<T, H> | |
#endif | |
: IDisposable | |
where H : ISingletonScopeHelper<T>, new() | |
{ | |
private T _old; | |
public SingletonScope(T temp) | |
{ | |
_old = Helper.Install(temp); | |
} | |
private static H Helper | |
{ | |
get { return new H(); } | |
} | |
public void Dispose() | |
{ | |
// | |
// First, transfer fields to stack then nuke the fields. | |
// | |
T old = _old; | |
// | |
// Already disposed? | |
// | |
if (old == null) | |
return; | |
_old = default(T); | |
// | |
// Shazam! Restore the old value. | |
// | |
Helper.Restore(old); | |
#if DEBUG | |
GC.SuppressFinalize(this); // Only when defined as a class! | |
#endif | |
} | |
#if DEBUG | |
// | |
// This finalizer is used to detect an undisposed scope. This will | |
// only indicate that the scope was not disposed but (unfortunately) | |
// not which one and where since GC will probably collect much later | |
// than it should have been disposed. | |
// | |
~SingletonScope() | |
{ | |
Debug.Fail("Scope for " + typeof(T).FullName + " not disposed!"); | |
} | |
#endif | |
} | |
} | |
#region License, Terms and Author(s) | |
// | |
// Schnell - Wiki widgets | |
// Copyright (c) 2007 Atif Aziz. All rights reserved. | |
// | |
// Author(s): | |
// Atif Aziz, http://www.raboof.com | |
// | |
// This library is free software; you can redistribute it and/or modify it | |
// under the terms of the GNU Lesser General Public License as published by | |
// the Free Software Foundation; either version 2.1 of the License, or (at | |
// your option) any later version. | |
// | |
// This library is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
// License for more details. | |
// | |
// You should have received a copy of the GNU Lesser General Public License | |
// along with this library; if not, write to the Free Software Foundation, | |
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
// | |
#endregion | |
namespace WikiPad | |
{ | |
/// <summary> | |
/// Provides helper implementation to SingletonScope for installing | |
/// and restoring the singleton value. | |
/// </summary> | |
internal interface ISingletonScopeHelper<T> | |
{ | |
T Install(T temp); | |
void Restore(T old); | |
} | |
} | |
#region License, Terms and Author(s) | |
// | |
// Schnell - Wiki widgets | |
// Copyright (c) 2007 Atif Aziz. All rights reserved. | |
// | |
// Author(s): | |
// Atif Aziz, http://www.raboof.com | |
// | |
// This library is free software; you can redistribute it and/or modify it | |
// under the terms of the GNU Lesser General Public License as published by | |
// the Free Software Foundation; either version 2.1 of the License, or (at | |
// your option) any later version. | |
// | |
// This library is distributed in the hope that it will be useful, but WITHOUT | |
// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public | |
// License for more details. | |
// | |
// You should have received a copy of the GNU Lesser General Public License | |
// along with this library; if not, write to the Free Software Foundation, | |
// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
// | |
#endregion | |
namespace WikiPad | |
{ | |
#region Imports | |
using System.Windows.Forms; | |
#endregion | |
internal static class CurrentCursorScope | |
{ | |
public static SingletonScope<Cursor, Helper> EnterWait() | |
{ | |
return Enter(Cursors.WaitCursor); | |
} | |
public static SingletonScope<Cursor, Helper> Enter(Cursor cursor) | |
{ | |
return new SingletonScope<Cursor, Helper>(cursor); | |
} | |
internal struct Helper : ISingletonScopeHelper<Cursor> | |
{ | |
public Cursor Install(Cursor temp) | |
{ | |
var save = Cursor.Current; | |
Cursor.Current = temp; | |
return save; | |
} | |
public void Restore(Cursor old) | |
{ | |
Cursor.Current = old; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment