├── .gitattributes ├── .gitignore ├── Power Threading License.docx ├── Power Threading Overview.docx ├── PowerThreading-CompactFx ├── PowerThreading-CompactFx.csproj └── Properties │ └── AssemblyInfo.cs ├── PowerThreading-Desktop ├── CustomDictionary.xml ├── GlobalSuppressions.cs ├── PowerThreading-Desktop.csproj ├── PowerThreading.FxCop ├── Properties │ └── AssemblyInfo.cs ├── Wintellect.CmdArgParser │ ├── CmdArgAttribute.cs │ ├── CmdArgExceptionArgTypes.cs │ └── CmdArgParser.cs ├── Wintellect.IO │ ├── DeviceIO.cs │ └── StreamExtensions.cs ├── Wintellect.Threading │ ├── ArbitraryWaitHandle.cs │ ├── AsyncProgModel │ │ ├── ApmWrap.cs │ │ ├── AsyncEnumerator.cs │ │ ├── AsyncResult.cs │ │ ├── CountdownTimer.cs │ │ ├── EventApm.cs │ │ ├── SyncContextAsyncCallback.cs │ │ └── SyncGate.cs │ ├── InterlockedEx.cs │ ├── LogicalProcessor │ │ ├── LogicalProcessor.cs │ │ └── NumaInformation.cs │ ├── NativeMethods.cs │ ├── Progress.cs │ ├── ReaderWriterGate │ │ └── ReaderWriterGate.cs │ ├── ResourceLocks │ │ ├── ConditionVariable.cs │ │ ├── Diagnostics │ │ │ ├── DeadlockDetector.cs │ │ │ ├── ExclusiveOwnerResourceLockModifier.cs │ │ │ ├── RecursionResourceLockModifier.cs │ │ │ ├── ResourceLockDelegator.cs │ │ │ ├── StatisticsGatheringResourceLockObserver.cs │ │ │ ├── ThreadSafeCheckerResourceLockObserver.cs │ │ │ ├── TimeoutNotifierResourceLockObserver.cs │ │ │ └── WaitChainTraversal.cs │ │ ├── ExclusiveSpinResourceLock.cs │ │ ├── MonitorResourceLock.cs │ │ ├── MutexResourceLock.cs │ │ ├── NullResourceLock.cs │ │ ├── OneManyResourceLock.cs │ │ ├── OneManySpinResourceLock.cs │ │ ├── OneResourceLock.cs │ │ ├── OptexResourceLock.cs │ │ ├── ReaderWriterResourceLock.cs │ │ ├── ReaderWriterSlimResourceLock.cs │ │ ├── ResourceLock.cs │ │ ├── SemaphoreResourceLock.cs │ │ └── Win32SlimResourceLock.cs │ ├── SafeTokenHandle.cs │ ├── SyncContextEventRaiser.cs │ └── ThreadUtility.cs └── Wintellect │ ├── Contracts.cs │ ├── Disposer.cs │ ├── Exception.cs │ ├── Flags.cs │ ├── OperationTimer.cs │ ├── SafePinnedObject.cs │ └── Singleton.cs ├── PowerThreading-Silverlight ├── PowerThreading-Silverlight.csproj └── Properties │ └── AssemblyInfo.cs ├── PowerThreading-WindowsPhone ├── PowerThreading-WindowsPhone.csproj └── Properties │ └── AssemblyInfo.cs ├── PowerThreading.sln └── ReadMe.md /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | *.sln merge=union 7 | *.csproj merge=union 8 | *.vbproj merge=union 9 | *.fsproj merge=union 10 | *.dbproj merge=union 11 | 12 | # Standard to msysgit 13 | *.doc diff=astextplain 14 | *.DOC diff=astextplain 15 | *.docx diff=astextplain 16 | *.DOCX diff=astextplain 17 | *.dot diff=astextplain 18 | *.DOT diff=astextplain 19 | *.pdf diff=astextplain 20 | *.PDF diff=astextplain 21 | *.rtf diff=astextplain 22 | *.RTF diff=astextplain 23 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ################# 2 | ## Eclipse 3 | ################# 4 | 5 | *.pydevproject 6 | .project 7 | .metadata 8 | bin/ 9 | tmp/ 10 | *.tmp 11 | *.bak 12 | *.swp 13 | *~.nib 14 | local.properties 15 | .classpath 16 | .settings/ 17 | .loadpath 18 | 19 | # External tool builders 20 | .externalToolBuilders/ 21 | 22 | # Locally stored "Eclipse launch configurations" 23 | *.launch 24 | 25 | # CDT-specific 26 | .cproject 27 | 28 | # PDT-specific 29 | .buildpath 30 | 31 | 32 | ################# 33 | ## Visual Studio 34 | ################# 35 | 36 | ## Ignore Visual Studio temporary files, build results, and 37 | ## files generated by popular Visual Studio add-ons. 38 | 39 | # User-specific files 40 | *.suo 41 | *.user 42 | *.sln.docstates 43 | 44 | # Build results 45 | [Dd]ebug/ 46 | [Rr]elease/ 47 | *_i.c 48 | *_p.c 49 | *.ilk 50 | *.meta 51 | *.obj 52 | *.pch 53 | *.pdb 54 | *.pgc 55 | *.pgd 56 | *.rsp 57 | *.sbr 58 | *.tlb 59 | *.tli 60 | *.tlh 61 | *.tmp 62 | *.vspscc 63 | .builds 64 | *.dotCover 65 | 66 | ## TODO: If you have NuGet Package Restore enabled, uncomment this 67 | #packages/ 68 | 69 | # Visual C++ cache files 70 | ipch/ 71 | *.aps 72 | *.ncb 73 | *.opensdf 74 | *.sdf 75 | 76 | # Visual Studio profiler 77 | *.psess 78 | *.vsp 79 | 80 | # ReSharper is a .NET coding add-in 81 | _ReSharper* 82 | 83 | # Installshield output folder 84 | [Ee]xpress 85 | 86 | # DocProject is a documentation generator add-in 87 | DocProject/buildhelp/ 88 | DocProject/Help/*.HxT 89 | DocProject/Help/*.HxC 90 | DocProject/Help/*.hhc 91 | DocProject/Help/*.hhk 92 | DocProject/Help/*.hhp 93 | DocProject/Help/Html2 94 | DocProject/Help/html 95 | 96 | # Click-Once directory 97 | publish 98 | 99 | # Others 100 | [Pp]rivate 101 | [Bb]in 102 | [Oo]bj 103 | sql 104 | TestResults 105 | *.Cache 106 | ClientBin 107 | stylecop.* 108 | ~$* 109 | *.dbmdl 110 | Generated_Code #added for RIA/Silverlight projects 111 | 112 | # Backup & report files from converting an old project file to a newer 113 | # Visual Studio version. Backup files are not needed, because we have git ;-) 114 | _UpgradeReport_Files/ 115 | Backup*/ 116 | UpgradeLog*.XML 117 | 118 | 119 | 120 | ############ 121 | ## Windows 122 | ############ 123 | 124 | # Windows image file caches 125 | Thumbs.db 126 | 127 | # Folder config file 128 | Desktop.ini 129 | 130 | 131 | ############# 132 | ## Python 133 | ############# 134 | 135 | *.py[co] 136 | 137 | # Packages 138 | *.egg 139 | *.egg-info 140 | dist 141 | build 142 | eggs 143 | parts 144 | bin 145 | var 146 | sdist 147 | develop-eggs 148 | .installed.cfg 149 | 150 | # Installer logs 151 | pip-log.txt 152 | 153 | # Unit test / coverage reports 154 | .coverage 155 | .tox 156 | 157 | #Translations 158 | *.mo 159 | 160 | #Mr Developer 161 | .mr.developer.cfg 162 | 163 | # Mac crap 164 | .DS_Store 165 | -------------------------------------------------------------------------------- /Power Threading License.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wintellect/PowerThreading/4e41e0ec397d1fcb9b8523990a70c83614c1b614/Power Threading License.docx -------------------------------------------------------------------------------- /Power Threading Overview.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Wintellect/PowerThreading/4e41e0ec397d1fcb9b8523990a70c83614c1b614/Power Threading Overview.docx -------------------------------------------------------------------------------- /PowerThreading-CompactFx/PowerThreading-CompactFx.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {F905C677-4009-492E-965D-5473221B6BE7} 9 | Library 10 | Properties 11 | Wintellect 12 | Wintellect.Threading.CompactFx 13 | {4D628B5B-2FBC-4AA6-8C16-197242AEB884};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 14 | PocketPC 15 | 4118C335-430C-497f-BE48-11C3316B135E 16 | 5.1 17 | PowerThreading_CF 18 | v2.0 19 | Windows Mobile 5.0 Pocket PC SDK 20 | 21 | 22 | 40 23 | 4.0 24 | C:\Users\Jeffrey\Documents\Projects\PowerThreading\Backup\ 25 | 26 | 27 | true 28 | full 29 | false 30 | ..\..\Seminars\Threading\Code\PowerThreading\ 31 | DEBUG;TRACE;$(PlatformFamilyName) 32 | true 33 | true 34 | prompt 35 | 512 36 | 4 37 | Off 38 | 39 | 40 | pdbonly 41 | true 42 | ..\..\Seminars\Threading\Code\PowerThreading\ 43 | TRACE;$(PlatformFamilyName) 44 | true 45 | true 46 | prompt 47 | 512 48 | 4 49 | Off 50 | C:\Users\Jeffrey\Documents\Seminars\Threading\Code\PowerThreading\Wintellect.Threading.CompactFx.XML 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Wintellect.Threading\AsyncProgModel\ApmWrap.cs 62 | 63 | 64 | Wintellect.Threading\AsyncProgModel\AsyncEnumerator.cs 65 | 66 | 67 | Wintellect.Threading\AsyncProgModel\AsyncResult.cs 68 | 69 | 70 | Wintellect.Threading\AsyncProgModel\SyncGate.cs 71 | 72 | 73 | Wintellect.Threading\InterlockedEx.cs 74 | 75 | 76 | Wintellect\Disposer.cs 77 | 78 | 79 | Wintellect\Exception.cs 80 | 81 | 82 | Wintellect\Singleton.cs 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 101 | -------------------------------------------------------------------------------- /PowerThreading-CompactFx/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly:CLSCompliant(true)] 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Power Threading (for Compact Framework)")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Wintellect")] 14 | [assembly: AssemblyProduct("Power Threading (for Compact Framework)")] 15 | [assembly: AssemblyCopyright("Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM componenets. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("3ccc9fe8-006a-42b8-a1b0-aa7136552e96")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | [assembly: AssemblyVersion("4.6.*")] 37 | //[assembly: AssemblyFileVersion("4.5.0.0")] 38 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/CustomDictionary.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | Wintellect 8 | Associativity 9 | Numa 10 | Notifier 11 | Optex 12 | Multi 13 | Abortable 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Wct 24 | Rpcss 25 | Pid 26 | Alpc 27 | 28 | 29 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/PowerThreading-Desktop.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.21022 7 | 2.0 8 | {A74FEF61-2540-4C74-9300-2DADEF397CC7} 9 | Library 10 | Properties 11 | Wintellect.Threading 12 | Wintellect.Threading 13 | 14 | 15 | 3.5 16 | 17 | 18 | v2.0 19 | false 20 | 21 | 22 | publish\ 23 | true 24 | Disk 25 | false 26 | Foreground 27 | 7 28 | Days 29 | false 30 | false 31 | true 32 | 0 33 | 1.0.0.%2a 34 | false 35 | false 36 | true 37 | 38 | 39 | 1 40 | 41 | 42 | true 43 | full 44 | false 45 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 46 | TRACE;DEBUG;CODE_ANALYSIS;INCLUDE_GATES 47 | prompt 48 | 4 49 | 50 | 51 | true 52 | false 53 | AllRules.ruleset 54 | False 55 | False 56 | True 57 | False 58 | False 59 | True 60 | True 61 | True 62 | True 63 | True 64 | True 65 | False 66 | False 67 | 68 | 69 | 70 | 71 | 72 | 73 | Full 74 | %28none%29 75 | true 76 | 77 | 78 | pdbonly 79 | true 80 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 81 | TRACE;INCLUDE_GATES 82 | prompt 83 | 4 84 | 85 | 86 | true 87 | ..\..\..\Seminars\Threading\Code\PowerThreading\Wintellect.Threading.xml 88 | false 89 | AllRules.ruleset 90 | False 91 | False 92 | True 93 | False 94 | True 95 | True 96 | True 97 | True 98 | True 99 | True 100 | True 101 | False 102 | False 103 | 104 | 105 | 106 | 107 | 108 | ..\..\baseline.xml 109 | Full 110 | %28none%29 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | Code 148 | 149 | 150 | 151 | 152 | Code 153 | 154 | 155 | 156 | Code 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | False 168 | .NET Framework 3.5 SP1 Client Profile 169 | false 170 | 171 | 172 | False 173 | .NET Framework 3.5 SP1 174 | true 175 | 176 | 177 | False 178 | Microsoft Visual Basic PowerPacks 10.0 179 | true 180 | 181 | 182 | False 183 | Windows Installer 3.1 184 | true 185 | 186 | 187 | 188 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly:CLSCompliant(true)] 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Power Threading (for Workstation/Server CLR)")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Wintellect")] 14 | [assembly: AssemblyProduct("Power Threading (for Workstation/Server CLR)")] 15 | [assembly: AssemblyCopyright("Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("3ccc9fe8-006a-42b8-a1b0-aa7136552e96")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | [assembly: AssemblyVersion("5.0.*")] 37 | [assembly: AssemblyFileVersion("5.0.0.0")] 38 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.CmdArgParser/CmdArgAttribute.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: CmdArgAttribute.cs 3 | Notices: Copyright (c) 2011 Jeffrey Richter 4 | ******************************************************************************/ 5 | 6 | 7 | // TODO: Add support for an option array and for default options (without /Xxx:) 8 | using System; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.CommandArgumentParser { 15 | /// 16 | /// Indicates whether the command-line argument is required, not-required, or is optional. 17 | /// 18 | public enum CmdArgRequiredValue { 19 | /// 20 | /// Indicates that the argument is required. 21 | /// 22 | Yes, 23 | 24 | /// 25 | /// Indicates that the argument is not required. 26 | /// 27 | No, 28 | 29 | /// 30 | /// Indicates that the argument is optional. 31 | /// 32 | Optional 33 | } 34 | } 35 | 36 | 37 | /////////////////////////////////////////////////////////////////////////////// 38 | 39 | 40 | namespace Wintellect.CommandArgumentParser { 41 | /// 42 | /// An attribute that can be applied to a field or property indicating 43 | /// that the member maps to a command line argument. 44 | /// 45 | [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = true)] 46 | public sealed class CmdArgAttribute : Attribute { 47 | /// 48 | /// The attribute has no mandatory arguments. 49 | /// 50 | public CmdArgAttribute() { } 51 | 52 | private String m_ArgName; 53 | private Boolean m_RequiredArg; 54 | private CmdArgRequiredValue m_RequiredValue = CmdArgRequiredValue.No; 55 | private String m_Description; 56 | private Boolean m_UndocumentedArg; 57 | 58 | /// 59 | /// Identifies the argument name that maps to the associated field or property. 60 | /// If not specified, the argument name is identical to the field or property name. 61 | /// 62 | public String ArgName { 63 | get { return m_ArgName; } 64 | set { m_ArgName = value; } 65 | } 66 | 67 | /// 68 | /// Indicates whether this argument must be specified. 69 | /// 70 | public Boolean RequiredArg { 71 | get { return m_RequiredArg; } 72 | set { m_RequiredArg = value; } 73 | } 74 | 75 | /// 76 | /// Indicates whether the command-line argument's value is required, not-required, or is optional. 77 | /// 78 | public CmdArgRequiredValue RequiredValue { 79 | get { return m_RequiredValue; } 80 | set { m_RequiredValue = value; } 81 | } 82 | 83 | /// 84 | /// Indicates the Usage text for this command-line argument. 85 | /// 86 | public String Description { 87 | get { return m_Description; } 88 | set { m_Description = value; } 89 | } 90 | 91 | /// 92 | /// Indicates whether this argument should appear in the Usage string. 93 | /// 94 | public Boolean UndocumentedArg { 95 | get { return m_UndocumentedArg; } 96 | set { m_UndocumentedArg = value; } 97 | } 98 | } 99 | } 100 | 101 | 102 | /////////////////////////////////////////////////////////////////////////////// 103 | 104 | 105 | namespace Wintellect.CommandArgumentParser { 106 | /// Attribute describing how the target field maps to a command-line argument. 107 | [AttributeUsage(AttributeTargets.Field, AllowMultiple = false)] 108 | public sealed class CmdArgEnumValueDescriptionAttribute : Attribute { 109 | /// Constructs an attribute using the specified command-line argument description. 110 | /// 111 | public CmdArgEnumValueDescriptionAttribute(String description) { 112 | m_Description = description; 113 | } 114 | 115 | private String m_Description = null; 116 | 117 | /// Returns the description passed in the constructor. 118 | public String Description { 119 | get { return m_Description; } 120 | } 121 | } 122 | } 123 | 124 | 125 | //////////////////////////////// End of File ////////////////////////////////// 126 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.CmdArgParser/CmdArgExceptionArgTypes.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: CmdArgExceptionArgTypes.cs 3 | Notices: Copyright (c) 2010 Jeffrey Richter 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Runtime.Serialization; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.CommandArgumentParser { 15 | /// 16 | /// This represents a CmdArgumentType exception. 17 | /// 18 | [Serializable] 19 | public sealed class CmdArgumentTypeExceptionArgs: ExceptionArgs { 20 | internal CmdArgumentTypeExceptionArgs() { } 21 | } 22 | } 23 | 24 | 25 | /////////////////////////////////////////////////////////////////////////////// 26 | 27 | 28 | namespace Wintellect.CommandArgumentParser { 29 | /// 30 | /// The exception argument indicating that an invalid command-line argument has been found. 31 | /// 32 | [Serializable] 33 | public sealed class InvalidCmdArgumentExceptionArgs : ExceptionArgs { 34 | // Define any private fields 35 | private readonly String m_InvalidCmdArg; 36 | 37 | // Define additional constructors that set the field 38 | /// 39 | /// Constructs an InvalidCmdArgumentExceptionArgs with the specified invalid command argument. 40 | /// 41 | /// 42 | public InvalidCmdArgumentExceptionArgs(String invalidCmdArg) { 43 | m_InvalidCmdArg = invalidCmdArg; 44 | } 45 | 46 | /// 47 | /// Returns the invalid argument. 48 | /// 49 | public String InvalidCmdArg { get { return m_InvalidCmdArg; } } 50 | 51 | /// 52 | /// Returns a string that contains the invalid argument. 53 | /// 54 | /// 55 | public override String ToString() { 56 | if (InvalidCmdArg == null) return null; 57 | return "Invalid command-line argument: " + InvalidCmdArg; 58 | } 59 | } 60 | } 61 | 62 | 63 | //////////////////////////////// End of File ////////////////////////////////// 64 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.IO/StreamExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.Collections.Generic; 4 | using Wintellect.Threading.AsyncProgModel; 5 | using System.Threading; 6 | using System.Diagnostics.Contracts; 7 | 8 | namespace Wintellect.IO { 9 | /// Provides a set of static methods for manipulating System.IO.Stream. 10 | public static class StreamExtensions { 11 | private static IEnumerator CopyStream(AsyncEnumerator ae, Stream source, Stream destination, Int32 bufferSize, Action reportProgress) { 12 | Byte[] buffer = new Byte[bufferSize]; 13 | Int64 totalBytesRead = 0; 14 | while (true) { 15 | ae.SetOperationTag("Reading from source stream"); 16 | // Read whichever is smaller (number of bytes left to read OR the buffer size) 17 | source.BeginRead(buffer, 0, buffer.Length, ae.End(), null); 18 | yield return 1; 19 | Int32 bytesReadThisTime = source.EndRead(ae.DequeueAsyncResult()); 20 | totalBytesRead += bytesReadThisTime; 21 | 22 | ae.SetOperationTag("Writing to destination stream"); 23 | destination.BeginWrite(buffer, 0, bytesReadThisTime, ae.End(), null); 24 | yield return 1; 25 | destination.EndWrite(ae.DequeueAsyncResult()); 26 | 27 | if (reportProgress != null) reportProgress(totalBytesRead); 28 | if (bytesReadThisTime < buffer.Length) break; 29 | } 30 | ae.Result = totalBytesRead; 31 | } 32 | 33 | /// 34 | /// Asynchronously copies the contents of the source stream to the destination stream. 35 | /// 36 | /// The stream containing the data to be copied. 37 | /// The stream that will receive the copied data. 38 | /// The size of the internal buffer that should be used to copy the data in chunks. 39 | /// A callback method that is called after each chunk is copied to the destination stream. 40 | /// An optional asynchronous callback, to be called when copy completes. 41 | /// A user-provided object that distinguishes this particular asynchronous operation from other operations. 42 | /// 43 | public static IAsyncResult BeginCopyStream(/* this */ Stream source, Stream destination, Int32 bufferSize, Action reportProgress, AsyncCallback callback, Object state) { 44 | var ae = new AsyncEnumerator("CopyStream") { SyncContext = null }; 45 | return ae.BeginExecute(CopyStream(ae, source, destination, bufferSize, reportProgress), callback, state); 46 | } 47 | 48 | /// Gets the results of the stream copy operation. 49 | /// The stream used to initiate the stream copy operation. 50 | /// Identifies the asynchronous operation. 51 | /// The number of bytes copied to the destination stream. 52 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "source")] 53 | public static Int64 EndCopyStream(/* this */ Stream source, IAsyncResult result) { 54 | Contract.Requires(result != null); 55 | return AsyncEnumerator.FromAsyncResult(result).EndExecute(result); 56 | } 57 | } 58 | } -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ArbitraryWaitHandle.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ArbitraryWaitHandle.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.ComponentModel; 10 | using Microsoft.Win32.SafeHandles; 11 | using System.Runtime.InteropServices; 12 | using System.Diagnostics.Contracts; 13 | 14 | using HANDLE = System.IntPtr; 15 | 16 | /////////////////////////////////////////////////////////////////////////////// 17 | 18 | namespace Wintellect.Threading { 19 | /// 20 | /// Converts various handles to waitable handle for synchronization. 21 | /// 22 | public sealed class ArbitraryWaitHandle : WaitHandle { 23 | private ArbitraryWaitHandle(HANDLE handle) { 24 | this.SafeWaitHandle = 25 | new SafeWaitHandle(DuplicateHandle(handle), true); 26 | } 27 | 28 | /// 29 | /// A factory method that converts a Win32 handle to an ArbitraryWaitHandle. 30 | /// 31 | /// Identifies a handle to a synchronizable Win32 object. 32 | /// An ArbitraryWaitHandle object. 33 | public static ArbitraryWaitHandle FromHandle(HANDLE handle) { 34 | return new ArbitraryWaitHandle(handle); 35 | } 36 | 37 | /// 38 | /// Implicitly casts a Win32 handle to an ArbitraryWaitHandle. 39 | /// 40 | /// Identifies a handle to a synchronizable Win32 object. 41 | /// An ArbitraryWaitHandle object. 42 | public static implicit operator ArbitraryWaitHandle(HANDLE handle) { 43 | return FromHandle(handle); 44 | } 45 | 46 | /// 47 | /// Converts a SafeHandle-derived object to an ArbitraryWaitHandle object. 48 | /// 49 | /// Identifies a SafeHandle to a synchronizable Win32 object. 50 | /// An ArbitraryWaitHandle object. 51 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2001:AvoidCallingProblematicMethods", MessageId = "System.Runtime.InteropServices.SafeHandle.DangerousGetHandle")] 52 | public static ArbitraryWaitHandle FromSafeHandle(SafeHandle safeHandle) { 53 | Contract.Requires(safeHandle != null); 54 | Boolean success = false; 55 | try { 56 | safeHandle.DangerousAddRef(ref success); 57 | if (!success) throw new InvalidOperationException("Couldn't AddRef"); 58 | 59 | return new ArbitraryWaitHandle(safeHandle.DangerousGetHandle()); 60 | } 61 | finally { 62 | safeHandle.DangerousRelease(); 63 | } 64 | } 65 | 66 | /// 67 | /// Implicitly casts a SafeHandle-derived object to an ArbitraryWaitHandle. 68 | /// 69 | /// Identifies a SafeHandle to a synchronizable Win32 object. 70 | /// An ArbitraryWaitHandle object. 71 | public static implicit operator ArbitraryWaitHandle(SafeHandle safeHandle) { 72 | Contract.Requires(safeHandle != null); 73 | return FromSafeHandle(safeHandle); 74 | } 75 | 76 | private static HANDLE DuplicateHandle(IntPtr sourceHandle) { 77 | HANDLE currentProcess = NativeMethods.GetCurrentProcess(); 78 | HANDLE targetHandle; 79 | if (!NativeMethods.DuplicateHandle(currentProcess, sourceHandle, currentProcess, out targetHandle, 0, false, DuplicateHandleOptions.SameAcces)) 80 | throw new Win32Exception(); 81 | return targetHandle; 82 | } 83 | 84 | [Flags] 85 | private enum DuplicateHandleOptions { 86 | None = 0x00000000, 87 | CloseSource = 0x00000001, 88 | SameAcces = 0x00000002 89 | } 90 | 91 | private static class NativeMethods { 92 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 93 | internal static extern HANDLE GetCurrentProcess(); 94 | 95 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 96 | [return: MarshalAs(UnmanagedType.Bool)] 97 | internal static extern Boolean DuplicateHandle( 98 | HANDLE hSourceProcessHandle, HANDLE hSourceHandle, 99 | HANDLE hTargetProcessHandle, out HANDLE lpTargetHandle, 100 | UInt32 dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] Boolean bInheritHandle, DuplicateHandleOptions dwOptions); 101 | } 102 | } 103 | } 104 | 105 | 106 | //////////////////////////////// End of File ////////////////////////////////// 107 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/AsyncProgModel/ApmWrap.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ApmWrap.cs 3 | Notices: Copyright (c) 2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Diagnostics; 9 | using System.Diagnostics.Contracts; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | namespace Wintellect.Threading.AsyncProgModel { 15 | /// 16 | /// This class contains utility methods to help with the APM. 17 | /// 18 | public static class ApmWrap { 19 | /// 20 | /// Wraps an AsyncCallback with the calling thread's SynchronizationContext so that the 21 | /// callback method is invoked via posting to the calling thread's SynchronizationContext. 22 | /// 23 | /// The callback method to be invoked via the calling thread's SynchronizationContext 24 | /// The wrapped callback method 25 | public static AsyncCallback SyncContextCallback(AsyncCallback callback) { 26 | // Capture the calling thread's SynchronizationContext-derived object 27 | SynchronizationContext sc = SynchronizationContext.Current; 28 | // If there is no SC, just return what was passed in 29 | if (sc == null) return callback; 30 | // Return a delegate that, when invoked, posts to the captured SC a method that 31 | // calls the original AsyncCallback passing it the IAsyncResult argument 32 | return asyncResult => sc.Post(result => callback((IAsyncResult)result), asyncResult); 33 | } 34 | } 35 | } 36 | 37 | 38 | namespace Wintellect.Threading.AsyncProgModel { 39 | /// 40 | /// This light-weight struct has the ability to associate an arbitrary piece 41 | /// of data (of type T) with any IAsyncResult object. When the asynchronous 42 | /// operation completes, the associated piece of data can be retrieved to 43 | /// complete processing. This struct is typically used when you are 44 | /// implementing code that wraps an asynchronous operation and you wish to 45 | /// add some context or state of your own to complete the wrapping. 46 | /// 47 | /// The type of the data you wish to embed in 48 | /// the IAsyncResult object. 49 | [DebuggerStepThrough] 50 | public struct ApmWrap { 51 | /// 52 | /// Returns a value indicating whether this instance and a specified ApmWrap object represent the same value. 53 | /// 54 | /// An ApmWrap object to compare to this instance. 55 | /// true if value is equal to this instance; otherwise, false. 56 | public Boolean Equals(ApmWrap value) { 57 | return this.SyncContext.Equals(value.SyncContext); 58 | } 59 | 60 | /// 61 | /// Returns a value indicating whether this instance and a specified ApmWrap object represent the same value. 62 | /// 63 | /// An ApmWrap object to compare to this instance. 64 | /// true if value is equal to this instance; otherwise, false. 65 | public override Boolean Equals(Object obj) { 66 | if (obj is ApmWrap) return Equals((ApmWrap) obj); 67 | return false; 68 | } 69 | 70 | /// 71 | /// Returns the hash code for this instance. 72 | /// 73 | /// A 32-bit signed integer hash code. 74 | public override Int32 GetHashCode() { 75 | return base.GetHashCode(); 76 | } 77 | 78 | /// 79 | /// /// Returns a value indicating whether two instances of ApmWrap are equal. 80 | /// 81 | /// An ApmWrap. 82 | /// An ApmWrap. 83 | /// true if obj1 and obj2 are equal; otherwise, false. 84 | public static Boolean operator ==(ApmWrap obj1, ApmWrap obj2) { 85 | return obj1.Equals(obj2); 86 | } 87 | 88 | /// 89 | /// /// Returns a value indicating whether two instances of ApmWrap are not equal. 90 | /// 91 | /// An ApmWrap. 92 | /// An ApmWrap. 93 | /// true if obj1 and obj2 are not equal; otherwise, true. 94 | public static Boolean operator !=(ApmWrap obj1, ApmWrap obj2) { 95 | return !obj1.Equals(obj2); 96 | } 97 | 98 | 99 | /// 100 | /// If non-null when creating an ApmWrap object, the ApmWrap object will 101 | /// force the operation to complete using the specified SynchronizationContext. 102 | /// /// 103 | private SynchronizationContext SyncContext { get; set; } 104 | 105 | /// 106 | /// Call this method to create an ApmWrap object around an asynchronous operation. 107 | /// 108 | /// The data to embed in the ApmWrap object. 109 | /// The callback method that should be invoked when the operation completes. 110 | /// An ApmWrap object's completion method. 111 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "1#")] 112 | public AsyncCallback Callback(T data, AsyncCallback callback) { 113 | if (callback == null) return null; 114 | return new ApmWrapper { 115 | Data = data, AsyncCallback = callback, SyncContext = SyncContext 116 | }.AsyncCallbackInternal; 117 | } 118 | 119 | /// 120 | /// Call this method to create an ApmWrap object around an asynchronous operation. 121 | /// 122 | /// The data to embed in the ApmWrap object. 123 | /// The original IAsyncResult object returned from the BeginXxx method. 124 | /// An ApmWrap object that contains the originally-returned IAsyncResult object. 125 | public IAsyncResult Return(T data, IAsyncResult result) { 126 | return new ApmWrapper { Data = data, AsyncResult = result }; 127 | } 128 | 129 | /// 130 | /// Call this method to unwrap an ApmWrap object to get its embedded data and IAsyncResult. 131 | /// 132 | /// A variable that will receive a reference to the wrapped IAsyncResult object. 133 | /// The embedded piece of data passed to the Callback/Return methods. 134 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1045:DoNotPassTypesByReference", MessageId = "0#")] 135 | public T Unwrap(ref IAsyncResult result) { 136 | Contract.Requires(result != null); 137 | ApmWrapper apmWrap = (ApmWrapper)result; 138 | result = apmWrap.AsyncResult; 139 | return apmWrap.Data; 140 | } 141 | 142 | 143 | [DebuggerStepThrough] 144 | private sealed class ApmWrapper : IAsyncResult { 145 | internal T Data { get; set; } 146 | internal AsyncCallback AsyncCallback { get; set; } 147 | internal SynchronizationContext SyncContext { get; set; } 148 | internal IAsyncResult AsyncResult { get; set; } 149 | internal ApmWrapper() { } 150 | 151 | internal void AsyncCallbackInternal(IAsyncResult result) { 152 | Contract.Requires(result != null); 153 | Contract.Requires(AsyncCallback != null); 154 | this.AsyncResult = result; 155 | if (SyncContext == null) AsyncCallback(this); 156 | else SyncContext.Post(PostCallback, this); 157 | } 158 | 159 | private static void PostCallback(Object state) { 160 | Contract.Requires(state != null); 161 | Contract.Requires(((ApmWrapper)state).AsyncCallback != null); 162 | ApmWrapper apmWrap = (ApmWrapper)state; 163 | apmWrap.AsyncCallback(apmWrap); 164 | } 165 | 166 | public Object AsyncState { get { return AsyncResult.AsyncState; } } 167 | public WaitHandle AsyncWaitHandle { get { return AsyncResult.AsyncWaitHandle; } } 168 | public Boolean CompletedSynchronously { get { return AsyncResult.CompletedSynchronously; } } 169 | public Boolean IsCompleted { get { return AsyncResult.IsCompleted; } } 170 | public override String ToString() { return AsyncResult.ToString(); } 171 | public override Boolean Equals(object obj) { return AsyncResult.Equals(obj); } 172 | public override Int32 GetHashCode() { return AsyncResult.GetHashCode(); } 173 | } 174 | } 175 | } 176 | 177 | 178 | //////////////////////////////// End of File ////////////////////////////////// 179 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/AsyncProgModel/CountdownTimer.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: CountdownTimer.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Diagnostics; 9 | using System.Diagnostics.Contracts; 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.AsyncProgModel { 15 | /// 16 | /// This class offers a timer that implements the asynchronous programming model (APM). 17 | /// 18 | [DebuggerStepThrough] 19 | public sealed class CountdownTimer : IDisposable { 20 | private AsyncResult m_asyncResult; 21 | private Timer m_timer; 22 | 23 | /// Constructs a new CountdownTimer object. 24 | public CountdownTimer() { m_timer = new Timer(CountdownDone); } 25 | 26 | /// Initiates an asynchronous countdown timer operation. 27 | /// How many milliseconds the countdown timer should wait before firing. 28 | /// An optional asynchronous callback, to be called when the timer fires. 29 | /// A user-provided object that distinguishes this particular asynchronous operation from other operations. 30 | /// An IAsyncResult that references the asynchronous countdown operation. 31 | public IAsyncResult BeginCountdown(Int32 ms, AsyncCallback callback, Object state) { 32 | Interlocked.Exchange(ref m_asyncResult, new AsyncResult(callback, state, this)); 33 | Contract.Assume(m_timer != null); 34 | m_timer.Change(ms, Timeout.Infinite); 35 | return m_asyncResult; 36 | } 37 | 38 | private void CountdownDone(Object state) { 39 | Contract.Requires(m_asyncResult != null); 40 | m_asyncResult.SetAsCompleted(null, false); 41 | } 42 | 43 | /// Returns the result of the asynchronous countdown operation. 44 | /// The reference to the pending asynchronous countdown operation. 45 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1822:MarkMembersAsStatic")] 46 | public void EndCountdown(IAsyncResult result) { 47 | Contract.Requires(result != null); 48 | ((AsyncResult) result).EndInvoke(); 49 | } 50 | 51 | /// Releases all resources used by the countdown timer. 52 | public void Dispose() { 53 | if (m_timer == null) return; 54 | m_timer.Dispose(); 55 | m_timer = null; 56 | } 57 | } 58 | } 59 | 60 | 61 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/AsyncProgModel/EventApm.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: EventApm.cs 3 | Notices: Copyright (c) 2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Diagnostics; 8 | using System.Diagnostics.Contracts; 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | namespace Wintellect.Threading.AsyncProgModel { 14 | /// 15 | /// This class represents an asynchronous operation that will be initiated 16 | /// by some method and the operations completes by way of raising an event. 17 | /// 18 | /// The object passed as the event's second argument. 19 | /// This object is usually of an EventArgs-derived type. 20 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Apm"), DebuggerStepThrough] 21 | public sealed class EventApmOperation { 22 | private AsyncCallback m_callback; 23 | private Object m_state; 24 | 25 | internal EventApmOperation(AsyncCallback callback, Object state) { 26 | m_callback = callback; 27 | m_state = state; 28 | } 29 | 30 | /// 31 | /// The event handler that completes the APM operation when invoked. 32 | /// 33 | /// The source of the event. 34 | /// An object (usually derived from EventArgs) that contains the event data. 35 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "e"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "sender")] 36 | public void EventHandler(Object sender, TEventArgs e) { 37 | var result = new AsyncResult(m_callback, m_state); 38 | var acea = e as System.ComponentModel.AsyncCompletedEventArgs; 39 | if ((acea != null) && (acea.Error != null)) result.SetAsCompleted(acea.Error, false); 40 | else result.SetAsCompleted(e, false); 41 | } 42 | } 43 | 44 | /// 45 | /// This class converts a raised event to an IAsyncResult-based APM completion. 46 | /// 47 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Apm"), DebuggerStepThrough] 48 | public struct EventApmFactory { 49 | /// 50 | /// Prepares to initiate an asynchronous operation by setting the desired callback 51 | /// method and state that will be used to completed the operation when the 52 | /// event handler method is invoked. 53 | /// 54 | /// The method to be called when the event is raised. 55 | /// The state obtained via IAsyncResult's AsyncState property. 56 | /// The prepared operation which exposes the event handler method to be registered with the desired event. 57 | public EventApmOperation PrepareOperation(AsyncCallback callback, Object state) { 58 | return new EventApmOperation(callback, state); 59 | } 60 | 61 | /// 62 | /// Prepares to initiate an asynchronous operation by setting the desired callback 63 | /// method that will be used to completed the operation when the 64 | /// event handler method is invoked. 65 | /// 66 | /// The method to be called when the event is raised. 67 | /// The prepared operation which exposes the event handler method to be registered with the desired event. 68 | public EventApmOperation PrepareOperation(AsyncCallback callback) { 69 | return new EventApmOperation(callback, null); 70 | } 71 | 72 | /// 73 | /// Returns the object passed as the second argument to the event handler. 74 | /// This is usually an object whose type is derived from System.EventArgs. 75 | /// Note that you can use any instance of this type to call EndInvoke; you do not 76 | /// have to use the same instance that you used to call PrepareOperation. 77 | /// 78 | /// An IAsyncResult that references the pending operation. 79 | /// The object passed to the event handler. 80 | public TEventArgs EndInvoke(IAsyncResult result) { 81 | Contract.Requires(result != null); 82 | return ((AsyncResult)result).EndInvoke(); 83 | } 84 | 85 | /// Indicates whether this instance and a specified object are equal. 86 | /// Another object to compare to. 87 | /// true if obj and this instance are the same type and represent the same value; otherwise, false. 88 | public override bool Equals(Object obj) { 89 | if (obj == null) return false; 90 | return obj.GetType() == this.GetType(); 91 | } 92 | 93 | /// Returns a value indicating whether two instances of EventApmFactory are equal. 94 | /// A reference to an EventApmFactory object. 95 | /// A reference to an EventApmFactory object. 96 | /// true if factory1 and factory2 are equal; otherwise, false. 97 | public static Boolean operator==(EventApmFactory factory1, EventApmFactory factory2) { 98 | return factory1.Equals(factory2); 99 | } 100 | 101 | /// Returns a value indicating whether two instances of EventApmFactory are not equal. 102 | /// A reference to an EventApmFactory object. 103 | /// A reference to an EventApmFactory object. 104 | /// true if factory1 and factory2 are not equal; otherwise, false. 105 | public static Boolean operator !=(EventApmFactory factory1, EventApmFactory factory2) { 106 | return !factory1.Equals(factory2); 107 | } 108 | 109 | /// Returns the hash code for this instance. 110 | /// A 32-bit signed integer that is the hash code for this instance. 111 | public override int GetHashCode() { return base.GetHashCode(); } 112 | } 113 | } 114 | 115 | 116 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/AsyncProgModel/SyncContextAsyncCallback.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: SyncContextAsyncCallback.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Diagnostics; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | #if NO 16 | namespace Wintellect.Threading.AsyncProgModel { 17 | /// 18 | /// This class invokes an AsyncCallback delegate via a specific SynchronizationContext object. 19 | /// 20 | [DebuggerStepThrough] 21 | public sealed class SyncContextAsyncCallback { 22 | // One delegate for ALL instances of this class 23 | private static readonly SendOrPostCallback s_SendOrPostCallback = 24 | new SendOrPostCallback(SendOrPostCallback); 25 | 26 | // One SyncContextAsyncCallback object is created 27 | // per callback with the following state: 28 | private SynchronizationContext m_syncContext; 29 | private Boolean m_send; // versus Post 30 | private AsyncCallback m_originalCallback; 31 | private IAsyncResult m_result; 32 | 33 | /// 34 | /// Wraps the calling thread's SynchronizationContext object around the specified AsyncCallback. 35 | /// 36 | /// The method that should be invoked using 37 | /// the calling thread's SynchronizationContext. 38 | /// true if the AsyncCallback should be invoked via send; false if post. 39 | /// The wrapped AsyncCallback delegate. 40 | public static AsyncCallback Wrap(AsyncCallback callback, Boolean send) { 41 | // If no sync context, the just call through the original delegate 42 | SynchronizationContext syncContext = SynchronizationContext.Current; 43 | if (syncContext == null) return callback; 44 | 45 | // If there is a synchronization context, then call through it 46 | // NOTE: A delegate object is constructed here 47 | return new AsyncCallback( 48 | (new SyncContextAsyncCallback(syncContext, callback, send)).AsyncCallback); 49 | } 50 | 51 | /// 52 | /// Wraps the calling thread's SynchronizationContext object around the specified AsyncCallback. 53 | /// 54 | /// The method that should be invoked using 55 | /// the calling thread's SynchronizationContext. 56 | /// The wrapped AsyncCallback delegate. 57 | public static AsyncCallback Wrap(AsyncCallback callback) { 58 | return Wrap(callback, false); // Default to Posting 59 | } 60 | 61 | private SyncContextAsyncCallback(SynchronizationContext syncContext, AsyncCallback callback, Boolean send) { 62 | m_originalCallback = callback; 63 | m_syncContext = syncContext; 64 | m_send = send; 65 | } 66 | 67 | private void AsyncCallback(IAsyncResult result) { 68 | m_result = result; 69 | if (m_send) m_syncContext.Send(s_SendOrPostCallback, this); 70 | else m_syncContext.Post(s_SendOrPostCallback, this); 71 | } 72 | 73 | private static void SendOrPostCallback(Object state) { 74 | SyncContextAsyncCallback scac = (SyncContextAsyncCallback)state; 75 | scac.m_originalCallback(scac.m_result); 76 | } 77 | } 78 | } 79 | #endif 80 | 81 | //////////////////////////////// End of File ////////////////////////////////// 82 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/AsyncProgModel/SyncGate.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: SyncGate.cs 3 | Notices: Copyright (c) 2011 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | #if INCLUDE_GATES 8 | using System; 9 | using System.Threading; 10 | using System.Diagnostics; 11 | using System.Collections.Generic; 12 | 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | 16 | 17 | namespace Wintellect.Threading.AsyncProgModel { 18 | /// 19 | /// Indicates if the SyncGate should be acquired for exclusive or shared access. 20 | /// 21 | public enum SyncGateMode { 22 | /// 23 | /// Indicates that exclusive access is required. 24 | /// 25 | Exclusive, 26 | 27 | /// 28 | /// Indicates that shared access is required. 29 | /// 30 | Shared 31 | } 32 | } 33 | 34 | 35 | /////////////////////////////////////////////////////////////////////////////// 36 | 37 | 38 | namespace Wintellect.Threading.AsyncProgModel { 39 | using Wintellect.Threading.AsyncProgModel; 40 | using System.Diagnostics.Contracts; 41 | 42 | /// 43 | /// This class implements a reader/writer lock that never blocks any threads. 44 | /// This class integrates very well with the AsyncEnumerator class. 45 | /// 46 | public sealed class SyncGate { 47 | private readonly Object m_syncLock = new Object(); 48 | 49 | private enum SyncGateStates { 50 | Free = 0, 51 | OwnedByReaders = 1, 52 | OwnedByReadersAndWriterPending = 2, 53 | OwnedByWriter = 3, 54 | ReservedForWriter = 4 55 | } 56 | private SyncGateStates m_state = SyncGateStates.Free; 57 | private Int32 m_numReaders = 0; 58 | 59 | private readonly Queue m_qWriteRequests = new Queue(); 60 | private readonly Queue m_qReadRequests = new Queue(); 61 | 62 | /// Constructs a SyncGate object. 63 | public SyncGate() : this(false) { } 64 | 65 | /// Constructs a SyncGate object 66 | /// Pass true to have readers block until the first writer has created the data that is being protected by the SyncGate. 67 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 68 | public SyncGate(Boolean blockReadersUntilFirstWriteCompletes) { 69 | m_state = blockReadersUntilFirstWriteCompletes ? SyncGateStates.ReservedForWriter : SyncGateStates.Free; 70 | } 71 | 72 | private sealed class SyncGateAsyncResult : AsyncResult { 73 | private SyncGateMode m_mode; 74 | internal SyncGateMode Mode { get { return m_mode; } } 75 | 76 | internal SyncGateAsyncResult(SyncGateMode mode, AsyncCallback asyncCallback, Object state) 77 | : base(asyncCallback, state) { 78 | m_mode = mode; 79 | } 80 | } 81 | 82 | #region BeginRegion/EndRegion Members 83 | /// 84 | /// Allows the caller to notify the SyncGate that it wants exclusive or shared access to a resource. 85 | /// 86 | /// Indicates if exclusive or shared access is desired. 87 | /// The callback method to invoke once access can be granted. 88 | public void BeginRegion(SyncGateMode mode, AsyncCallback asyncCallback) { 89 | BeginRegion(mode, asyncCallback, null); 90 | } 91 | 92 | /// 93 | /// Allows the caller to notify the SyncGate that it wants exclusive or shared access to a resource. 94 | /// 95 | /// Indicates if exclusive or shared access is desired. 96 | /// The callback method to invoke once access can be granted. 97 | /// Additional state to pass to the callback method. 98 | public void BeginRegion(SyncGateMode mode, AsyncCallback asyncCallback, Object asyncState) { 99 | Contract.Assume(m_qReadRequests != null); 100 | Contract.Assume(m_qWriteRequests != null); 101 | // This method supports the method callback version of the IAsyncResult APM only; therefore, 102 | // a callback method must always be specified and this is also why the method returns void 103 | // instead of returning an IAsyncResult 104 | if (asyncCallback == null) throw new ArgumentNullException("asyncCallback"); 105 | SyncGateAsyncResult ar = new SyncGateAsyncResult(mode, asyncCallback, asyncState); 106 | Boolean goodToGo = false; 107 | Monitor.Enter(m_syncLock); 108 | switch (mode) { 109 | case SyncGateMode.Exclusive: 110 | switch (m_state) { 111 | case SyncGateStates.Free: // If Free | RFW -> OBW, invoke, return 112 | case SyncGateStates.ReservedForWriter: 113 | m_state = SyncGateStates.OwnedByWriter; 114 | goodToGo = true; // QueueCallback(ar); 115 | break; 116 | 117 | case SyncGateStates.OwnedByReaders: // If OBR | OBRAWP -> OBRAWP, queue, return 118 | case SyncGateStates.OwnedByReadersAndWriterPending: 119 | m_state = SyncGateStates.OwnedByReadersAndWriterPending; 120 | m_qWriteRequests.Enqueue(ar); 121 | break; 122 | 123 | case SyncGateStates.OwnedByWriter: // If OBW, queue, return 124 | m_qWriteRequests.Enqueue(ar); 125 | break; 126 | } 127 | break; 128 | 129 | case SyncGateMode.Shared: 130 | switch (m_state) { 131 | case SyncGateStates.Free: // If Free | OBR -> OBR, NR++, invoke, return 132 | case SyncGateStates.OwnedByReaders: 133 | m_state = SyncGateStates.OwnedByReaders; 134 | m_numReaders++; 135 | goodToGo = true; // QueueCallback(ar); 136 | break; 137 | 138 | case SyncGateStates.OwnedByWriter: // If OBW | OBRAWP | RFW, queue, return 139 | case SyncGateStates.OwnedByReadersAndWriterPending: 140 | case SyncGateStates.ReservedForWriter: 141 | m_qReadRequests.Enqueue(ar); 142 | break; 143 | } 144 | break; 145 | } 146 | Monitor.Exit(m_syncLock); 147 | if (goodToGo) ar.SetAsCompleted(null, true); 148 | } 149 | 150 | /// 151 | /// Call this method after accessing the resource to notify the SyncGate that it can grant access to other code. 152 | /// 153 | /// The IAsyncResult object given to the callback method when access was granted. 154 | public void EndRegion(IAsyncResult result) { 155 | if (result == null) throw new ArgumentNullException("result"); 156 | SyncGateAsyncResult sgar = (SyncGateAsyncResult)result; 157 | sgar.EndInvoke(); 158 | 159 | Monitor.Enter(m_syncLock); 160 | if (sgar.Mode == SyncGateMode.Shared) { 161 | // Subtract a reader and return (without changing the gate's state) 162 | // if this is not the last reader 163 | if (--m_numReaders > 0) { 164 | Monitor.Exit(m_syncLock); 165 | return; 166 | } 167 | 168 | // This was the last reader, wake up any queued requests 169 | } 170 | 171 | Contract.Assume(m_qReadRequests != null); 172 | Contract.Assume(m_qWriteRequests != null); 173 | 174 | // Wake-up any queued requests 175 | if (m_qWriteRequests.Count > 0) { 176 | // A writer is queued, invoke it 177 | m_state = SyncGateStates.OwnedByWriter; 178 | QueueCallback(m_qWriteRequests.Dequeue()); 179 | } else if (m_qReadRequests.Count > 0) { 180 | // Reading requests are queued, invoke all of them 181 | m_state = SyncGateStates.OwnedByReaders; 182 | m_numReaders = m_qReadRequests.Count; 183 | while (m_qReadRequests.Count > 0) { 184 | // The 1st reader can run on this thread; the others will be on thread pool threads 185 | QueueCallback(m_qReadRequests.Dequeue()); 186 | } 187 | } else { 188 | // No requests are queued, free the gate 189 | m_state = SyncGateStates.Free; 190 | } 191 | Monitor.Exit(m_syncLock); 192 | } 193 | 194 | private static void QueueCallback(SyncGateAsyncResult sgar) { 195 | ThreadPool.QueueUserWorkItem(InvokeCallback, sgar); 196 | } 197 | private static void InvokeCallback(Object o) { 198 | Contract.Requires(o != null); 199 | ((SyncGateAsyncResult)o).SetAsCompleted(null, false); 200 | } 201 | #endregion 202 | } 203 | } 204 | #endif 205 | 206 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/LogicalProcessor/NumaInformation.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: NumaInformation.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.ComponentModel; 9 | using System.Runtime.InteropServices; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect.Threading.LogicalProcessor { 16 | /// 17 | /// This class returns NUMA information about the host machine. 18 | /// 19 | public static class NumaInformation { 20 | /// 21 | /// A constant indicating that there is no preferred node. 22 | /// 23 | public const Int32 NoPreferredNode = -1; 24 | private static readonly Int32 s_highestNode; 25 | 26 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1065:DoNotRaiseExceptionsInUnexpectedLocations")] 27 | static NumaInformation() { 28 | if (!NativeMethods.GetNumaHighestNodeNumber(out s_highestNode)) 29 | throw new Win32Exception(); 30 | } 31 | 32 | /// 33 | /// Retrieves the node that currently has the highest number. 34 | /// 35 | public static Int32 HighestNode { get { return s_highestNode; } } 36 | 37 | /// 38 | /// Retrieves the node number for the specified processor. 39 | /// 40 | /// The processor number. 41 | /// The node number. 42 | public static Int32 GetNodeFromProcessor(Int32 processor) { 43 | Byte nodeNumber; 44 | if (NativeMethods.GetNumaProcessorNode((Byte) processor, out nodeNumber)) return nodeNumber; 45 | throw new Win32Exception(); 46 | } 47 | 48 | /// 49 | /// Retrieves the processor mask for the specified node. 50 | /// 51 | /// The node number. 52 | /// The processor mask for the node. A processor mask is 53 | /// a bit vector in which each bit represents a processor and 54 | /// whether it is in the node. 55 | [CLSCompliant(false)] 56 | public static UInt64 GetProcessorsFromNode(Int32 node) { 57 | UInt64 mask; 58 | if (NativeMethods.GetNumaNodeProcessorMask((Byte) node, out mask)) return mask; 59 | throw new Win32Exception(); 60 | } 61 | 62 | /// 63 | /// Retrieves the amount of memory available in the specified node. 64 | /// 65 | /// The numa node. 66 | /// The amount of available memory for the node, in bytes. 67 | [CLSCompliant(false)] 68 | public static UInt64 GetAvailableMemoryOnNode(Int32 node) { 69 | UInt64 bytes; 70 | if (NativeMethods.GetNumaAvailableMemoryNode((Byte) node, out bytes)) return bytes; 71 | throw new Win32Exception(); 72 | } 73 | 74 | /// 75 | /// Retrieves the node number for the specified proximity identifier. 76 | /// 77 | /// The proximity identifier of the node. 78 | /// The node number. 79 | public static Int32 ProximityNode(Int32 proximityId) { 80 | Byte nodeNumber; 81 | if (NativeMethods.GetNumaProximityNode(proximityId, out nodeNumber)) return nodeNumber; 82 | throw new Win32Exception(); 83 | } 84 | 85 | private static class NativeMethods { 86 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 87 | [return: MarshalAs(UnmanagedType.Bool)] 88 | internal static extern Boolean GetNumaHighestNodeNumber(out Int32 HighestNodeNumber); 89 | 90 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 91 | [return: MarshalAs(UnmanagedType.Bool)] 92 | internal static extern Boolean GetNumaProcessorNode(Byte Processor, out Byte NodeNumber); 93 | 94 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 95 | [return: MarshalAs(UnmanagedType.Bool)] 96 | internal static extern Boolean GetNumaNodeProcessorMask(Byte Node, out UInt64 ProcessorMask); 97 | 98 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 99 | [return: MarshalAs(UnmanagedType.Bool)] 100 | internal static extern Boolean GetNumaAvailableMemoryNode(Byte Node, out UInt64 AvailableBytes); 101 | 102 | [DllImport("Kernel32", ExactSpelling = true, SetLastError = true)] 103 | [return: MarshalAs(UnmanagedType.Bool)] 104 | internal static extern Boolean GetNumaProximityNode(Int32 ProximityId, out Byte NodeNumber); 105 | } 106 | } 107 | } 108 | 109 | 110 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/NativeMethods.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using System; 3 | using System.Runtime.InteropServices; 4 | using System.Runtime.ConstrainedExecution; 5 | 6 | namespace PrivilegeClass { 7 | [Flags] 8 | public enum TokenAccessLevels { 9 | AssignPrimary = 0x00000001, 10 | Duplicate = 0x00000002, 11 | Impersonate = 0x00000004, 12 | Query = 0x00000008, 13 | QuerySource = 0x00000010, 14 | AdjustPrivileges = 0x00000020, 15 | AdjustGroups = 0x00000040, 16 | AdjustDefault = 0x00000080, 17 | AdjustSessionId = 0x00000100, 18 | 19 | Read = 0x00020000 | Query, 20 | 21 | Write = 0x00020000 | AdjustPrivileges | AdjustGroups | AdjustDefault, 22 | 23 | AllAccess = 0x000F0000 | 24 | AssignPrimary | 25 | Duplicate | 26 | Impersonate | 27 | Query | 28 | QuerySource | 29 | AdjustPrivileges | 30 | AdjustGroups | 31 | AdjustDefault | 32 | AdjustSessionId, 33 | 34 | MaximumAllowed = 0x02000000 35 | } 36 | 37 | public enum SecurityImpersonationLevel { 38 | Anonymous = 0, 39 | Identification = 1, 40 | Impersonation = 2, 41 | Delegation = 3, 42 | } 43 | 44 | public enum TokenType { 45 | Primary = 1, 46 | Impersonation = 2, 47 | } 48 | 49 | internal static class NativeMethods { 50 | private const uint SE_PRIVILEGE_DISABLED = 0x00000000; 51 | private const uint SE_PRIVILEGE_ENABLED = 0x00000002; 52 | 53 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 54 | private struct LUID { 55 | internal uint LowPart; 56 | internal uint HighPart; 57 | } 58 | 59 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 60 | private struct LUID_AND_ATTRIBUTES { 61 | internal LUID Luid; 62 | internal uint Attributes; 63 | } 64 | 65 | [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] 66 | private struct TOKEN_PRIVILEGE { 67 | internal uint PrivilegeCount; 68 | internal LUID_AND_ATTRIBUTES Privilege; 69 | } 70 | 71 | private const string ADVAPI32 = "advapi32.dll"; 72 | internal const string KERNEL32 = "kernel32.dll"; 73 | 74 | private const int ERROR_SUCCESS = 0x0; 75 | private const int ERROR_ACCESS_DENIED = 0x5; 76 | private const int ERROR_NOT_ENOUGH_MEMORY = 0x8; 77 | private const int ERROR_NO_TOKEN = 0x3f0; 78 | private const int ERROR_NOT_ALL_ASSIGNED = 0x514; 79 | private const int ERROR_NO_SUCH_PRIVILEGE = 0x521; 80 | private const int ERROR_CANT_OPEN_ANONYMOUS = 0x543; 81 | 82 | [DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)] 83 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 84 | private static extern Boolean CloseHandle(IntPtr handle); 85 | 86 | [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] 87 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 88 | private static extern Boolean AdjustTokenPrivileges(SafeTokenHandle TokenHandle, 89 | Boolean DisableAllPrivileges, [In] ref TOKEN_PRIVILEGE NewState, UInt32 BufferLength, 90 | [In, Out] ref TOKEN_PRIVILEGE PreviousState, [In, Out] ref uint ReturnLength); 91 | 92 | [DllImport(ADVAPI32, ExactSpelling = true, SetLastError = true)] 93 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 94 | private static extern Boolean RevertToSelf(); 95 | 96 | [DllImport(ADVAPI32, EntryPoint = "LookupPrivilegeValueW", CharSet = CharSet.Unicode, SetLastError = true)] 97 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 98 | private static extern Boolean LookupPrivilegeValue(String lpSystemName, String lpName, [In, Out] ref LUID Luid); 99 | 100 | [DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)] 101 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 102 | internal static extern IntPtr GetCurrentProcess(); 103 | 104 | [DllImport(KERNEL32, ExactSpelling = true, SetLastError = true)] 105 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 106 | internal static extern IntPtr GetCurrentThread(); 107 | 108 | [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] 109 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 110 | internal static extern Boolean OpenProcessToken(IntPtr ProcessToken, 111 | TokenAccessLevels DesiredAccess, [In, Out] ref SafeTokenHandle TokenHandle); 112 | 113 | [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] 114 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 115 | internal static extern Boolean OpenThreadToken(IntPtr ThreadToken, TokenAccessLevels DesiredAccess, 116 | Boolean OpenAsSelf, [In, Out] ref SafeTokenHandle TokenHandle); 117 | 118 | [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] 119 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 120 | internal static extern Boolean DuplicateTokenEx(SafeTokenHandle ExistingToken, 121 | TokenAccessLevels DesiredAccess, IntPtr TokenAttributes, 122 | SecurityImpersonationLevel ImpersonationLevel, TokenType TokenType, 123 | [In, Out] ref SafeTokenHandle NewToken); 124 | 125 | [DllImport(ADVAPI32, CharSet = CharSet.Unicode, SetLastError = true)] 126 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)] 127 | internal static extern Boolean SetThreadToken(IntPtr Thread, SafeTokenHandle Token); 128 | } 129 | } 130 | #endif -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/Progress.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Progress.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using Wintellect.Threading; 10 | using Wintellect.Threading.ResourceLocks; 11 | using System.Globalization; 12 | 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | 16 | 17 | namespace Wintellect.Threading { 18 | /// 19 | /// A thread-safe class for managing the progress of an operation. 20 | /// 21 | public sealed class Progress : IDisposable { 22 | private SyncContextEventRaiser m_syncContentEventRaiser = new SyncContextEventRaiser(); 23 | private ResourceLock m_lock = new MonitorResourceLock(); 24 | private Int64 m_low = 0, m_current = 0, m_high = 0; 25 | private Timer m_timer = null; 26 | private Int64 m_timerUpdateAmount = 0; 27 | 28 | /// 29 | /// Constructs a Progress object with a low and high value of zero. 30 | /// 31 | public Progress() : this(0, 0) { } 32 | 33 | /// 34 | /// Constructs a Progress object with a low value of zero. 35 | /// 36 | /// The value indicating the completion of the operation. 37 | public Progress(Int64 high) : this(0, high) { } 38 | 39 | /// 40 | /// Constructs a Progress object with the specified low and high values. 41 | /// 42 | /// The value indicating the start of the operation. 43 | /// The value indicating the completion of the operation. 44 | public Progress(Int64 low, Int64 high) { 45 | m_timer = new Timer(TimerProgressUpdate); 46 | SetValues(low, high, low); 47 | } 48 | 49 | /// 50 | /// Sets all the values associated with maintaining progress of an operation. 51 | /// 52 | /// The value indicating the start of the operation. 53 | /// The value indicating the completion of the operation. 54 | /// The value indicating the current completion state of the operation. 55 | public void Reset(Int64 low, Int64 high, Int64 current) { 56 | StopTimer(); 57 | SetValues(low, high, current); 58 | } 59 | 60 | /// 61 | /// Call this to indicate that Progress tracking for this operation is complete. 62 | /// 63 | public void Dispose() { 64 | m_timer.Dispose(); 65 | m_lock.Dispose(); 66 | } 67 | 68 | /// 69 | /// Allows Progress to automatically update periodically. 70 | /// 71 | /// Indicates how long to wait before each update to Progress. 72 | /// How much to add to the current status. 73 | public void SetTimer(Int32 millisecondsBetweenUpdates, Int64 timerUpdateAmount) { 74 | m_timerUpdateAmount = timerUpdateAmount; 75 | m_timer.Change(millisecondsBetweenUpdates, millisecondsBetweenUpdates); 76 | } 77 | 78 | /// 79 | /// Stops the timer from continuing to update progress status. 80 | /// 81 | public void StopTimer() { 82 | SetTimer(Timeout.Infinite, 0); 83 | } 84 | private void TimerProgressUpdate(Object state) { 85 | AddToCurrent(m_timerUpdateAmount); 86 | } 87 | 88 | /// 89 | /// Returns the value indicating the start of the operation. 90 | /// 91 | public Int64 Low { get { return m_low; } } 92 | 93 | /// 94 | /// Sets the value indicating the start of the operation. 95 | /// 96 | /// The value indicating the start of the operation. 97 | public void SetLow(Int64 value) { 98 | SetValues(value, null, null); 99 | } 100 | 101 | /// 102 | /// Adds the specified value to the value that indicates the start of the operation. 103 | /// 104 | /// How much to add. 105 | public void AddToLow(Int64 addend) { 106 | AddToValues(addend, 0, 0); 107 | } 108 | 109 | /// 110 | /// Returns the value indicating the end of the operation. 111 | /// 112 | public Int64 High { get { return m_high; } } 113 | 114 | /// 115 | /// Sets the value indicating the end of the operation. 116 | /// 117 | /// The value indicating the end of the operation. 118 | public void SetHigh(Int64 value) { 119 | SetValues(null, value, null); 120 | } 121 | 122 | /// 123 | /// Adds the specified value to the value that indicates the end of the operation. 124 | /// 125 | /// How much to add. 126 | public void AddToHigh(Int64 addend) { 127 | AddToValues(0, addend, 0); 128 | } 129 | 130 | 131 | /// 132 | /// Returns the value indicating the current state of the operation. 133 | /// 134 | public Int64 Current { get { return m_current; } } 135 | 136 | /// 137 | /// Sets the value indicating the current state of the operation. 138 | /// 139 | /// The value indicating the current state of the operation. 140 | public void SetCurrent(Int64 value) { 141 | SetValues(null, null, value); 142 | } 143 | 144 | /// 145 | /// Adds the specified value to the value that indicates the current state of the operation. 146 | /// 147 | /// How much to add. 148 | public void AddToCurrent(Int64 addend) { 149 | AddToValues(0, 0, addend); 150 | } 151 | 152 | private void AddToValues(Int64 lowAddend, Int64 highAddend, Int64 currentAddend) { 153 | Boolean reportProgressUpdate; 154 | m_lock.Enter(true); 155 | reportProgressUpdate = SetValues(true, m_low + lowAddend, m_high + highAddend, m_current + currentAddend); 156 | m_lock.Leave(); 157 | ReportProgressUpdate(reportProgressUpdate); 158 | } 159 | 160 | // A value of null means that the value doesn't change 161 | private void SetValues(Int64? low, Int64? high, Int64? current) { 162 | ReportProgressUpdate(SetValues(false, low, high, current)); 163 | } 164 | 165 | // Returns true if low, high, or current has changed 166 | private Boolean SetValues(Boolean lockAlreadyTaken, Int64? low, Int64? high, Int64? current) { 167 | if (!lockAlreadyTaken) m_lock.Enter(true); 168 | try { 169 | // If any value is null, set it to its current value (assume no change) 170 | low = low.GetValueOrDefault(m_low); 171 | high = high.GetValueOrDefault(m_high); 172 | current = current.GetValueOrDefault(m_current); 173 | 174 | if (low > high) throw new InvalidOperationException("Low can't be greater than high"); 175 | 176 | Int64 oldLow = m_low, oldHigh = m_high, oldCurrent = m_current; 177 | m_low = low.Value; 178 | m_high = high.Value; 179 | 180 | // Make sure Current stays between Low and High inclusive 181 | if (current < m_low) current = m_low; 182 | if (current > m_high) current = m_high; 183 | m_current = current.Value; 184 | 185 | return (oldLow != m_low) || (oldHigh != m_high) || (oldCurrent != m_current); 186 | } 187 | finally { 188 | if (!lockAlreadyTaken) m_lock.Leave(); 189 | } 190 | } 191 | 192 | /// 193 | /// An event which is raised whenever the operation's low, current, or high value changes. 194 | /// This event is raised using the SynchronizationContext that was in place on 195 | /// the thread that constructed this Progress object. 196 | /// 197 | public event EventHandler ProgressUpdated; 198 | private void ReportProgressUpdate(Boolean reportProgressUpdate) { 199 | if (!reportProgressUpdate) return; 200 | m_syncContentEventRaiser.PostEvent(OnProgressUpdate, 201 | new ProgressUpdateEventArgs(m_low, m_high, m_current)); 202 | } 203 | 204 | private void OnProgressUpdate(ProgressUpdateEventArgs e) { 205 | EventHandler t = ProgressUpdated; 206 | if (t != null) t(this, e); 207 | } 208 | } 209 | } 210 | 211 | 212 | /////////////////////////////////////////////////////////////////////////////// 213 | 214 | 215 | namespace Wintellect.Threading { 216 | /// 217 | /// Indicates the current progress of an operation. 218 | /// 219 | public sealed class ProgressUpdateEventArgs : EventArgs { 220 | private readonly Int64 m_low, m_high, m_current; 221 | private readonly Int32 m_percentage; 222 | 223 | internal ProgressUpdateEventArgs(Int64 low, Int64 high, Int64 current) { 224 | m_low = low; 225 | m_high = high; 226 | m_current = current; 227 | try { 228 | m_percentage = (Int32)((100 * (m_current - m_low)) / (m_high - m_low)); 229 | } 230 | catch (DivideByZeroException) { /* m_percentage will be 0 */ } 231 | } 232 | 233 | /// 234 | /// Returns the value representing the start of the operation. 235 | /// 236 | public Int64 Low { get { return m_low; } } 237 | 238 | /// 239 | /// Returns the value representing the end of the operation. 240 | /// 241 | public Int64 High { get { return m_high; } } 242 | 243 | /// 244 | /// Returns a value representing the current state of the operation. 245 | /// 246 | public Int64 Current { get { return m_current; } } 247 | 248 | /// 249 | /// Returns a percentage of how much of the operation has completed thus far. 250 | /// 251 | public Int32 Percentage { get { return m_percentage; } } 252 | 253 | /// 254 | /// Returns a string representing the state of this object. 255 | /// 256 | /// The string representing the state of the object. 257 | public override String ToString() { 258 | return String.Format(CultureInfo.CurrentCulture, 259 | "Low={0}, High={1}, Current={2}, Percentage={3}%", 260 | Low, High, Current, Percentage); 261 | } 262 | } 263 | } 264 | 265 | 266 | //////////////////////////////// End of File ////////////////////////////////// 267 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/ConditionVariable.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | /****************************************************************************** 3 | Module: ConditionVariable.cs 4 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 5 | ******************************************************************************/ 6 | 7 | 8 | using System; 9 | using System.Threading; 10 | using System.Diagnostics.Contracts; 11 | 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | // This class allows a ResourceLock to be used with a Condition Variable 17 | namespace Wintellect.Threading.ResourceLocks { 18 | /// 19 | /// Adds condition variable support to a ResourceLock class. 20 | /// 21 | public class ConditionVariable : IDisposable { 22 | // Contains the number of threads that are paused on the condition variable 23 | private Int32 m_numPausedThreads = 0; 24 | 25 | // Used to wake up threads paused on the condition variable 26 | // private Semaphore m_semaphore = new Semaphore(0, Int32.MaxValue); 27 | 28 | /// 29 | /// Releases all resources used by the ConditionVariable. 30 | /// 31 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA1816:CallGCSuppressFinalizeCorrectly")] 32 | public void Dispose() { Dispose(true); } 33 | 34 | /// 35 | /// Releases all resources associated with the ConditionVariable 36 | /// 37 | /// 38 | protected virtual void Dispose(Boolean disposing) { /* if (disposing) ((IDisposable) m_semaphore).Dispose();*/ } 39 | 40 | /// 41 | /// Constructs a ConditionVariable object. 42 | /// 43 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 44 | public ConditionVariable() { 45 | } 46 | 47 | /// 48 | /// Causes the calling thread to enter a condition variable wait using the specified ResourceLock. 49 | /// 50 | /// A reference to the ResourceLock object that will be 51 | /// temporarily released while waiting for the condition to change. 52 | public void CVWait(ResourceLock resourceLock) { 53 | Contract.Requires(resourceLock != null); 54 | // If lock is held by a writer, reacquire it for writing 55 | Boolean writing = resourceLock.CurrentWriterCount() > 0; 56 | CVWait(resourceLock, writing); 57 | } 58 | 59 | /// 60 | /// Causes the calling thread to enter a condition variable wait using the specified ResourceLock. 61 | /// 62 | /// A reference to the ResourceLock object that will be 63 | /// temporarily released while waiting for the condition to change. 64 | /// true if the ResourceLock should be reacquired for writing when the condition changes; 65 | /// false if the lock should be reacquired for reading when the condition changes. 66 | public void CVWait(ResourceLock resourceLock, Boolean reacquireForWriting) { 67 | Contract.Requires(resourceLock != null); 68 | // We can't wait on a lock that is free; the lock must currently be held 69 | if (resourceLock.CurrentlyFree()) 70 | throw new InvalidOperationException("Can't wait on free lock."); 71 | 72 | // Indicate that this thread is going to pause 73 | // This value is "decremented" in Unpause 74 | Interlocked.Increment(ref m_numPausedThreads); 75 | //Console.WriteLine("{0}: Inc to {1}", Thread.CurrentThread.ManagedThreadId, m_numPausedThreads); 76 | 77 | AutoResetEvent are = new AutoResetEvent(false); 78 | m_waitingThreads.AddLast(are); 79 | 80 | 81 | // Find out if the lock is held by readers or a writer 82 | //Boolean reading = resourceLock.CurrentReaderCount() > 0; 83 | 84 | // Release the lock held by this thread 85 | resourceLock.Leave(); 86 | 87 | // Make this thread paused until unpaused 88 | are.WaitOne(); //m_semaphore.WaitOne(); 89 | 90 | // Make this thread regain the lock it used to hold 91 | resourceLock.Enter(reacquireForWriting); 92 | } 93 | 94 | System.Collections.Generic.LinkedList m_waitingThreads = new System.Collections.Generic.LinkedList(); 95 | 96 | /// 97 | /// Wakes a single thread that is currently inside a call to CVWait. 98 | /// 99 | public void CVPulseOne() { CVPulse(true); } 100 | 101 | /// 102 | /// Wakes all threads that are currently inside a call to CVWait. 103 | /// 104 | public void CVPulseAll() { CVPulse(false); } 105 | 106 | private void CVPulse(Boolean justOne) { 107 | Int32 count = 0; 108 | if (justOne) { 109 | // If count of paused threads is great than zero, unpause one of them 110 | if (InterlockedEx.DecrementIfGreaterThan(ref m_numPausedThreads, 0) > 0) 111 | count = 1; 112 | } else { 113 | // Get count of paused threads and set to 0 114 | count = Interlocked.Exchange(ref m_numPausedThreads, 0); 115 | } 116 | //Console.WriteLine("{0}: releasing {1}", Thread.CurrentThread.ManagedThreadId, count); 117 | for (Int32 n = 0; n < count; n++) { 118 | m_waitingThreads.First.Value.Set(); 119 | m_waitingThreads.RemoveFirst(); 120 | } 121 | //if (count == 0) return; // No threads were paused, return 122 | //m_semaphore.Release(count); // Unpause 1 or all threads 123 | } 124 | } 125 | } 126 | 127 | 128 | //////////////////////////////// End of File ////////////////////////////////// 129 | #endif -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/ExclusiveOwnerResourceLockModifier.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ExclusiveOwnerResourceLockModifier.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Collections.Generic; 9 | using Wintellect; 10 | using System.Diagnostics.Contracts; 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 15 | internal struct ExclusiveOwnerResourceLockHelper { 16 | private Int32 m_owningThreadId; 17 | private readonly IDisposable m_afterWaitDisposer; 18 | private readonly IDisposable m_afterReleaseDisposer; 19 | 20 | public ExclusiveOwnerResourceLockHelper(ResourceLock resLock) { 21 | Contract.Requires(resLock != null); 22 | if (!resLock.IsMutualExclusive) 23 | throw new ArgumentException("resLock must identify a ResourceLock that is really a mutual-exclusive lock"); 24 | 25 | if (resLock.SupportsRecursion) 26 | throw new ArgumentException("resLock must identify a ResourceLock that does not support recursion"); 27 | 28 | m_owningThreadId = 0; 29 | 30 | // C# requires that all fields be assigned to before 'this' is used (when newing the Disposer objects) 31 | m_afterWaitDisposer = null; 32 | m_afterReleaseDisposer = null; 33 | 34 | m_afterWaitDisposer = new Disposer(AfterWait); 35 | m_afterReleaseDisposer = new Disposer(AfterRelease); 36 | } 37 | 38 | // Call this method just before waiting on the lock. 39 | public IDisposable BeforeWait() { 40 | Int32 callingThreadId = Thread.CurrentThread.ManagedThreadId; 41 | 42 | // If the calling thread already owns the lock, we have a deadlock 43 | if (callingThreadId == m_owningThreadId) 44 | Environment.FailFast("Calling thread already owns this lock"); 45 | return m_afterWaitDisposer; 46 | } 47 | 48 | // Call this method just after waiting sucessfully on the lock. 49 | public void AfterWait() { 50 | m_owningThreadId = Thread.CurrentThread.ManagedThreadId; // The calling thread is the owner 51 | } 52 | 53 | public IDisposable BeforeRelease() { 54 | Int32 callingThreadId = Thread.CurrentThread.ManagedThreadId; 55 | if (m_owningThreadId != callingThreadId) 56 | throw new InvalidOperationException("Calling thread doesn't own this lock!"); 57 | return m_afterReleaseDisposer; 58 | } 59 | 60 | public void AfterRelease() { 61 | m_owningThreadId = 0; // The lock is becoming unowned 62 | } 63 | } 64 | } 65 | 66 | 67 | /////////////////////////////////////////////////////////////////////////////// 68 | 69 | 70 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 71 | /// 72 | /// Modifies a ResourceLock enforcing that whatever thread acquires the lock must also release the lock. 73 | /// 74 | public class ExclusiveOwnerResourceLockModifier: ResourceLockModifier { 75 | 76 | private ExclusiveOwnerResourceLockHelper m_exclusiveOwner; 77 | 78 | /// 79 | /// Constructs an ExclusiveOwnerResourceLockModifier over the specified ResourceLock. 80 | /// 81 | /// 82 | public ExclusiveOwnerResourceLockModifier(ResourceLock resLock) 83 | : base(resLock, ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.IsMutualExclusive) { 84 | Contract.Requires(resLock != null); 85 | m_exclusiveOwner = new ExclusiveOwnerResourceLockHelper(resLock); 86 | } 87 | 88 | #region Override of ResourceLock Members 89 | /// 90 | /// Implements the ResourceLock's WaitToWrite behavior. 91 | /// 92 | protected override void OnEnter(Boolean exclusive) { 93 | if (exclusive) { 94 | using (m_exclusiveOwner.BeforeWait()) { 95 | base.OnEnter(exclusive); 96 | } 97 | } else { 98 | using (m_exclusiveOwner.BeforeWait()) { 99 | base.OnEnter(exclusive); 100 | } 101 | } 102 | } 103 | 104 | /// 105 | /// Implements the ResourceLock's DoneWriting behavior. 106 | /// 107 | protected override void OnLeave(Boolean exclusive) { 108 | if (exclusive) { 109 | using (m_exclusiveOwner.BeforeRelease()) { 110 | base.OnLeave(exclusive); 111 | } 112 | } else { 113 | using (m_exclusiveOwner.BeforeRelease()) { 114 | base.OnLeave(exclusive); 115 | } 116 | } 117 | } 118 | #endregion 119 | } 120 | } 121 | 122 | 123 | //////////////////////////////// End of File ////////////////////////////////// 124 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/RecursionResourceLockModifier.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: RecursionResourceLockModifier.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Collections.Generic; 9 | using System.Globalization; 10 | using System.Diagnostics.Contracts; 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 16 | /// 17 | /// A ResourceLock modifier that adds recursion support to the inner lock. 18 | /// 19 | public class RecursionResourceLockModifier : ResourceLockModifier { 20 | private struct ThreadIdAndRecurseCount { 21 | public Int32 m_Id, m_Count; 22 | public override String ToString() { 23 | return String.Format(CultureInfo.InvariantCulture, "Id={0}, Count={1}", m_Id, m_Count); 24 | } 25 | } 26 | 27 | private ThreadIdAndRecurseCount m_WriterThreadIdAndRecurseCount; 28 | private ThreadIdAndRecurseCount[] m_ReaderThreadIdsAndRecurseCounts; 29 | /// 30 | /// Constructs a RecursionResourceLockModifier object. 31 | /// 32 | /// A reference to a ResourceLock object that will not support recursion. 33 | /// The maximum number of concurrent reader threads that this 34 | /// RecursionResourceLockModifier object should support. 35 | public RecursionResourceLockModifier(ResourceLock resLock, Int32 maxReaders) 36 | : base(resLock, ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.SupportsRecursion | 37 | (resLock.IsMutualExclusive ? ResourceLockOptions.IsMutualExclusive : 0)) { 38 | Contract.Requires(resLock != null); 39 | Contract.Requires(maxReaders >= 0); 40 | m_ReaderThreadIdsAndRecurseCounts = new ThreadIdAndRecurseCount[maxReaders]; 41 | } 42 | 43 | private Boolean TryFindThreadIdIndex(Int32 threadId, out Int32 index) { 44 | Contract.Assume(m_ReaderThreadIdsAndRecurseCounts != null); 45 | // The JITter produces more efficient code if we load the array reference into a temporary 46 | ThreadIdAndRecurseCount[] readerThreadIdsAndRecurseCounts = m_ReaderThreadIdsAndRecurseCounts; 47 | for (index = 0; index < readerThreadIdsAndRecurseCounts.Length; index++) { 48 | if (readerThreadIdsAndRecurseCounts[index].m_Id == threadId) 49 | return true; 50 | } 51 | return false; 52 | } 53 | 54 | private void AddThreadIdWithRecurseCountOf1(Int32 callingThreadId) { 55 | Contract.Assume(m_ReaderThreadIdsAndRecurseCounts != null); 56 | // The JITter produces more efficient code if we load the array reference into a temporary 57 | ThreadIdAndRecurseCount[] readerThreadIdsAndRecurseCounts = m_ReaderThreadIdsAndRecurseCounts; 58 | for (Int32 index = 0; index < readerThreadIdsAndRecurseCounts.Length; index++) { 59 | if (readerThreadIdsAndRecurseCounts[index].m_Id == 0) { 60 | if (InterlockedEx.IfThen(ref readerThreadIdsAndRecurseCounts[index].m_Id, 0, callingThreadId)) { 61 | readerThreadIdsAndRecurseCounts[index].m_Count = 1; 62 | return; 63 | } else { 64 | // We found a slot but then it was taken away from us 65 | index = -1; // Start the search over again from the beginning 66 | continue; 67 | } 68 | } 69 | } 70 | throw new InvalidOperationException("More current reader threads than allowed!"); 71 | } 72 | 73 | #region Override of ResourceLock Members 74 | /// Implements the ResourceLock's WaitToWrite behavior. 75 | protected override void OnEnter(Boolean exclusive) { 76 | Int32 CallingThreadId = Thread.CurrentThread.ManagedThreadId; 77 | if (exclusive) { 78 | // If the calling thread already owns the lock, add 1 to the recursion count and return 79 | if (CallingThreadId == m_WriterThreadIdAndRecurseCount.m_Id) { 80 | m_WriterThreadIdAndRecurseCount.m_Count++; 81 | return; 82 | } 83 | InnerLock.Enter(exclusive); 84 | Interlocked.Exchange(ref m_WriterThreadIdAndRecurseCount.m_Id, CallingThreadId); 85 | m_WriterThreadIdAndRecurseCount.m_Count = 0; 86 | } else { 87 | Int32 index; 88 | if (TryFindThreadIdIndex(CallingThreadId, out index)) { 89 | // This thread has the reader lock, increment the count and return 90 | m_ReaderThreadIdsAndRecurseCounts[index].m_Count++; 91 | return; 92 | } 93 | 94 | // This thread doesn't have the lock, wait for it 95 | InnerLock.Enter(exclusive); 96 | 97 | // Record that this thread has the reader lock once 98 | AddThreadIdWithRecurseCountOf1(CallingThreadId); 99 | } 100 | } 101 | 102 | /// Implements the ResourceLock's Leave behavior. 103 | protected override void OnLeave(Boolean exclusive) { 104 | Int32 CallingThreadId = Thread.CurrentThread.ManagedThreadId; 105 | if (exclusive) { 106 | if (m_WriterThreadIdAndRecurseCount.m_Id != CallingThreadId) 107 | throw new InvalidOperationException("Calling thread doesn't own this lock for writing!"); 108 | 109 | if (--m_WriterThreadIdAndRecurseCount.m_Count > 0) return; 110 | 111 | Interlocked.Exchange(ref m_WriterThreadIdAndRecurseCount.m_Id, 0); 112 | InnerLock.Leave(); 113 | } else { 114 | Int32 index; 115 | if (!TryFindThreadIdIndex(CallingThreadId, out index)) { 116 | throw new InvalidOperationException("Calling thread doesn't own the lock for reading!"); 117 | } 118 | // Decrement this readers recursion count 119 | if (--m_ReaderThreadIdsAndRecurseCounts[index].m_Count == 0) { 120 | // If this reader is done (recursion count == 0), remove this reader off the list 121 | Interlocked.Exchange(ref m_ReaderThreadIdsAndRecurseCounts[index].m_Id, 0); 122 | 123 | // This reader gives up the lock too 124 | InnerLock.Leave(); 125 | } 126 | } 127 | } 128 | #endregion 129 | } 130 | } 131 | 132 | //////////////////////////////// End of File ////////////////////////////////// 133 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/ResourceLockDelegator.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ResourceLockDelegator.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Text; 8 | using System.Threading; 9 | using System.Collections.Generic; 10 | using System.Reflection; 11 | using System.Diagnostics; 12 | using System.Diagnostics.Contracts; 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | 16 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 17 | /// 18 | /// An abstract class that delegates a lot of ResourceLock behavior to an inner ResourceLock. 19 | /// 20 | public abstract class ResourceLockDelegator : ResourceLock { 21 | private readonly ResourceLock m_resLock; 22 | 23 | /// Constructs a ResourceLockDelegator over the specified ResourceLock. 24 | /// The inner ResourceLock. 25 | [ContractVerification(false)] 26 | protected ResourceLockDelegator(ResourceLock resLock) 27 | : this(resLock, resLock.ResourceLockOptions) { 28 | Contract.Requires(resLock != null); 29 | Contract.Ensures(InnerLock != null); 30 | Contract.Assert(m_resLock != null); 31 | } 32 | 33 | /// Constructs a ResourceLockDelegator over the specified ResourceLock. 34 | /// The inner ResourceLock. 35 | /// Indicates the flags to use with this specified lock. 36 | [ContractVerification(false)] 37 | protected ResourceLockDelegator(ResourceLock resLock, ResourceLockOptions resourceLockOptions) 38 | : base(resourceLockOptions) { 39 | Contract.Requires(resLock != null); 40 | Contract.Ensures(InnerLock != null); 41 | m_resLock = resLock; 42 | #if DEADLOCK_DETECTION 43 | m_resLock.ImmuneFromDeadlockDetection = true; // The outerlock is used for deadlock detection; not the inner lock 44 | #endif 45 | Contract.Assert(m_resLock != null); 46 | } 47 | 48 | /// Determines whether the specified Object is equal to the current Object. 49 | /// The Object to compare with the current Object. 50 | /// true if the specified Object is equal to the current Object; otherwise, false. 51 | public override Boolean Equals(Object obj) { 52 | return (Object.Equals(m_resLock, ((ResourceLockObserver)obj).m_resLock) && base.Equals(obj)); 53 | } 54 | 55 | /// Serves as a hash function for a particular type. 56 | /// A hash code for the current Object. 57 | public override Int32 GetHashCode() { return m_resLock.GetHashCode(); } 58 | 59 | /// Returns a reference to the inner ResourceLock object. 60 | protected ResourceLock InnerLock { get { return m_resLock; } } 61 | 62 | #if false 63 | [ContractInvariantMethod] 64 | private void ObjectInvariant() { 65 | Contract.Invariant(InnerLock != null); 66 | } 67 | #endif 68 | 69 | /// Allows the object to clean itself up. 70 | /// true if Dispose is being called; false if the object is being finalized. 71 | protected override void Dispose(Boolean disposing) { 72 | try { 73 | if (disposing) m_resLock.Dispose(); 74 | } 75 | finally { 76 | base.Dispose(disposing); 77 | } 78 | } 79 | 80 | /// Implements the ResourceLock's Enter behavior. 81 | protected override void OnEnter(Boolean exclusive) { 82 | m_resLock.Enter(exclusive); 83 | } 84 | 85 | /// Implements the ResourceLock's Leave behavior. 86 | protected override void OnLeave(Boolean exclusive) { 87 | m_resLock.Leave(); 88 | } 89 | } 90 | } 91 | 92 | 93 | /////////////////////////////////////////////////////////////////////////////// 94 | 95 | 96 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 97 | /// 98 | /// An abstract class that all ResourceLockObserver classes derive from. 99 | /// 100 | public abstract class ResourceLockObserver : ResourceLockDelegator { 101 | /// 102 | /// Constructs a ResourceLockObserver. 103 | /// 104 | /// 105 | protected ResourceLockObserver(ResourceLock resLock) 106 | : base(resLock) { 107 | Contract.Requires(resLock != null); 108 | } 109 | } 110 | } 111 | 112 | 113 | /////////////////////////////////////////////////////////////////////////////// 114 | 115 | 116 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 117 | /// An abstract class that all ResourceLockModifier classes derive from. 118 | public abstract class ResourceLockModifier : ResourceLockDelegator { 119 | /// Constructs a ResourceLockModifier object. 120 | /// Identifies the inner ResourceLock object. 121 | /// Identifies the flags associted with the innter ResourceLock object. 122 | protected ResourceLockModifier(ResourceLock resLock, ResourceLockOptions resourceLockOptions) 123 | : base(resLock, resourceLockOptions) { 124 | Contract.Requires(resLock != null); 125 | } 126 | } 127 | } 128 | 129 | 130 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/StatisticsGatheringResourceLockObserver.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: StatisticsGatheringResourceLockObserver.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Text; 9 | using System.Threading; 10 | using System.Collections.Generic; 11 | using System.Reflection; 12 | using System.Diagnostics; 13 | using System.Diagnostics.Contracts; 14 | 15 | 16 | /////////////////////////////////////////////////////////////////////////////// 17 | 18 | 19 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 20 | ///A compositional resource lock providing statics for another lock. 21 | public sealed class StatisticsGatheringResourceLockObserver : ResourceLockObserver { 22 | 23 | [AttributeUsage(AttributeTargets.Property)] 24 | private sealed class StatisticPropertyAttribute : Attribute { } 25 | 26 | private static List InitializeProperties() { 27 | List props = new List(); 28 | foreach (PropertyInfo pi in typeof(StatisticsGatheringResourceLockObserver).GetProperties()) { 29 | if (Attribute.IsDefined(pi, typeof(StatisticPropertyAttribute))) 30 | props.Add(pi); 31 | } 32 | return props; 33 | } 34 | private static List s_statisticProperties = InitializeProperties(); 35 | 36 | private Int64 m_ReadRequests = 0, m_WriteRequests = 0; 37 | 38 | ///Returns the number of read requests against a lock. 39 | ///The number of read requests. 40 | [StatisticProperty] 41 | public Int64 ReadRequests { get { return m_ReadRequests; } } 42 | 43 | ///Returns the number of write requests against a lock. 44 | ///The number of write requests. 45 | [StatisticProperty] 46 | public Int64 WriteRequests { get { return m_WriteRequests; } } 47 | 48 | private Int64 m_ReadersReading = 0, m_WritersWriting = 0; 49 | 50 | ///Returns the current number of readers reading. 51 | ///The current number of reads. 52 | [StatisticProperty] 53 | public Int64 ReadersReading { get { return m_ReadersReading; } } 54 | 55 | ///Returns the current number of writers writing. 56 | ///The current number of writers. 57 | [StatisticProperty] 58 | public Int64 WritersWriting { get { return m_WritersWriting; } } 59 | 60 | 61 | private Int64 m_ReadersDone = 0, m_WritersDone = 0; 62 | 63 | ///Returns the number of readers done reading. 64 | ///The number of done readers. 65 | [StatisticProperty] 66 | public Int64 ReadersDone { get { return m_ReadersDone; } } 67 | 68 | ///Returns the number of writers done writing. 69 | ///The number of done writers. 70 | [StatisticProperty] 71 | public Int64 WritersDone { get { return m_WritersDone; } } 72 | 73 | 74 | private Int64 m_ReadersWaiting = 0, m_WritersWaiting = 0; 75 | 76 | ///Returns the current number of readers waiting. 77 | ///The number of waiting readers. 78 | [StatisticProperty] 79 | public Int64 ReadersWaiting { get { return m_ReadersWaiting; } } 80 | 81 | ///Returns the current number of writers waiting. 82 | ///The number of waiting writers. 83 | [StatisticProperty] 84 | public Int64 WritersWaiting { get { return m_WritersWaiting; } } 85 | 86 | 87 | private Int64 m_ReaderMaxWaitTime = 0, m_WriterMaxWaitTime = 0; 88 | 89 | ///Returns the maximum time that a reader waited to acquire the lock. 90 | ///Maximum time a reader waited to acquire the lock. 91 | [StatisticProperty] 92 | public TimeSpan ReaderMaxWaitTime { get { return TimeSpan.FromMilliseconds(m_ReaderMaxWaitTime); } } 93 | 94 | ///Returns the maximum time that a writer waited to acquire the lock. 95 | ///Maximum time a writer waited to acquire the lock. 96 | [StatisticProperty] 97 | public TimeSpan WriterMaxWaitTime { get { return TimeSpan.FromMilliseconds(m_WriterMaxWaitTime); } } 98 | 99 | 100 | private Int64 m_ReaderMinHoldTime = Int64.MaxValue, m_ReaderMaxHoldTime = 0; 101 | private Dictionary m_ReaderStartHoldTime = new Dictionary(); 102 | 103 | ///Returns the minimum time that a reader held the lock. 104 | ///Minimum time a reader held the lock. 105 | [StatisticProperty] 106 | public TimeSpan ReaderMinHoldTime { get { return TimeSpan.FromMilliseconds(m_ReaderMinHoldTime); } } 107 | 108 | ///Returns the maximum time that a reader held the lock. 109 | ///Maximum time a reader held the lock. 110 | [StatisticProperty] 111 | public TimeSpan ReaderMaxHoldTime { get { return TimeSpan.FromMilliseconds(m_ReaderMaxHoldTime); } } 112 | 113 | 114 | private Int64 m_WriterMinHoldTime = Int64.MaxValue, m_WriterMaxHoldTime = 0; 115 | private Int64 m_WriterStartHoldTime; 116 | 117 | ///Returns the minimum time that a writer held the lock. 118 | ///Minimum time a writer held the lock. 119 | [StatisticProperty] 120 | public TimeSpan WriterMinHoldTime { get { return TimeSpan.FromMilliseconds(m_WriterMinHoldTime); } } 121 | 122 | ///Returns the maximum time that a writer held the lock. 123 | ///Maximum time a writer held the lock. 124 | [StatisticProperty] 125 | public TimeSpan WriterMaxHoldTime { get { return TimeSpan.FromMilliseconds(m_WriterMaxHoldTime); } } 126 | 127 | ///Initializes a new instance of the StatisticsGatheringResourceLock class that wraps another ResouceLock-derived type. 128 | ///The ResourceLock-derived type to wrap. 129 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 130 | public StatisticsGatheringResourceLockObserver(ResourceLock resLock) 131 | : base(resLock) { 132 | Contract.Requires(resLock != null); 133 | } 134 | 135 | ///Returns the object's string representation. 136 | ///If null or "extra" is allowed. 137 | ///Not used. 138 | ///A String containing the object's string representation. 139 | public override String ToString(String format, IFormatProvider formatProvider) { 140 | StringBuilder sb = new StringBuilder(base.ToString(format, formatProvider)); 141 | if (String.Compare(format, "extra", StringComparison.OrdinalIgnoreCase) == 0) { 142 | sb.AppendLine(); 143 | foreach (PropertyInfo pi in s_statisticProperties) { 144 | sb.AppendLine(" " + pi.Name + "=" + pi.GetValue(this, null)); 145 | } 146 | } 147 | return sb.ToString(); 148 | } 149 | 150 | ///Derived class overrides OnEnter to provide specific reader locking semantics. 151 | protected override void OnEnter(Boolean exclusive) { 152 | if (exclusive) { 153 | Interlocked.Increment(ref m_WriteRequests); 154 | Interlocked.Increment(ref m_WritersWaiting); 155 | Int64 startTime = Environment.TickCount; 156 | InnerLock.Enter(exclusive); 157 | 158 | // Only 1 thread is writing, so no thread safety is required here 159 | m_WriterMaxWaitTime = Math.Max(m_WriterMaxWaitTime, checked((Int64)(Environment.TickCount - startTime))); 160 | Interlocked.Decrement(ref m_WritersWaiting); 161 | Interlocked.Increment(ref m_WritersWriting); 162 | m_WriterStartHoldTime = Environment.TickCount; 163 | } else { 164 | Interlocked.Increment(ref m_ReadRequests); 165 | Interlocked.Increment(ref m_ReadersWaiting); 166 | Int64 startTime = Environment.TickCount; 167 | InnerLock.Enter(exclusive); 168 | 169 | InterlockedEx.Max(ref m_ReaderMaxWaitTime, checked((Int64)(Environment.TickCount - startTime))); 170 | Interlocked.Decrement(ref m_ReadersWaiting); 171 | Interlocked.Increment(ref m_ReadersReading); 172 | Monitor.Enter(m_ReaderStartHoldTime); 173 | m_ReaderStartHoldTime.Add(Thread.CurrentThread.ManagedThreadId, Environment.TickCount); 174 | Monitor.Exit(m_ReaderStartHoldTime); 175 | } 176 | } 177 | 178 | ///Derived class overrides OnDoneReading to provide specific reader unlocking semantics. 179 | ///You do not need to override this method if the specific lock provides mutual-exclusive locking semantics. 180 | protected override void OnLeave(Boolean write) { 181 | if (write) { 182 | // Only 1 thread is writing, so no thread safety is required here 183 | Int64 HoldTime = checked((Int64)(Environment.TickCount - m_WriterStartHoldTime)); 184 | m_WriterMinHoldTime = Math.Min(m_WriterMinHoldTime, HoldTime); 185 | m_WriterMaxHoldTime = Math.Max(m_WriterMaxHoldTime, HoldTime); 186 | m_WritersWriting--; 187 | m_WritersDone++; 188 | InnerLock.Leave(); 189 | } else { 190 | Int32 threadId = Thread.CurrentThread.ManagedThreadId; 191 | Int64 HoldTime = checked((Int64)(Environment.TickCount - m_ReaderStartHoldTime[threadId])); 192 | Monitor.Enter(m_ReaderStartHoldTime); 193 | m_ReaderStartHoldTime.Remove(threadId); 194 | Monitor.Exit(m_ReaderStartHoldTime); 195 | 196 | InterlockedEx.Min(ref m_ReaderMinHoldTime, HoldTime); 197 | InterlockedEx.Max(ref m_ReaderMaxHoldTime, HoldTime); 198 | Interlocked.Decrement(ref m_ReadersReading); 199 | Interlocked.Increment(ref m_ReadersDone); 200 | 201 | InnerLock.Leave(); 202 | } 203 | } 204 | } 205 | } 206 | 207 | 208 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/ThreadSafeCheckerResourceLockObserver.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ThreadSafeCheckerResourceLockObserver.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Diagnostics.Contracts; 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 14 | /// 15 | /// This class performs various sanity checks on a ResourceLock-derived type 16 | /// making sure that the lock is performing correctly 17 | /// 18 | public sealed class ThreadSafeCheckerResourceLockObserver : ResourceLockObserver { 19 | /// Constructs a ThreadSafeCheckerResourceLockObserver wrapping the desired ResourceLock. 20 | /// 21 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 22 | public ThreadSafeCheckerResourceLockObserver(ResourceLock resLock) 23 | : base(resLock) { 24 | Contract.Requires(resLock != null); 25 | } 26 | 27 | // The high bit is on if a writer is writing, the low 31 bits are for # of readers 28 | private Int32 m_LockState = 0; 29 | 30 | /// Performs any desired cleanup for this object. 31 | /// true if Dispose is being called; false if the object is being finalized. 32 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoWriters(System.String)"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoReaders(System.String)")] 33 | protected override void Dispose(Boolean disposing) { 34 | try { 35 | // When being finalized or disposed, the lock should be free 36 | VerifyNoReaders("Lock held by readers while being disposed"); 37 | VerifyNoWriters("Lock held by a writer while being disposed"); 38 | } 39 | finally { 40 | base.Dispose(disposing); 41 | } 42 | } 43 | 44 | ///Allows the calling thread to acquire the lock for reading. 45 | ///A object that can be used to release the reader lock. 46 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoReaders(System.String)"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoWriters(System.String)")] 47 | protected override void OnEnter(Boolean exclusive) { 48 | if (exclusive) { 49 | InnerLock.Enter(exclusive); 50 | VerifyNoWriters("Writing while already writing!"); 51 | VerifyNoReaders("Writing while already reading!"); 52 | InterlockedEx.BitTestAndSet(ref m_LockState, 31); // Add the writer 53 | } else { 54 | InnerLock.Enter(exclusive); 55 | VerifyNoWriters("Reading while already writing!"); // Sanity check for no writers 56 | Interlocked.Increment(ref m_LockState); // Add a reader 57 | } 58 | } 59 | 60 | ///Allows the calling thread to release the reader lock. 61 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifySomeReaders(System.String)"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyOneWriter(System.String)"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoWriters(System.String)"), System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Globalization", "CA1303:Do not pass literals as localized parameters", MessageId = "Wintellect.Threading.ResourceLocks.Diagnostics.ThreadSafeCheckerResourceLockObserver.VerifyNoReaders(System.String)")] 62 | protected override void OnLeave(Boolean write) { 63 | if (write) { 64 | VerifyOneWriter("Done writing while not writing!"); 65 | VerifyNoReaders("Done writing while already reading!"); 66 | InterlockedEx.BitTestAndReset(ref m_LockState, 31); // Remove the writer 67 | } else { 68 | VerifySomeReaders("Done reading while not reading!"); 69 | VerifyNoWriters("Done reading while already writing!"); 70 | Interlocked.Decrement(ref m_LockState); // Subtract a reader 71 | } 72 | InnerLock.Leave(); 73 | } 74 | 75 | #region Verify Routines 76 | private void VerifyNoWriters(String message) { 77 | // There should be no writers 78 | if ((m_LockState & 0x80000000) != 0) 79 | ThrowException(message); 80 | } 81 | private void VerifyOneWriter(String message) { 82 | // There should be one writer 83 | if ((m_LockState & 0x80000000) == 0) 84 | ThrowException(message); 85 | } 86 | 87 | private void VerifyNoReaders(String message) { 88 | // There should be no readers 89 | if ((m_LockState & 0x7FFFFFFF) != 0) 90 | ThrowException(message); 91 | } 92 | 93 | private void VerifySomeReaders(String message) { 94 | // There should be some readers 95 | if ((m_LockState & 0x7FFFFFFF) == 0) 96 | ThrowException(message); 97 | } 98 | 99 | private static void ThrowException(String message) { 100 | throw new InvalidOperationException(message); 101 | } 102 | #endregion 103 | } 104 | } 105 | 106 | 107 | //////////////////////////////// End of File ////////////////////////////////// 108 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Diagnostics/TimeoutNotifierResourceLockObserver.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: TimeoutNotifierResourceLockObserver.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.Diagnostics; 9 | using System.Diagnostics.Contracts; 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | namespace Wintellect.Threading.ResourceLocks.Diagnostics { 14 | /// 15 | /// A ResourceLock-wrapper class that throws an exception if a thread waits 16 | /// too long on the inner lock. 17 | /// 18 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", MessageId = "Notifier")] 19 | public class TimeoutNotifierResourceLockObserver : ResourceLockObserver { 20 | private Int64 m_timeout; 21 | 22 | /// Constructs a TimeoutNotifierResourceLockObserver object. 23 | /// Indicates the inner ResourceLock. 24 | /// Indicates how long any thread should wait on the inner lock before throwing an exception. This value is in milliseconds. 25 | public TimeoutNotifierResourceLockObserver(ResourceLock resLock, Int64 timeout) 26 | : base(resLock) { 27 | Contract.Requires(resLock != null); 28 | m_timeout = timeout; 29 | } 30 | 31 | /// Constructs a TimeoutNotifierResourceLockObserver object. 32 | /// Indicates the inner ResourceLock. 33 | /// Indicates how long any thread should wait on the inner lock before throwing an exception. 34 | public TimeoutNotifierResourceLockObserver(ResourceLock resLock, TimeSpan timeout) 35 | : this(resLock, (Int64) timeout.TotalMilliseconds) { 36 | Contract.Requires(resLock != null); 37 | } 38 | 39 | /// This method is invoked when a thread has waited too long on a ResourceLock. The default behavior, throws a TimeoutException. 40 | /// The stack trace at the point where the thread waited on the ResourceLock. 41 | protected virtual void OnTimeout(StackTrace stackTrace) { 42 | Contract.Requires(stackTrace != null); 43 | String message = "Timed out while waiting for lock. Stack trace of waiting thread follows:" + 44 | Environment.NewLine + stackTrace.ToString(); 45 | throw new TimeoutException(message); 46 | } 47 | 48 | private void OnTimeout(Object stackTrace) { 49 | Contract.Requires(stackTrace != null); 50 | OnTimeout((StackTrace)stackTrace); 51 | } 52 | 53 | /// Implements the ResourceLock's Enter behavior. 54 | protected override void OnEnter(Boolean exclusive) { 55 | StackTrace st = new System.Diagnostics.StackTrace(0, true); 56 | using (new Timer(OnTimeout, st, m_timeout, -1)) { 57 | if (exclusive) InnerLock.Enter(exclusive); 58 | } 59 | } 60 | 61 | /// Implements the ResourceLock's Leave behavior. 62 | protected override void OnLeave(Boolean exclusive) { 63 | InnerLock.Leave(); 64 | } 65 | } 66 | } 67 | 68 | 69 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/ExclusiveSpinResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ExclusiveSpinResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.ResourceLocks { 15 | /// 16 | /// An exclusive lock that always spins in user-mode. 17 | /// 18 | public sealed class ExclusiveSpinResourceLock : ResourceLock { 19 | private SpinWaitLock m_lock = new SpinWaitLock(); 20 | 21 | /// 22 | /// Constructs an ExclusiveSpinResourceLock. 23 | /// 24 | public ExclusiveSpinResourceLock() : base(ResourceLockOptions.IsMutualExclusive) { } 25 | 26 | /// 27 | /// Implements the ResourceLock's WaitToWrite behavior. 28 | /// 29 | protected override void OnEnter(Boolean exclusive) { 30 | m_lock.Enter(); 31 | } 32 | 33 | /// 34 | /// Implements the ResourceLock's DoneWriting behavior. 35 | /// 36 | protected override void OnLeave(Boolean write) { 37 | m_lock.Exit(); 38 | } 39 | } 40 | } 41 | 42 | 43 | namespace Wintellect.Threading.ResourceLocks { 44 | // NOTE: This is a value type so it works very efficiently when used 45 | // as a field in a class. Avoid boxing this or you will lose thread safety! 46 | internal struct SpinWaitLock { 47 | private const Int32 c_lsFree = 0; 48 | private const Int32 c_lsOwned = 1; 49 | private volatile Int32 m_lockState; // Defaults to 0=c_lsFree 50 | 51 | public void Enter() { 52 | while (true) { 53 | #pragma warning disable 420 // 'identifier': a reference to a volatile field will not be treated as volatile 54 | // If resource available, set it to in-use and return 55 | if (Interlocked.Exchange(ref m_lockState, c_lsOwned) == c_lsFree) { 56 | return; 57 | } 58 | #pragma warning restore 420 59 | 60 | // Efficiently spin, until the resource looks like it might be free 61 | // NOTE: m_LockState is volatile which is faster than Thread.VolatileRead 62 | while (m_lockState == c_lsOwned) ThreadUtility.StallThread(); 63 | } 64 | } 65 | 66 | public void Exit() { 67 | // Mark the resource as available 68 | m_lockState = c_lsFree; // Note: m_lockState is volatile 69 | } 70 | } 71 | } 72 | 73 | 74 | //////////////////////////////// End of File //////////////////////////////////} 75 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/MonitorResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: MonitorResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.ResourceLocks { 15 | /// 16 | /// A ResourceLock implemented using System.Threading.Monitor 17 | /// 18 | public sealed class MonitorResourceLock : ResourceLock { 19 | private readonly Object m_lock; 20 | 21 | /// 22 | /// Constructs an instance on the MonitorResourceLock. 23 | /// 24 | public MonitorResourceLock() 25 | : base(ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.IsMutualExclusive | ResourceLockOptions.SupportsRecursion) { m_lock = this; } 26 | 27 | /// 28 | /// Constructs an instance of the MonitorResourceLock using the specified object as the lock itself. 29 | /// 30 | /// 31 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1720:IdentifiersShouldNotContainTypeNames", MessageId = "obj")] 32 | public MonitorResourceLock(Object obj) 33 | : base(ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.IsMutualExclusive | ResourceLockOptions.SupportsRecursion) { m_lock = obj; } 34 | 35 | /// 36 | /// Implements the ResourceLock's WaitToWrite behavior. 37 | /// 38 | protected override void OnEnter(Boolean exclusive) { 39 | Monitor.Enter(m_lock); 40 | } 41 | 42 | /// 43 | /// Implements the ResourceLock's DoneWriting behavior. 44 | /// 45 | protected override void OnLeave(Boolean exclusive) { 46 | Monitor.Exit(m_lock); 47 | } 48 | } 49 | } 50 | 51 | 52 | //////////////////////////////// End of File //////////////////////////////////} 53 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/MutexResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: MutexResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.ResourceLocks { 15 | /// 16 | /// This class implements a ResourceLock by way of a Windows Mutex. 17 | /// 18 | public sealed class MutexResourceLock : ResourceLock { 19 | private readonly Mutex m_lockObj; 20 | 21 | /// 22 | /// Constructs a MutexResourceLock. 23 | /// 24 | public MutexResourceLock() : this(false) { } 25 | 26 | /// 27 | /// Constructs a MutexResourceLock. 28 | /// 29 | /// true if the calling thread should own the mutex; false if the mutex should be unowned. 30 | public MutexResourceLock(Boolean initiallyOwned) 31 | : base(ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.IsMutualExclusive | ResourceLockOptions.SupportsRecursion) { 32 | m_lockObj = new Mutex(initiallyOwned); 33 | } 34 | 35 | /// 36 | /// Implements the ResourceLock's WaitToWrite behavior. 37 | /// 38 | protected override void OnEnter(Boolean exclusive) { 39 | m_lockObj.WaitOne(); 40 | } 41 | 42 | /// 43 | /// Implements the ResourceLock's DoneWriting behavior. 44 | /// 45 | protected override void OnLeave(Boolean write) { 46 | m_lockObj.ReleaseMutex(); 47 | } 48 | } 49 | } 50 | 51 | 52 | //////////////////////////////// End of File //////////////////////////////////} 53 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/NullResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: NullResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.ResourceLocks { 15 | /// 16 | /// A ResourceLock that actually performs no locking at all. 17 | /// 18 | public sealed class NullResourceLock : ResourceLock { 19 | /// 20 | /// Constructs an instance of the NullResourceLock. 21 | /// 22 | public NullResourceLock() : base( 23 | #if DEADLOCK_DETECTION 24 | ResourceLockOptions.ImmuneFromDeadlockDetection | 25 | #endif 26 | ResourceLockOptions.SupportsRecursion) { } 27 | 28 | /// 29 | /// Implements the ResourceLock's WaitToWrite behavior. 30 | /// 31 | protected override void OnEnter(Boolean exclusive) { } 32 | 33 | /// 34 | /// Implements the ResourceLock's DoneWriting behavior. 35 | /// 36 | protected override void OnLeave(Boolean exclusive) { } 37 | } 38 | } 39 | 40 | 41 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/OneManySpinResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: OneManySpinResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | 14 | namespace Wintellect.Threading.ResourceLocks { 15 | /// 16 | /// A reader/writer lock that always spins in user-mode. 17 | /// 18 | public sealed class OneManySpinResourceLock : ResourceLock { 19 | private const Int32 c_lsFree = 0x00000000; 20 | private const Int32 c_lsOwnedByWriter = 0x00000001; 21 | 22 | private const Int32 c_1WritersPending = 0x00000100; 23 | private const Int32 c_WritersPendingMask = 0x0000FF00; 24 | 25 | private const Int32 c_1ReadersReading = 0x00010000; 26 | private const Int32 c_ReadersReadingMask = 0x00FF0000; 27 | 28 | // Here's how to interpret the m_LockState field's 4 bytes: nu RR WP WW 29 | // nu = not used, RR=ReadersReading, WP=WritersPending, WW=Writer is writing 30 | private Int32 m_LockState = c_lsFree; 31 | 32 | /// 33 | /// Constucts a OneManySpinResourceLock object. 34 | /// 35 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 36 | public OneManySpinResourceLock() : base(ResourceLockOptions.None) { } 37 | 38 | /// 39 | /// Implements the ResourceLock's WaitToWrite behavior. 40 | /// 41 | protected override void OnEnter(Boolean exclusive) { 42 | if (exclusive) { 43 | // Indicate that a writer wants to write: WP++ 44 | Interlocked.Add(ref m_LockState, c_1WritersPending); 45 | StressPause(); 46 | 47 | // OK to write if no readers are reading and 48 | // no writers are pending: RR=0, WP=don't care, WW=0 49 | // Set the Writer is writing bit on. 50 | InterlockedEx.MaskedOr(ref m_LockState, c_lsOwnedByWriter, c_WritersPendingMask); 51 | } else { 52 | // OK to read if no writers are waiting: RR=don't care, WP=0, WW=0 53 | // If we're good, add 1 to the RR 54 | InterlockedEx.MaskedAdd(ref m_LockState, c_1ReadersReading, c_ReadersReadingMask); 55 | } 56 | StressPause(); 57 | } 58 | 59 | /// 60 | /// Implements the ResourceLock's DoneWriting behavior. 61 | /// 62 | protected override void OnLeave(Boolean write) { 63 | if (write) { 64 | // Subtract 1 from waiting pending & turn off the writer is writing bit. 65 | StressPause(); 66 | Interlocked.Add(ref m_LockState, -c_1WritersPending - c_lsOwnedByWriter); 67 | } else { 68 | // Subtract 1 from the RR 69 | Interlocked.Add(ref m_LockState, -c_1ReadersReading); 70 | } 71 | StressPause(); 72 | } 73 | } 74 | } 75 | 76 | 77 | //////////////////////////////// End of File //////////////////////////////////} 78 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/OneResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: OneResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | //#define Stress 8 | using System; 9 | using System.Diagnostics; 10 | using System.Threading; 11 | using System.Globalization; 12 | 13 | 14 | /////////////////////////////////////////////////////////////////////////////// 15 | 16 | 17 | namespace Wintellect.Threading.ResourceLocks { 18 | /// 19 | /// Implements a ResourceLock via a high-speed mutual-exclusive lock. 20 | /// 21 | public sealed class OneResourceLock : ResourceLock { 22 | // m_LockState's 4 bytes are interpreted like this: 00 00 WW ls 23 | #region Lock State Management 24 | private enum OneLockStates { 25 | Free = 0x00000000, 26 | OwnedByWriter = 0x00000001 27 | } 28 | private const Int32 c_lsStateMask = 0x000000ff; 29 | private const Int32 c_lsWritersWaitingMask = 0x0000ff00; 30 | private const Int32 c_ls1WriterWaiting = 0x00000100; 31 | private static OneLockStates State(Int32 ls) { 32 | return (OneLockStates)(ls & c_lsStateMask); 33 | } 34 | private static void State(ref Int32 ls, OneLockStates newState) { 35 | ls = (ls & ~c_lsStateMask) | ((Int32)newState); 36 | } 37 | 38 | private static Int32 NumWritersWaiting(Int32 ls) { return (ls & c_lsWritersWaitingMask) >> 8; } 39 | private static void IncWritersWaiting(ref Int32 ls) { ls += c_ls1WriterWaiting; } 40 | private static void DecWritersWaiting(ref Int32 ls) { ls -= c_ls1WriterWaiting; } 41 | 42 | private enum WakeUp { None, Writer } 43 | private Int32 NumWritersToWake() { 44 | Int32 ls = m_LockState; 45 | 46 | // If lock is Free && WW>0, try to subtract 1 writer 47 | while ((State(ls) == OneLockStates.Free) && (NumWritersWaiting(ls) > 0)) { 48 | Int32 desired = ls; 49 | DecWritersWaiting(ref desired); 50 | if (InterlockedEx.IfThen(ref m_LockState, ls, desired, out ls)) { 51 | // We sucessfully subtracted 1 waiting writer, wake it up 52 | return 1; 53 | } 54 | } 55 | return 0; 56 | } 57 | 58 | /// 59 | /// Returns a string representing the state of the object. 60 | /// 61 | /// The string representing the state of the object. 62 | public override string ToString() { 63 | Int32 ls = m_LockState; 64 | return String.Format(CultureInfo.InvariantCulture, 65 | "State={0}, WW={1}", State(ls), NumWritersWaiting(ls)); 66 | } 67 | #endregion 68 | 69 | #region State Fields 70 | private Int32 m_LockState = (Int32)OneLockStates.Free; 71 | 72 | // Writers wait on this if another writer owns the lock 73 | private Semaphore m_WritersLock = new Semaphore(0, Int32.MaxValue); 74 | #endregion 75 | 76 | #region Construction and Dispose 77 | /// 78 | /// Constructs a OneResourceLock object. 79 | /// 80 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 81 | public OneResourceLock() : base(ResourceLockOptions.IsMutualExclusive) { } 82 | 83 | /// 84 | /// Allow the object to clean itself up. 85 | /// 86 | /// true if the object is being disposed; false if it is being finalzied. 87 | protected override void Dispose(Boolean disposing) { 88 | try { 89 | if (disposing) { 90 | m_WritersLock.Close(); m_WritersLock = null; 91 | } 92 | } 93 | finally { 94 | base.Dispose(disposing); 95 | } 96 | } 97 | #endregion 98 | 99 | #region Writer members 100 | /// 101 | /// Implements the ResourceLock's WaitToWrite behavior. 102 | /// 103 | protected override void OnEnter(Boolean exclusive) { 104 | while (WaitToWrite(ref m_LockState)) m_WritersLock.WaitOne(); 105 | } 106 | 107 | private static Boolean WaitToWrite(ref Int32 target) { 108 | Int32 i, j = target; 109 | Boolean wait; 110 | do { 111 | i = j; 112 | Int32 desired = i; 113 | wait = false; 114 | 115 | switch (State(desired)) { 116 | case OneLockStates.Free: // If Free->OBW, return 117 | State(ref desired, OneLockStates.OwnedByWriter); 118 | break; 119 | 120 | case OneLockStates.OwnedByWriter: // If OBW -> WW++, wait & loop around 121 | IncWritersWaiting(ref desired); 122 | wait = true; 123 | break; 124 | 125 | default: 126 | Debug.Assert(false, "Invalid Lock state"); 127 | break; 128 | } 129 | j = Interlocked.CompareExchange(ref target, desired, i); 130 | } while (i != j); 131 | return wait; 132 | } 133 | 134 | /// 135 | /// Implements the ResourceLock's DoneWriting behavior. 136 | /// 137 | protected override void OnLeave(Boolean write) { 138 | Debug.Assert(State(m_LockState) == OneLockStates.OwnedByWriter); 139 | // Pre-condition: Lock's state must be OBW (not Free) 140 | // Post-condition: Lock's state must become Free (the lock is never passed) 141 | 142 | // Phase 1: Release the lock 143 | WakeUp wakeup = DoneWriting(ref m_LockState); 144 | 145 | // Phase 2: Possibly wake waiters 146 | switch (wakeup) { 147 | case WakeUp.None: 148 | break; 149 | case WakeUp.Writer: 150 | Int32 numWritersToWake = NumWritersToWake(); 151 | Debug.Assert(numWritersToWake < 2); // Must be 0 or 1 152 | if (numWritersToWake > 0) m_WritersLock.Release(numWritersToWake); 153 | break; 154 | } 155 | } 156 | 157 | private static WakeUp DoneWriting(ref Int32 target) { 158 | Int32 i, j = target; 159 | WakeUp wakeup = WakeUp.None; 160 | do { 161 | i = j; 162 | Int32 desired = i; 163 | 164 | // The lock should become free 165 | State(ref desired, OneLockStates.Free); 166 | 167 | // Possible wake a waiting writer 168 | wakeup = (NumWritersWaiting(desired) > 0) ? WakeUp.Writer : WakeUp.None; 169 | j = Interlocked.CompareExchange(ref target, desired, i); 170 | } while (i != j); 171 | return wakeup; 172 | } 173 | #endregion 174 | } 175 | } 176 | 177 | 178 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/OptexResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: OptexResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Diagnostics; 9 | using System.Threading; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect.Threading.ResourceLocks { 16 | /// 17 | /// A fast mutual-exclusive lock 18 | /// 19 | public class OptexResourceLock : ResourceLock { 20 | /// 21 | /// Constructs an OptexResourceLock. 22 | /// 23 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 24 | public OptexResourceLock() : base(ResourceLockOptions.IsMutualExclusive) { } 25 | 26 | // Bit 0: 0=Lock is free, 1=Lock is owned 27 | // Bits 1-31: Number of waiters 28 | private Int32 m_LockState = c_lsFree; 29 | 30 | private const Int32 c_lsFree = 0x00000000; 31 | private const Int32 c_lsOwned = 0x00000001; 32 | private const Int32 c_1Waiter = 0x00000002; 33 | 34 | private Semaphore m_WaiterLock = new Semaphore(0, Int32.MaxValue); 35 | 36 | /// 37 | /// Allows the object to clean itself up. 38 | /// 39 | /// true if the object is being disposed; false if being finalized. 40 | protected override void Dispose(Boolean disposing) { 41 | try { 42 | if (disposing) { m_WaiterLock.Close(); m_WaiterLock = null; } 43 | } 44 | finally { 45 | base.Dispose(disposing); 46 | } 47 | } 48 | 49 | /// 50 | /// Implements the ResourceLock's WaitToWrite behavior. 51 | /// 52 | protected override void OnEnter(Boolean exclusive) { 53 | while (true) { 54 | // Turn on the "owned" bit 55 | Int32 ls = InterlockedEx.Or(ref m_LockState, c_lsOwned); 56 | StressPause(); 57 | 58 | // If lock was free, this thread got it, return 59 | if ((ls & c_lsOwned) == c_lsFree) return; 60 | StressPause(); 61 | // Another thread owned the lock, add 1 waiter 62 | if (IfThen(ref m_LockState, ls, ls + c_1Waiter)) { 63 | // If successfully added 1, wait for lock 64 | m_WaiterLock.WaitOne(); 65 | StressPause(); 66 | } 67 | // We weren't able to add 1 waiter or waiter woke, attempt to get the lock 68 | StressPause(); 69 | } 70 | } 71 | 72 | /// 73 | /// Implements the ResourceLock's DoneWriting behavior. 74 | /// 75 | protected override void OnLeave(Boolean exclusive) { 76 | // Pre-condition: Lock's state must be Owned 77 | // Post-condition: Lock's state must become Free (the lock is never passed) 78 | 79 | // Phase 1: Free the lock 80 | Int32 ls = InterlockedEx.And(ref m_LockState, ~c_lsOwned); 81 | if (ls == c_lsOwned) { 82 | StressPause(); 83 | // If no waiters, nothing to do, we can just return 84 | } else { 85 | // Phase 2: Possibly wake waiters 86 | // If lock is free, try to subtract 1 from the number of waiters 87 | ls &= ~c_lsOwned; 88 | if (IfThen(ref m_LockState, ls, ls - c_1Waiter)) { 89 | StressPause(); 90 | // We sucessfully subtracted 1, wake 1 waiter 91 | m_WaiterLock.Release(1); 92 | StressPause(); 93 | } else { 94 | // Lock's state changed by other thread, other thread will deal with it 95 | StressPause(); 96 | } 97 | } 98 | } 99 | } 100 | } 101 | 102 | 103 | //////////////////////////////// End of File ////////////////////////////////// 104 | 105 | namespace Wintellect.Threading.ResourceLocks { 106 | /// 107 | /// Implements a recursive mutual-exclusive lock 108 | /// 109 | public sealed class RecursiveOptex : IDisposable { 110 | private static readonly Boolean s_uniProcessor = (Environment.ProcessorCount == 1); 111 | private Int32 m_spincount; 112 | private Int32 m_waiters = 0; 113 | private Int32 m_owningThreadId = 0; 114 | private Int32 m_recursionCount = 0; 115 | private AutoResetEvent m_waiterLock = new AutoResetEvent(false); 116 | 117 | /// 118 | /// Constructs a RecursiveOptex with the specified user-mode spin count 119 | /// 120 | /// The number of times the lock should spin in user-mode 121 | /// when there is contention on the lock before waiting in the kernel. 122 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1805:DoNotInitializeUnnecessarily")] 123 | public RecursiveOptex(Int32 spinCount) { 124 | m_spincount = s_uniProcessor ? 0 : spinCount; 125 | } 126 | 127 | /// 128 | /// Allows the object to clean itself up. 129 | /// 130 | public void Dispose() { 131 | m_waiterLock.Close(); m_waiterLock = null; 132 | } 133 | 134 | /// 135 | /// Causes the calling thread to enter the lock. 136 | /// 137 | public void Enter() { 138 | Int32 threadId = Thread.CurrentThread.ManagedThreadId; 139 | if (threadId == m_owningThreadId) { 140 | // This thread owns the lock and wants it again 141 | m_recursionCount++; 142 | return; 143 | } 144 | 145 | for (Int32 spinCount = 0; spinCount < m_spincount; spinCount++) { 146 | if (Interlocked.CompareExchange(ref m_waiters, 1, 0) == 0) 147 | goto GotLock; 148 | } 149 | 150 | // After spinning, try 1 more time to get the lock 151 | if (Interlocked.Increment(ref m_waiters) == 1) 152 | goto GotLock; 153 | 154 | // We still can't get the lock; wait for it 155 | m_waiterLock.WaitOne(); 156 | 157 | GotLock: 158 | // This thread got the lock 159 | m_owningThreadId = threadId; 160 | m_recursionCount = 1; 161 | } 162 | 163 | /// 164 | /// Causes the calling thread to release the lock. 165 | /// 166 | public void Exit() { 167 | Int32 threadId = Thread.CurrentThread.ManagedThreadId; 168 | if (threadId != m_owningThreadId) 169 | throw new SynchronizationLockException("Lock not owned by current thread"); 170 | 171 | // If this thread doesn't completely release it, just return 172 | if (--m_recursionCount > 0) return; 173 | 174 | m_owningThreadId = 0; // No thread owns it now 175 | 176 | if (Interlocked.Decrement(ref m_waiters) > 0) 177 | m_waiterLock.Set(); 178 | } 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/ReaderWriterResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: ReaderWriterResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | 9 | 10 | /////////////////////////////////////////////////////////////////////////////// 11 | 12 | 13 | namespace Wintellect.Threading.ResourceLocks { 14 | /// 15 | /// A reader/write lock implemented using the .NET Framework's own System.Threading.ReaderWriterLock 16 | /// 17 | public sealed class ReaderWriterResourceLock : ResourceLock { 18 | private readonly ReaderWriterLock m_lockObj = new ReaderWriterLock(); 19 | 20 | /// 21 | /// Constructs a ReaderWriterResourceLock object. 22 | /// 23 | public ReaderWriterResourceLock() : base(ResourceLockOptions.AcquiringThreadMustRelease | ResourceLockOptions.SupportsRecursion) { } 24 | 25 | /// 26 | /// Implements the ResourceLock's WaitToWrite behavior. 27 | /// 28 | protected override void OnEnter(Boolean exclusive) { 29 | if (exclusive) m_lockObj.AcquireWriterLock(-1); 30 | else m_lockObj.AcquireReaderLock(-1); 31 | } 32 | 33 | /// 34 | /// Implements the ResourceLock's DoneWriting behavior. 35 | /// 36 | protected override void OnLeave(Boolean exclusive) { 37 | if (exclusive) m_lockObj.ReleaseWriterLock(); 38 | else m_lockObj.ReleaseReaderLock(); 39 | } 40 | } 41 | } 42 | 43 | 44 | //////////////////////////////// End of File //////////////////////////////////} 45 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/ReaderWriterSlimResourceLock.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | /****************************************************************************** 3 | Module: ReaderWriterSlimResourceLock.cs 4 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 5 | ******************************************************************************/ 6 | 7 | 8 | using System; 9 | using System.Threading; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect.Threading.ResourceLocks { 16 | // This class is only available when running on .NET 3.5 or later 17 | /// 18 | /// A ResourceLock implemented using System.Threading.ReaderWriterLockSlim 19 | /// 20 | public sealed class ReaderWriterSlimResourceLock : ResourceLock { 21 | private readonly ReaderWriterLockSlim m_lock; 22 | 23 | /// 24 | /// Constructs an instance on the ReaderWriterSlimResourceLock. 25 | /// 26 | public ReaderWriterSlimResourceLock() 27 | : this(LockRecursionPolicy.NoRecursion) { 28 | } 29 | 30 | /// 31 | /// Constructs an instance on the ReaderWriterSlimResourceLock with the desired recursion policy. 32 | /// 33 | public ReaderWriterSlimResourceLock(LockRecursionPolicy recursionPolicy) 34 | : base(ResourceLockOptions.AcquiringThreadMustRelease | 35 | ((recursionPolicy == LockRecursionPolicy.SupportsRecursion) ? ResourceLockOptions.SupportsRecursion : 0)) { 36 | m_lock = new ReaderWriterLockSlim(recursionPolicy); 37 | } 38 | 39 | ///Derived class overrides OnEnter to provide specific lock-acquire semantics. 40 | protected override void OnEnter(Boolean exclusive) { 41 | if (exclusive) m_lock.EnterWriteLock(); 42 | else m_lock.EnterReadLock(); 43 | } 44 | 45 | ///Derived class overrides OnLeave to provide specific lock-release semantics. 46 | protected override void OnLeave(Boolean exclusive) { 47 | if (exclusive) m_lock.ExitWriteLock(); 48 | else m_lock.ExitReadLock(); 49 | } 50 | } 51 | } 52 | 53 | 54 | //////////////////////////////// End of File //////////////////////////////////} 55 | #endif -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/SemaphoreResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: SemaphoreResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Diagnostics; 10 | using Wintellect.Threading.ResourceLocks.Diagnostics; 11 | 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | namespace Wintellect.Threading.ResourceLocks { 17 | /// Implements a ResourceLock by way of a Windows Semaphore. 18 | public sealed class SemaphoreResourceLock : ResourceLock { 19 | private readonly Semaphore m_lockObj; 20 | 21 | /// Constructs a SemaphoreResourceLock. 22 | public SemaphoreResourceLock() 23 | : base(ResourceLockOptions.IsMutualExclusive) { 24 | m_lockObj = new Semaphore(1, 1); 25 | } 26 | 27 | /// 28 | /// Implements the ResourceLock's WaitToWrite behavior. 29 | /// 30 | protected override void OnEnter(Boolean exclusive) { 31 | m_lockObj.WaitOne(); 32 | } 33 | 34 | /// 35 | /// Implements the ResourceLock's DoneWriting behavior. 36 | /// 37 | protected override void OnLeave(Boolean exclusive) { 38 | m_lockObj.Release(); 39 | } 40 | } 41 | } 42 | 43 | 44 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/ResourceLocks/Win32SlimResourceLock.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Win32SlimResourceLock.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Runtime.InteropServices; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect.Threading.ResourceLocks { 16 | /// 17 | /// Implements a ResourceLock by way of the Windows SlimResourceLock. 18 | /// This class is only available when running on Windows Vista or later. 19 | /// 20 | public sealed class Win32SlimResourceLock : ResourceLock { 21 | [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Reliability", "CA2006:UseSafeHandleToEncapsulateNativeResources")] 22 | private IntPtr m_SRWLock; 23 | 24 | /// 25 | /// Constructs a Win32SlimResourceLock. 26 | /// 27 | public Win32SlimResourceLock() 28 | : base(ResourceLockOptions.AcquiringThreadMustRelease) { 29 | NativeMethods.InitializeSRWLock(out m_SRWLock); 30 | } 31 | 32 | /// 33 | /// Implements the ResourceLock's WaitToWrite behavior. 34 | /// 35 | protected override void OnEnter(Boolean exclusive) { 36 | if (exclusive) NativeMethods.AcquireSRWLockExclusive(ref m_SRWLock); 37 | else NativeMethods.AcquireSRWLockShared(ref m_SRWLock); 38 | } 39 | 40 | /// 41 | /// Implements the ResourceLock's DoneWriting behavior. 42 | /// 43 | protected override void OnLeave(Boolean exclusive) { 44 | if (exclusive) NativeMethods.ReleaseSRWLockExclusive(ref m_SRWLock); 45 | else NativeMethods.ReleaseSRWLockShared(ref m_SRWLock); 46 | } 47 | 48 | private static class NativeMethods { 49 | [DllImport("Kernel32", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] 50 | internal static extern void InitializeSRWLock(out IntPtr srw); 51 | 52 | [DllImport("Kernel32", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] 53 | internal static extern void AcquireSRWLockExclusive(ref IntPtr srw); 54 | 55 | [DllImport("Kernel32", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] 56 | internal static extern void AcquireSRWLockShared(ref IntPtr srw); 57 | 58 | [DllImport("Kernel32", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] 59 | internal static extern void ReleaseSRWLockExclusive(ref IntPtr srw); 60 | 61 | [DllImport("Kernel32", CallingConvention = CallingConvention.Winapi, ExactSpelling = true)] 62 | internal static extern void ReleaseSRWLockShared(ref IntPtr srw); 63 | } 64 | } 65 | } 66 | 67 | 68 | //////////////////////////////// End of File //////////////////////////////////} 69 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/SafeTokenHandle.cs: -------------------------------------------------------------------------------- 1 | #if false 2 | using System; 3 | using System.Security; 4 | using System.Runtime.InteropServices; 5 | using Microsoft.Win32.SafeHandles; 6 | using System.Runtime.ConstrainedExecution; 7 | 8 | namespace PrivilegeClass { 9 | internal sealed class SafeTokenHandle : SafeHandleZeroOrMinusOneIsInvalid { 10 | private SafeTokenHandle() : base(true) { } 11 | 12 | // 0 is an Invalid Handle 13 | internal SafeTokenHandle(IntPtr handle) : base(true) { 14 | SetHandle(handle); 15 | } 16 | 17 | internal static SafeTokenHandle InvalidHandle { 18 | get { return new SafeTokenHandle(IntPtr.Zero); } 19 | } 20 | 21 | [DllImport(NativeMethods.KERNEL32, SetLastError = true)] 22 | [SuppressUnmanagedCodeSecurity] 23 | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)] 24 | private static extern Boolean CloseHandle(IntPtr handle); 25 | 26 | protected override Boolean ReleaseHandle() { 27 | return CloseHandle(handle); 28 | } 29 | } 30 | } 31 | #endif -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect.Threading/SyncContextEventRaiser.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: SyncContextEventRaiser.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | using System; 7 | using System.Threading; 8 | using System.ComponentModel; 9 | using System.Diagnostics.CodeAnalysis; 10 | 11 | /////////////////////////////////////////////////////////////////////////////// 12 | 13 | #if true 14 | namespace Wintellect.Threading { 15 | /// 16 | /// This class raises an event using a specific SynchronizationContext object. 17 | /// 18 | public sealed class SyncContextEventRaiser { 19 | // This SynchronizationContext object will help us marshal events to the correct thread: 20 | // For Windows Forms app, it will marshal events to the GUI thread 21 | // For other apps, it will do the right thing (which may mean no marshalling at all) 22 | private SynchronizationContext m_syncContext; 23 | 24 | /// 25 | /// Constructs a SyncContextEventRaiser using the current thread's SynchronizationContext. 26 | /// 27 | public SyncContextEventRaiser() : this(null) { } 28 | 29 | /// 30 | /// Constructs a SyncContextEventRaiser using the specified SynchronizationContext. 31 | /// 32 | public SyncContextEventRaiser(SynchronizationContext syncContext) { 33 | m_syncContext = syncContext ?? AsyncOperationManager.SynchronizationContext; 34 | } 35 | 36 | /// Represents a callback to a protected virtual method that raises an event. 37 | /// The type identifying the type of object that gets raised with the event"/> 38 | /// The object that should be passed to a protected virtual method that raises the event. 39 | [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] 40 | public delegate void EventRaiser(T e) where T : EventArgs; 41 | 42 | /// A method that asynchronously raises an event on the application's desired thread. 43 | /// The type identifying the type of object that gets raised with the event"/> 44 | /// The protected virtual method that will raise the event. 45 | /// The object that should be passed to the protected virtual method raising the event. 46 | public void PostEvent(EventRaiser callback, T e) where T : EventArgs { 47 | m_syncContext.Post(delegate(Object state) { callback((T)state); }, e); 48 | } 49 | 50 | /// A method that synchronously raises an event on the application's desired thread. 51 | /// The type identifying the type of object that gets raised with the event"/> 52 | /// The protected virtual method that will raise the event. 53 | /// The object that should be passed to the protected virtual method raising the event. 54 | public void SendEvent(EventRaiser callback, T e) where T : EventArgs { 55 | m_syncContext.Send(delegate(Object state) { callback((T)state); }, e); 56 | } 57 | } 58 | } 59 | #endif 60 | 61 | //////////////////////////////// End of File ////////////////////////////////// 62 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/Contracts.cs: -------------------------------------------------------------------------------- 1 | #if !SILVERLIGHT && !PocketPC 2 | using System; 3 | using System.Collections.Generic; 4 | using System.Text; 5 | 6 | namespace System.Diagnostics.Contracts { 7 | [Conditional("CONTRACTS_FULL"), AttributeUsage(AttributeTargets.Property | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Struct | AttributeTargets.Class | AttributeTargets.Assembly)] 8 | internal sealed class ContractVerificationAttribute : Attribute { 9 | // Fields 10 | private bool _value; 11 | 12 | // Methods 13 | public ContractVerificationAttribute(bool value) { 14 | this._value = value; 15 | } 16 | 17 | // Properties 18 | public bool Value { 19 | get { 20 | return this._value; 21 | } 22 | } 23 | } 24 | 25 | [Conditional("CONTRACTS_FULL"), AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 26 | internal sealed class ContractInvariantMethodAttribute : Attribute { 27 | } 28 | 29 | 30 | internal static class Contract { 31 | [Conditional("DEBUG"), Conditional("CONTRACTS_FULL")] 32 | public static void Assert(bool condition) { } 33 | 34 | [Conditional("CONTRACTS_FULL"), Conditional("DEBUG")] 35 | public static void Assert(bool condition, string userMessage) { } 36 | 37 | [Conditional("CONTRACTS_FULL"), Conditional("DEBUG")] 38 | public static void Assume(bool condition) { 39 | Debug.Assert(condition); 40 | } 41 | 42 | [Conditional("CONTRACTS_FULL"), Conditional("DEBUG")] 43 | public static void Assume(bool condition, string userMessage) { 44 | Debug.Assert(condition); 45 | } 46 | 47 | [Conditional("CONTRACTS_FULL")] 48 | public static void EndContractBlock() { } 49 | 50 | [Conditional("CONTRACTS_FULL")] 51 | public static void Ensures(bool condition) { } 52 | 53 | [Conditional("CONTRACTS_FULL")] 54 | public static void Ensures(bool condition, string userMessage) { } 55 | 56 | [Conditional("CONTRACTS_FULL")] 57 | public static void EnsuresOnThrow(bool condition) where TException : Exception { } 58 | 59 | [Conditional("CONTRACTS_FULL")] 60 | public static void EnsuresOnThrow(bool condition, string userMessage) where TException : Exception { } 61 | 62 | public static bool Exists(IEnumerable collection, Predicate predicate) { return true; } 63 | 64 | public static bool Exists(int fromInclusive, int toExclusive, Predicate predicate) { return true; } 65 | 66 | public static bool ForAll(IEnumerable collection, Predicate predicate) { return true; } 67 | 68 | public static bool ForAll(int fromInclusive, int toExclusive, Predicate predicate) { return true; } 69 | 70 | [Conditional("CONTRACTS_FULL")] 71 | public static void Invariant(bool condition) { } 72 | 73 | [Conditional("CONTRACTS_FULL")] 74 | public static void Invariant(bool condition, string userMessage) {} 75 | 76 | public static T OldValue(T value) { return value; } 77 | 78 | [Conditional("CONTRACTS_FULL")] 79 | public static void Requires(bool condition) {} 80 | 81 | public static void Requires(bool condition) where TException : Exception {} 82 | 83 | [Conditional("CONTRACTS_FULL")] 84 | public static void Requires(bool condition, string userMessage) {} 85 | 86 | public static void Requires(bool condition, string userMessage) where TException : Exception {} 87 | 88 | public static T Result() { return default(T); } 89 | 90 | public static T ValueAtReturn(out T value) { value = default(T); return value; } 91 | } 92 | } 93 | #endif -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/Disposer.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Disposer.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Diagnostics.Contracts; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect { 16 | /// 17 | /// Puts an IDisposable wrapper around a callback method allowing any 18 | /// method to be used with the C# using statement. 19 | /// 20 | public sealed class Disposer : IDisposable { 21 | /// 22 | /// A delegate that matches the signature of IDisposable's Dispose method. 23 | /// 24 | private readonly ThreadStart m_disposeMethod = null; 25 | 26 | /// 27 | /// Constructs a Dispose object around the specified method. 28 | /// 29 | /// The method that should be called via Dispose. 30 | public Disposer(ThreadStart disposeMethod) { 31 | if (disposeMethod == null) throw new ArgumentNullException("disposeMethod"); 32 | m_disposeMethod = disposeMethod; 33 | } 34 | 35 | /// 36 | /// Invokes the desired method via this method. 37 | /// 38 | public void Dispose() { Contract.Assume(m_disposeMethod != null); m_disposeMethod(); } 39 | } 40 | } 41 | 42 | 43 | //////////////////////////////// End of File ////////////////////////////////// 44 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/Exception.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Exception.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | #if !PocketPC 9 | using System.Runtime.Serialization; 10 | #endif 11 | using System.Security; 12 | 13 | #if !v4 14 | using System.Security.Permissions; 15 | using System.Diagnostics.Contracts; 16 | #endif 17 | 18 | 19 | /////////////////////////////////////////////////////////////////////////////// 20 | 21 | 22 | #region Sample Exception Usage Code 23 | #if false 24 | internal static class SampleUsage { 25 | private sealed class Simple : ExceptionArgs { } 26 | 27 | private sealed class BadCustomer : ExceptionArgs { 28 | private String m_customerName; 29 | public BadCustomer(String customerName) { m_customerName = customerName; } 30 | public String CustomerName { get { return m_customerName; } } 31 | public override string Message { 32 | get { 33 | return base.Message + 34 | ((m_customerName == null) ? null : "Customer name=" + m_customerName); 35 | } 36 | } 37 | } 38 | 39 | private static void SampleThrow() { 40 | throw new Exception( 41 | new BadCustomer("Jeff"), "Customer not in database"); 42 | } 43 | 44 | internal static void SampleCatch() { 45 | try { 46 | SampleThrow(); 47 | } 48 | catch (Exception e) { 49 | Console.WriteLine(e.Args.CustomerName); 50 | } 51 | } 52 | } 53 | #endif 54 | #endregion 55 | 56 | 57 | /////////////////////////////////////////////////////////////////////////////// 58 | 59 | 60 | namespace Wintellect { 61 | /// 62 | /// A base class that a custom exception would derive from in order to add its own exception arguments. 63 | /// 64 | #if !SILVERLIGHT 65 | [Serializable] 66 | #endif 67 | public class ExceptionArgs { 68 | 69 | /// 70 | /// The string message associated with this exception. 71 | /// 72 | public virtual String Message { get { return null; } } 73 | } 74 | } 75 | 76 | 77 | /////////////////////////////////////////////////////////////////////////////// 78 | 79 | 80 | namespace Wintellect { 81 | /// 82 | /// Represents errors that occur during application execution. 83 | /// 84 | /// The type of exception and any additional arguments associated with it. 85 | #if !SILVERLIGHT && !PocketPC 86 | [Serializable] 87 | public sealed class Exception : Exception, ISerializable where T : ExceptionArgs { 88 | #else 89 | public sealed class Exception : Exception where T : ExceptionArgs { 90 | #endif 91 | // The three public constructors 92 | 93 | /// 94 | /// Initializes a new instance of the Exception class 95 | /// 96 | public Exception() : this(null) { } 97 | 98 | /// 99 | /// Initializes a new instance of the Exception class with a specified error message. 100 | /// 101 | /// The error message that explains the reason for the exception. 102 | public Exception(String message) 103 | : this(message, null) { 104 | } 105 | 106 | /// 107 | /// Initializes a new instance of the Exception class with a specified error message 108 | /// and a reference to the inner exception that is the cause of this exception. 109 | /// 110 | /// The error message that explains the reason for the exception. 111 | /// The exception that is the cause of the current exception, 112 | /// or a null reference if no inner exception is specified. 113 | public Exception(String message, Exception innerException) 114 | : this(null, message, innerException) { 115 | } 116 | 117 | private const String c_args = "Args"; 118 | private readonly T m_args; 119 | 120 | /// 121 | /// Returns a reference to this exception's additional arguments. 122 | /// 123 | public T Args { get { return m_args; } } 124 | 125 | // The fourth public constructor because there is a field 126 | /// 127 | /// Initializes a new instance of the Exception class with additional arguments, 128 | /// a specified error message, and a reference to the inner exception 129 | /// that is the cause of this exception. 130 | /// 131 | /// The exception's additional arguments. 132 | /// The error message that explains the reason for the exception. 133 | /// The exception that is the cause of the current exception, 134 | /// or a null reference if no inner exception is specified. 135 | public Exception(T args, String message, Exception innerException) 136 | : base(message, innerException) { 137 | m_args = args; 138 | } 139 | 140 | /// 141 | /// Initializes a new instance of the Exception class with additional arguments and 142 | /// a specified error message. 143 | /// 144 | /// The exception's additional arguments. 145 | /// The error message that explains the reason for the exception. 146 | public Exception(T args, String message) 147 | : this(args, message, null) { 148 | } 149 | 150 | #if !SILVERLIGHT && !PocketPC 151 | // Because at least 1 field is defined, 152 | // define the special deserialization constructor 153 | // Since this class is sealed, this constructor is private 154 | // If this class were not sealed, this constructor should be protected 155 | #if v4 156 | [SecurityCritical] 157 | #else 158 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 159 | #endif 160 | private Exception(SerializationInfo info, StreamingContext context) 161 | : base(info, context) { // Let the base deserialize its fields 162 | Contract.Requires(info != null); 163 | 164 | // Deserialize each field 165 | m_args = (T)info.GetValue(c_args, typeof(T)); 166 | } 167 | 168 | // Because at least 1 field is defined, 169 | // define the serialization method 170 | /// 171 | /// When overridden in a derived class, sets the SerializationInfo with information about the exception. 172 | /// 173 | /// The SerializationInfo that holds the serialized object data about the exception being thrown. 174 | /// The StreamingContext that contains contextual information about the source or destination. 175 | #if v4 176 | [SecurityCritical] 177 | #else 178 | [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)] 179 | #endif 180 | public override void GetObjectData(SerializationInfo info, StreamingContext context) { 181 | // Serialize each field 182 | info.AddValue(c_args, m_args); 183 | 184 | // Let the base type serialize its fields 185 | base.GetObjectData(info, context); 186 | } 187 | #endif 188 | 189 | /// 190 | /// Gets a message that describes the current exception. 191 | /// 192 | public override String Message { 193 | get { 194 | return base.Message + ((m_args != null) ? m_args.Message : null); 195 | } 196 | } 197 | 198 | /// 199 | /// Creates and returns a string representation of the current exception. 200 | /// 201 | /// 202 | public override string ToString() { 203 | return base.ToString(); 204 | } 205 | 206 | /// 207 | /// Serves as a hash function for a particular type. 208 | /// 209 | /// A hash code for the current Object. 210 | public override int GetHashCode() { 211 | return base.GetHashCode(); 212 | } 213 | 214 | /// 215 | /// Determines whether the specified Object is equal to the current Object. 216 | /// 217 | /// The Object to compare with the current Object. 218 | /// true if the specified Object is equal to the current Object; otherwise, false. 219 | public override Boolean Equals(Object obj) { 220 | Exception other = obj as Exception; 221 | if (other == null) return false; 222 | return Object.Equals(m_args, other.m_args) && base.Equals(obj); 223 | } 224 | } 225 | } 226 | 227 | 228 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/Flags.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Flags.cs 3 | Notices: Copyright (c) 2006-2008 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | 9 | /////////////////////////////////////////////////////////////////////////////// 10 | 11 | 12 | #if false 13 | namespace Wintellect { 14 | internal static class Flags { 15 | public static Boolean IsSet(Int32 flags, Int32 flagToTest) { 16 | if (flagToTest == 0) throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0"); 17 | return (flags & flagToTest) == flagToTest; 18 | } 19 | 20 | public static Boolean IsClear(Int32 flags, Int32 flagToTest) { 21 | if (flagToTest == 0) throw new ArgumentOutOfRangeException("flagToTest", "Value must not be 0"); 22 | return !IsSet(flags, flagToTest); 23 | } 24 | 25 | public static Boolean AnyFlagsSet(Int32 flags, Int32 flagsToTest) { 26 | return ((flags & flagsToTest) != 0); 27 | } 28 | 29 | public static Int32 SetFlag(Int32 flags, Int32 flagsToSet) { 30 | return flags | flagsToSet; 31 | } 32 | public static Int32 ClearFlag(Int32 flags, Int32 flagsToClear) { 33 | return flags & ~flagsToClear; 34 | } 35 | 36 | public static Boolean IsExactlyOneBitSet(Int32 flags) { 37 | return ((flags != 0) && ((flags & (flags - 1)) == 0)); 38 | } 39 | 40 | public static Int32 CountOnBits(Int32 flags) { 41 | Int32 BitsOn = 0; 42 | while (flags != 0) { BitsOn++; flags = flags & (flags - 1); } 43 | return (BitsOn); 44 | } 45 | 46 | public static void ForEachBit(Int32 flags, Predicate predicate) { 47 | if (predicate == null) throw new ArgumentNullException("predicate"); 48 | while (flags != 0) { 49 | Int32 decimalValue = flags; 50 | flags &= (flags - 1); 51 | decimalValue -= flags; 52 | // For example: 0xFF yields 1 2 4 8 16 32 64 128 53 | if (!predicate(decimalValue)) break; // If predicate returns false, stop 54 | } 55 | } 56 | 57 | public static void ForEachBit(Int64 flags, Predicate predicate) { 58 | if (predicate == null) throw new ArgumentNullException("predicate"); 59 | while (flags != 0) { 60 | Int64 decimalValue = flags; 61 | flags &= (flags - 1); 62 | decimalValue -= flags; 63 | if (!predicate((Int32) decimalValue)) break; // If predicate returns false, stop 64 | } 65 | } 66 | 67 | public static void ForEachBit(IntPtr flags, Predicate predicate) { 68 | if (IntPtr.Size == 4) ForEachBit(flags.ToInt32(), predicate); 69 | else ForEachBit(flags.ToInt64(), predicate); 70 | } 71 | } 72 | } 73 | #endif 74 | 75 | 76 | //////////////////////////////// End of File //////////////////////////////////} 77 | -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/OperationTimer.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: OperationTimer.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Diagnostics; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect { 16 | /// 17 | /// This class is useful for timing the duration of an algorithm 18 | /// 19 | public sealed class OperationTimer : IDisposable { 20 | private static Int32 s_NumOperationTimersStarted; 21 | private Stopwatch m_sw; 22 | private String m_text; 23 | private Int32 m_collectionCount; 24 | 25 | /// 26 | /// Constructs an OperationTimer with an empty text string 27 | /// 28 | public OperationTimer() : this(String.Empty) { } 29 | 30 | /// 31 | /// Constructs an OperationTimer with text identifying the operation 32 | /// 33 | /// Text describing the operation. 34 | public OperationTimer(String text) { 35 | if (Interlocked.Increment(ref s_NumOperationTimersStarted) == 1) 36 | PrepareForOperation(); 37 | m_text = text; 38 | m_collectionCount = GC.CollectionCount(0); 39 | m_sw = Stopwatch.StartNew(); // This should be the last statement in this method 40 | } 41 | 42 | /// 43 | /// Call this when the operation is done to see how long it took and how many GCs occurred. 44 | /// 45 | public void Dispose() { 46 | Console.WriteLine("{0,7:N0} (GCs={1,3}) {2}", 47 | m_sw.Elapsed.TotalMilliseconds, 48 | GC.CollectionCount(0) - m_collectionCount, m_text); 49 | Interlocked.Decrement(ref s_NumOperationTimersStarted); 50 | m_sw = null; 51 | } 52 | 53 | private static void PrepareForOperation() { 54 | GC.Collect(); 55 | GC.WaitForPendingFinalizers(); 56 | GC.Collect(); 57 | } 58 | } 59 | } 60 | 61 | 62 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/SafePinnedObject.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: SafePinnedObject.cs 3 | Notices: Copyright (c) 2006-2009 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Runtime.InteropServices; 9 | using Microsoft.Win32.SafeHandles; 10 | 11 | 12 | /////////////////////////////////////////////////////////////////////////////// 13 | 14 | 15 | namespace Wintellect { 16 | /// 17 | /// This class encapsulates pinning a buffer. 18 | /// 19 | public sealed class SafePinnedObject: SafeHandleZeroOrMinusOneIsInvalid { 20 | private GCHandle m_gcHandle; // Handle of pinned object (or 0) 21 | private Int32 m_size = 0; // The size (in bytes) unless overridden in ctor 22 | 23 | private SafePinnedObject(Object obj, Int32 offsetIntoObject, Int32 size) : base(true) { 24 | if (obj == null) return; 25 | 26 | // Pin the buffer, set the native address, and save the object's size 27 | m_gcHandle = GCHandle.Alloc(obj, GCHandleType.Pinned); 28 | unsafe { SetHandle((IntPtr) ((byte*) m_gcHandle.AddrOfPinnedObject() + offsetIntoObject)); } 29 | m_size = size; 30 | } 31 | 32 | /// 33 | /// This factory method wraps a SafePinnedObject around the specified object. 34 | /// 35 | /// The object that you want to pin. 36 | /// The SafePinnedObject wrapping the desired object. 37 | public static SafePinnedObject FromObject(Object value) { 38 | // If obj is null, we create this object but it pins nothing (size will be 0) 39 | if (value == null) return new SafePinnedObject(null, 0, 0); 40 | 41 | // If obj is an Array, we pinned this array, and return 42 | if (value.GetType().IsArray) return FromArray((Array) value, 0, -1); 43 | 44 | // Validate the structure of the object before pinning it 45 | if (value.GetType().IsAutoLayout) 46 | throw new ArgumentException("object must not be auto layout"); 47 | 48 | return new SafePinnedObject(value, 0, Marshal.SizeOf(value)); 49 | } 50 | 51 | /// 52 | /// This factory method wraps a SafePinnedObject around the specified array. 53 | /// 54 | /// The array that you want to pin. 55 | /// The first element in the array whose address you want to pass to native code. 56 | /// The number of elements in the array you wish to pass to native code. 57 | /// The SafePinnedObject wrapping the desired array elements. 58 | public static SafePinnedObject FromArray(Array array, Int32 startOffset, Int32 numberOfElements) { 59 | // If obj is null, we create this object but it pins nothing (size will be 0) 60 | if (array == null) return new SafePinnedObject(null, 0, 0); 61 | 62 | // Validate the structure of the object before pinning it 63 | if (array.Rank != 1) 64 | throw new ArgumentException("array Rank must be 1"); 65 | 66 | if (startOffset < 0) 67 | throw new ArgumentOutOfRangeException("startOffset", "Must be >= 0"); 68 | 69 | // Validate the structure of the array's element type 70 | Type elementType = array.GetType().GetElementType(); 71 | if (!elementType.IsValueType && !elementType.IsEnum) 72 | throw new ArgumentException("array's elements must be value types or enum types"); 73 | 74 | if (elementType.IsAutoLayout) 75 | throw new ArgumentException("array's elements must not be auto layout"); 76 | 77 | // If numElements not specied (-1), assume the remainder of the array length 78 | if (numberOfElements == -1) numberOfElements = array.Length - startOffset; 79 | 80 | if (numberOfElements > array.Length) 81 | throw new ArgumentOutOfRangeException("numberOfElements", "Array has fewer elements than specified"); 82 | 83 | // Convert startOffset from element offset to byte offset 84 | startOffset *= Marshal.SizeOf(elementType); 85 | 86 | return new SafePinnedObject(array, startOffset, 87 | numberOfElements * Marshal.SizeOf(elementType)); // Convert numElements to number of bytes 88 | } 89 | 90 | /// 91 | /// This factory method wraps a SafePinnedObject around an instance of the specified type. 92 | /// 93 | /// The type, an instance of which you want to pass to native code. 94 | /// The SafePinnedObject wrapping the desired type's instance. 95 | public static SafePinnedObject FromType(Type type) { 96 | return FromObject(System.Runtime.Serialization.FormatterServices.GetUninitializedObject(type)); 97 | } 98 | 99 | /// 100 | /// This factory method wraps a SafePinnedObject around a native block of memory. 101 | /// 102 | /// The starting address of the native block of memory. 103 | /// The number of bytes in the native block of memory. 104 | /// The SafePinnedObject wrapping the desired native block of memory. 105 | public static SafePinnedObject FromPointer(IntPtr address, Int32 numberOfBytes) { 106 | return new SafePinnedObject(address, numberOfBytes); 107 | } 108 | 109 | private SafePinnedObject(IntPtr address, Int32 numberOfBytes) 110 | : base(true) { 111 | m_size = numberOfBytes; 112 | SetHandle(address); 113 | } 114 | //internal IntPtr Address { get { return this.handle; } } 115 | 116 | /// This method is called when it is time to release the native resource. 117 | /// true if the native resource is released successfully. 118 | protected override Boolean ReleaseHandle() { 119 | SetHandle(IntPtr.Zero); // Just for safety, set the address to null 120 | if (m_gcHandle.IsAllocated) m_gcHandle.Free(); // Unpin the object 121 | return true; 122 | } 123 | 124 | #region Public methods to return Object reference and size (in bytes) 125 | /// 126 | /// Returns the object of a pinned buffer or null if not specified 127 | /// 128 | public Object Target { 129 | get { 130 | return m_gcHandle.IsAllocated ? m_gcHandle.Target : null; 131 | } 132 | } 133 | 134 | /// 135 | /// Returns the number of bytes in a pinned object or 0 if not specified 136 | /// 137 | public Int32 Size { get { return m_size; } } 138 | #endregion 139 | } 140 | } 141 | 142 | 143 | //////////////////////////////// End of File ////////////////////////////////// -------------------------------------------------------------------------------- /PowerThreading-Desktop/Wintellect/Singleton.cs: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | Module: Singleton.cs 3 | Notices: Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect 4 | ******************************************************************************/ 5 | 6 | 7 | using System; 8 | using System.Threading; 9 | using System.Diagnostics.CodeAnalysis; 10 | using System.Diagnostics.Contracts; 11 | 12 | 13 | /////////////////////////////////////////////////////////////////////////////// 14 | 15 | 16 | namespace Wintellect.Threading { 17 | /// 18 | /// Indicates whether singleton should be created using a double-check 19 | /// locking technique or via an interlocked-compare-exchange technique. 20 | /// 21 | public enum SingletonRaceLoser { 22 | /// 23 | /// If there is a race to create the singleton, the race is 24 | /// resolved by blocking all but one thread. 25 | /// 26 | Block = 0, 27 | 28 | /// 29 | /// If there is a race to create the singleton, the race is resolved 30 | /// by having all threads create the singleton but, when done, only one 31 | /// thread will win and the losing threads will have their singleton GC'd 32 | /// 33 | GC = 1, 34 | } 35 | 36 | /// 37 | /// This class ensures that only one singleton object is used if mutliple 38 | /// threads race to create one simultaneously. 39 | /// 40 | /// 41 | public sealed class Singleton where T: class { 42 | private SingletonRaceLoser m_raceLoser = SingletonRaceLoser.Block; 43 | 44 | /// 45 | /// A delegate that refers to a method that creates a singleton object. 46 | /// 47 | /// The singleton object. 48 | [SuppressMessage("Microsoft.Design", "CA1034:NestedTypesShouldNotBeVisible")] 49 | public delegate T Creator(); 50 | private Creator m_creator = null; 51 | 52 | private T m_value = null; 53 | 54 | /// 55 | /// Constructs a Singleton object that knows how to create a singleton object. 56 | /// 57 | /// Indicates how to arbitrate a race between multiple thread attempting to create the singleton object. 58 | /// Refers to the method that knows how to create the singleton object. 59 | public Singleton(SingletonRaceLoser raceLoser, Creator creator) { 60 | m_raceLoser = raceLoser; 61 | m_creator = creator; 62 | } 63 | 64 | /// 65 | /// Returns the singleton object. 66 | /// 67 | public T Value { 68 | get { 69 | if (m_value != null) return m_value; 70 | Contract.Assume(m_creator != null); 71 | switch (m_raceLoser) { 72 | case SingletonRaceLoser.Block: 73 | lock (m_creator) { 74 | if (m_value == null) m_value = m_creator(); 75 | } 76 | break; 77 | 78 | case SingletonRaceLoser.GC: 79 | T val = m_creator(); 80 | if (Interlocked.CompareExchange(ref m_value, val, null) != null) { 81 | IDisposable d = val as IDisposable; 82 | if (d != null) d.Dispose(); 83 | } 84 | break; 85 | } 86 | return m_value; 87 | } 88 | } 89 | } 90 | } 91 | 92 | 93 | //////////////////////////////// End of File ////////////////////////////////// 94 | -------------------------------------------------------------------------------- /PowerThreading-Silverlight/PowerThreading-Silverlight.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | v3.5 5 | 6 | 7 | Debug 8 | AnyCPU 9 | 9.0.30729 10 | 2.0 11 | {263BF5D3-C2C7-41C4-9936-90F0E7C31451} 12 | {A1591282-1198-4647-A2B1-27E5FF5F6F3B};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 13 | Library 14 | Properties 15 | Wintellect 16 | Wintellect.Threading.Silverlight 17 | v5.0 18 | false 19 | true 20 | false 21 | false 22 | 23 | 24 | Silverlight 25 | $(TargetFrameworkVersion) 26 | 27 | 28 | 29 | 30 | 4.0 31 | publish\ 32 | true 33 | Disk 34 | false 35 | Foreground 36 | 7 37 | Days 38 | false 39 | false 40 | true 41 | 0 42 | 1.0.0.%2a 43 | false 44 | false 45 | true 46 | 47 | 48 | true 49 | full 50 | false 51 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 52 | DEBUG;TRACE;SILVERLIGHT 53 | true 54 | true 55 | prompt 56 | 4 57 | true 58 | false 59 | AllRules.ruleset 60 | 61 | 62 | pdbonly 63 | true 64 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 65 | TRACE;SILVERLIGHT,INCLUDE_GATES 66 | true 67 | true 68 | prompt 69 | 4 70 | ..\..\..\Seminars\Threading\Code\PowerThreading\Wintellect.Threading.Silverlight.xml 71 | true 72 | AllRules.ruleset 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | Wintellect.IO\StreamExtensions.cs 86 | 87 | 88 | Wintellect.Threading\AsyncProgModel\ApmWrap.cs 89 | 90 | 91 | Wintellect.Threading\AsyncProgModel\AsyncEnumerator.cs 92 | 93 | 94 | Wintellect.Threading\AsyncProgModel\AsyncResult.cs 95 | 96 | 97 | Wintellect.Threading\AsyncProgModel\CountdownTimer.cs 98 | 99 | 100 | Wintellect.Threading\AsyncProgModel\EventApm.cs 101 | 102 | 103 | Wintellect.Threading\AsyncProgModel\SyncContextAsyncCallback.cs 104 | 105 | 106 | Wintellect.Threading\AsyncProgModel\SyncGate.cs 107 | 108 | 109 | Wintellect.Threading\InterlockedEx.cs 110 | 111 | 112 | Wintellect\Contracts.cs 113 | 114 | 115 | Wintellect\Disposer.cs 116 | 117 | 118 | Wintellect\Exception.cs 119 | 120 | 121 | Wintellect\Singleton.cs 122 | 123 | 124 | 125 | 126 | 127 | False 128 | .NET Framework 3.5 SP1 Client Profile 129 | false 130 | 131 | 132 | False 133 | .NET Framework 3.5 SP1 134 | true 135 | 136 | 137 | False 138 | Microsoft Visual Basic PowerPacks 10.0 139 | true 140 | 141 | 142 | False 143 | Windows Installer 3.1 144 | true 145 | 146 | 147 | 148 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | -------------------------------------------------------------------------------- /PowerThreading-Silverlight/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: CLSCompliant(true)] 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Power Threading (for Silverlight)")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Wintellect")] 14 | [assembly: AssemblyProduct("Power Threading (for Silverlight)")] 15 | [assembly: AssemblyCopyright("Copyright (c) 2006-2010 by Jeffrey Richter and Wintellect")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("8027db7f-7623-4e46-ab4c-9d557f105cd0")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | [assembly: AssemblyVersion("5.0.0.0")] 37 | [assembly: AssemblyFileVersion("5.0.0.0")] 38 | -------------------------------------------------------------------------------- /PowerThreading-WindowsPhone/PowerThreading-WindowsPhone.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 10.0.20506 7 | 2.0 8 | {F2D13F04-4069-4D1A-9C2D-A70F80A57DE6} 9 | {C089C8C0-30E0-4E22-80C0-CE093F111A43};{fae04ec0-301f-11d3-bf4b-00c04f79efbc} 10 | Library 11 | Properties 12 | Wintellect 13 | Wintellect.Threading.WindowsPhone 14 | v4.0 15 | $(TargetFrameworkVersion) 16 | WindowsPhone 17 | Silverlight 18 | false 19 | true 20 | true 21 | 22 | 23 | true 24 | full 25 | false 26 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 27 | TRACE;DEBUG;SILVERLIGHT,INCLUDE_GATES,PocketPC 28 | true 29 | true 30 | prompt 31 | 4 32 | 33 | 34 | pdbonly 35 | true 36 | ..\..\..\Seminars\Threading\Code\PowerThreading\ 37 | TRACE;PocketPC,SILVERLIGHT,INCLUDE_GATES 38 | true 39 | true 40 | prompt 41 | 4 42 | ..\..\..\Seminars\Threading\Code\PowerThreading\Wintellect.Threading.WindowsPhone.xml 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | ApmWrap.cs 51 | 52 | 53 | AsyncEnumerator.cs 54 | 55 | 56 | AsyncResult.cs 57 | 58 | 59 | EventApm.cs 60 | 61 | 62 | SyncGate.cs 63 | 64 | 65 | InterlockedEx.cs 66 | 67 | 68 | Exception.cs 69 | 70 | 71 | Contracts.cs 72 | 73 | 74 | 75 | 76 | 77 | 78 | 85 | -------------------------------------------------------------------------------- /PowerThreading-WindowsPhone/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Reflection; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: CLSCompliant(true)] 6 | 7 | // General Information about an assembly is controlled through the following 8 | // set of attributes. Change these attribute values to modify the information 9 | // associated with an assembly. 10 | [assembly: AssemblyTitle("Power Threading (for Windows Phone)")] 11 | [assembly: AssemblyDescription("")] 12 | [assembly: AssemblyConfiguration("")] 13 | [assembly: AssemblyCompany("Wintellect")] 14 | [assembly: AssemblyProduct("Power Threading (for Windows Phone)")] 15 | [assembly: AssemblyCopyright("Copyright (c) 2010 by Jeffrey Richter and Wintellect")] 16 | [assembly: AssemblyTrademark("")] 17 | [assembly: AssemblyCulture("")] 18 | 19 | // Setting ComVisible to false makes the types in this assembly not visible 20 | // to COM components. If you need to access a type in this assembly from 21 | // COM, set the ComVisible attribute to true on that type. 22 | [assembly: ComVisible(false)] 23 | 24 | // The following GUID is for the ID of the typelib if this project is exposed to COM 25 | [assembly: Guid("4b494cbd-3b70-4aab-b4cf-f827066a1a6a")] 26 | 27 | // Version information for an assembly consists of the following four values: 28 | // 29 | // Major Version 30 | // Minor Version 31 | // Build Number 32 | // Revision 33 | // 34 | // You can specify all the values or you can default the Revision and Build Numbers 35 | // by using the '*' as shown below: 36 | [assembly: AssemblyVersion("5.0.*")] 37 | [assembly: AssemblyFileVersion("5.0.0.0")] 38 | -------------------------------------------------------------------------------- /PowerThreading.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2012 4 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Collateral", "Collateral", "{3F2CE97F-49CD-4740-B582-C3D64D3102C3}" 5 | ProjectSection(SolutionItems) = preProject 6 | Power Threading License.docx = Power Threading License.docx 7 | Power Threading Overview.docx = Power Threading Overview.docx 8 | EndProjectSection 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerThreading-Desktop", "PowerThreading-Desktop\PowerThreading-Desktop.csproj", "{A74FEF61-2540-4C74-9300-2DADEF397CC7}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PowerThreading-Silverlight", "PowerThreading-Silverlight\PowerThreading-Silverlight.csproj", "{263BF5D3-C2C7-41C4-9936-90F0E7C31451}" 13 | EndProject 14 | Global 15 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 16 | Debug|Any CPU = Debug|Any CPU 17 | Release|Any CPU = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {A74FEF61-2540-4C74-9300-2DADEF397CC7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {A74FEF61-2540-4C74-9300-2DADEF397CC7}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {A74FEF61-2540-4C74-9300-2DADEF397CC7}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {A74FEF61-2540-4C74-9300-2DADEF397CC7}.Release|Any CPU.Build.0 = Release|Any CPU 24 | {263BF5D3-C2C7-41C4-9936-90F0E7C31451}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 25 | {263BF5D3-C2C7-41C4-9936-90F0E7C31451}.Debug|Any CPU.Build.0 = Debug|Any CPU 26 | {263BF5D3-C2C7-41C4-9936-90F0E7C31451}.Release|Any CPU.ActiveCfg = Release|Any CPU 27 | {263BF5D3-C2C7-41C4-9936-90F0E7C31451}.Release|Any CPU.Build.0 = Release|Any CPU 28 | EndGlobalSection 29 | GlobalSection(SolutionProperties) = preSolution 30 | HideSolutionNode = FALSE 31 | EndGlobalSection 32 | EndGlobal 33 | -------------------------------------------------------------------------------- /ReadMe.md: -------------------------------------------------------------------------------- 1 | # Jeffrey Richter's Power Threading Library # 2 | 3 | The Power Threading Library consists of a number of classes to assist you with building responsive, reliable, and scalable applications and components. There are also a bunch of general-purpose utility classes in this library that have nothing to do with threading but I threw them in here anyway. 4 | 5 | The AsyncEnumerator class is particularly useful for developers who are trying to build responsive, reliable, and scalable applications and components. This class allows developers to leverage all the features of the APM using the simpler, more-familiar synchronous programming model. 6 | 7 | See the Power Threading Overview document in the root directory for more overview and detailed documentation. --------------------------------------------------------------------------------