├── .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.
--------------------------------------------------------------------------------