##// END OF EJS Templates
fixed AsyncQueue iterator
cin -
r127:d86da8d2d4c3 v2
parent child
Show More
@@ -1,232 +1,230
1 <?xml version="1.0" encoding="utf-8"?>
1 <?xml version="1.0" encoding="utf-8"?>
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
2 <Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup>
3 <PropertyGroup>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
4 <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
5 <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
6 <ProjectGuid>{F550F1F8-8746-4AD0-9614-855F4C4B7F05}</ProjectGuid>
7 <OutputType>Library</OutputType>
7 <OutputType>Library</OutputType>
8 <RootNamespace>Implab</RootNamespace>
8 <RootNamespace>Implab</RootNamespace>
9 <AssemblyName>Implab</AssemblyName>
9 <AssemblyName>Implab</AssemblyName>
10 <ProductVersion>8.0.30703</ProductVersion>
11 <SchemaVersion>2.0</SchemaVersion>
12 </PropertyGroup>
10 </PropertyGroup>
13 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
11 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
14 <DebugSymbols>true</DebugSymbols>
12 <DebugSymbols>true</DebugSymbols>
15 <DebugType>full</DebugType>
13 <DebugType>full</DebugType>
16 <Optimize>false</Optimize>
14 <Optimize>false</Optimize>
17 <OutputPath>bin\Debug</OutputPath>
15 <OutputPath>bin\Debug</OutputPath>
18 <DefineConstants>TRACE;DEBUG;</DefineConstants>
16 <DefineConstants>TRACE;DEBUG;</DefineConstants>
19 <ErrorReport>prompt</ErrorReport>
17 <ErrorReport>prompt</ErrorReport>
20 <WarningLevel>4</WarningLevel>
18 <WarningLevel>4</WarningLevel>
21 <ConsolePause>false</ConsolePause>
19 <ConsolePause>false</ConsolePause>
22 <RunCodeAnalysis>true</RunCodeAnalysis>
20 <RunCodeAnalysis>true</RunCodeAnalysis>
23 </PropertyGroup>
21 </PropertyGroup>
24 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
22 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
25 <DebugType>full</DebugType>
23 <DebugType>full</DebugType>
26 <Optimize>true</Optimize>
24 <Optimize>true</Optimize>
27 <OutputPath>bin\Release</OutputPath>
25 <OutputPath>bin\Release</OutputPath>
28 <ErrorReport>prompt</ErrorReport>
26 <ErrorReport>prompt</ErrorReport>
29 <WarningLevel>4</WarningLevel>
27 <WarningLevel>4</WarningLevel>
30 <ConsolePause>false</ConsolePause>
28 <ConsolePause>false</ConsolePause>
31 </PropertyGroup>
29 </PropertyGroup>
32 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
30 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug 4.5|AnyCPU' ">
33 <DebugSymbols>true</DebugSymbols>
31 <DebugSymbols>true</DebugSymbols>
34 <DebugType>full</DebugType>
32 <DebugType>full</DebugType>
35 <Optimize>false</Optimize>
33 <Optimize>false</Optimize>
36 <OutputPath>bin\Debug</OutputPath>
34 <OutputPath>bin\Debug</OutputPath>
37 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
35 <DefineConstants>TRACE;DEBUG;NET_4_5</DefineConstants>
38 <ErrorReport>prompt</ErrorReport>
36 <ErrorReport>prompt</ErrorReport>
39 <WarningLevel>4</WarningLevel>
37 <WarningLevel>4</WarningLevel>
40 <RunCodeAnalysis>true</RunCodeAnalysis>
38 <RunCodeAnalysis>true</RunCodeAnalysis>
41 <ConsolePause>false</ConsolePause>
39 <ConsolePause>false</ConsolePause>
42 </PropertyGroup>
40 </PropertyGroup>
43 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
41 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release 4.5|AnyCPU' ">
44 <Optimize>true</Optimize>
42 <Optimize>true</Optimize>
45 <OutputPath>bin\Release</OutputPath>
43 <OutputPath>bin\Release</OutputPath>
46 <ErrorReport>prompt</ErrorReport>
44 <ErrorReport>prompt</ErrorReport>
47 <WarningLevel>4</WarningLevel>
45 <WarningLevel>4</WarningLevel>
48 <ConsolePause>false</ConsolePause>
46 <ConsolePause>false</ConsolePause>
49 <DefineConstants>NET_4_5</DefineConstants>
47 <DefineConstants>NET_4_5</DefineConstants>
50 </PropertyGroup>
48 </PropertyGroup>
51 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
49 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'DebugMono|AnyCPU' ">
52 <DebugSymbols>true</DebugSymbols>
50 <DebugSymbols>true</DebugSymbols>
53 <DebugType>full</DebugType>
51 <DebugType>full</DebugType>
54 <Optimize>false</Optimize>
52 <Optimize>false</Optimize>
55 <OutputPath>bin\Debug</OutputPath>
53 <OutputPath>bin\Debug</OutputPath>
56 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
54 <DefineConstants>TRACE;DEBUG;NET_4_5;MONO</DefineConstants>
57 <ErrorReport>prompt</ErrorReport>
55 <ErrorReport>prompt</ErrorReport>
58 <WarningLevel>4</WarningLevel>
56 <WarningLevel>4</WarningLevel>
59 <RunCodeAnalysis>true</RunCodeAnalysis>
57 <RunCodeAnalysis>true</RunCodeAnalysis>
60 <ConsolePause>false</ConsolePause>
58 <ConsolePause>false</ConsolePause>
61 </PropertyGroup>
59 </PropertyGroup>
62 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
60 <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'ReleaseMono|AnyCPU' ">
63 <Optimize>true</Optimize>
61 <Optimize>true</Optimize>
64 <OutputPath>bin\Release</OutputPath>
62 <OutputPath>bin\Release</OutputPath>
65 <DefineConstants>NET_4_5;MONO;</DefineConstants>
63 <DefineConstants>NET_4_5;MONO;</DefineConstants>
66 <ErrorReport>prompt</ErrorReport>
64 <ErrorReport>prompt</ErrorReport>
67 <WarningLevel>4</WarningLevel>
65 <WarningLevel>4</WarningLevel>
68 <ConsolePause>false</ConsolePause>
66 <ConsolePause>false</ConsolePause>
69 </PropertyGroup>
67 </PropertyGroup>
70 <ItemGroup>
68 <ItemGroup>
71 <Reference Include="System" />
69 <Reference Include="System" />
72 <Reference Include="System.Xml" />
70 <Reference Include="System.Xml" />
73 </ItemGroup>
71 </ItemGroup>
74 <ItemGroup>
72 <ItemGroup>
75 <Compile Include="Component.cs" />
73 <Compile Include="Component.cs" />
76 <Compile Include="CustomEqualityComparer.cs" />
74 <Compile Include="CustomEqualityComparer.cs" />
77 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
75 <Compile Include="Diagnostics\ConsoleTraceListener.cs" />
78 <Compile Include="Diagnostics\EventText.cs" />
76 <Compile Include="Diagnostics\EventText.cs" />
79 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
77 <Compile Include="Diagnostics\IEventTextFormatter.cs" />
80 <Compile Include="Diagnostics\LogChannel.cs" />
78 <Compile Include="Diagnostics\LogChannel.cs" />
81 <Compile Include="Diagnostics\LogicalOperation.cs" />
79 <Compile Include="Diagnostics\LogicalOperation.cs" />
82 <Compile Include="Diagnostics\TextFileListener.cs" />
80 <Compile Include="Diagnostics\TextFileListener.cs" />
83 <Compile Include="Diagnostics\TextListenerBase.cs" />
81 <Compile Include="Diagnostics\TextListenerBase.cs" />
84 <Compile Include="Diagnostics\TraceLog.cs" />
82 <Compile Include="Diagnostics\TraceLog.cs" />
85 <Compile Include="Diagnostics\TraceEvent.cs" />
83 <Compile Include="Diagnostics\TraceEvent.cs" />
86 <Compile Include="Diagnostics\TraceEventType.cs" />
84 <Compile Include="Diagnostics\TraceEventType.cs" />
87 <Compile Include="Disposable.cs" />
85 <Compile Include="Disposable.cs" />
88 <Compile Include="ICancellable.cs" />
86 <Compile Include="ICancellable.cs" />
89 <Compile Include="IProgressHandler.cs" />
87 <Compile Include="IProgressHandler.cs" />
90 <Compile Include="IProgressNotifier.cs" />
88 <Compile Include="IProgressNotifier.cs" />
91 <Compile Include="IPromiseT.cs" />
89 <Compile Include="IPromiseT.cs" />
92 <Compile Include="IPromise.cs" />
90 <Compile Include="IPromise.cs" />
93 <Compile Include="IServiceLocator.cs" />
91 <Compile Include="IServiceLocator.cs" />
94 <Compile Include="ITaskController.cs" />
92 <Compile Include="ITaskController.cs" />
95 <Compile Include="JSON\JSONElementContext.cs" />
93 <Compile Include="JSON\JSONElementContext.cs" />
96 <Compile Include="JSON\JSONElementType.cs" />
94 <Compile Include="JSON\JSONElementType.cs" />
97 <Compile Include="JSON\JSONGrammar.cs" />
95 <Compile Include="JSON\JSONGrammar.cs" />
98 <Compile Include="JSON\JSONParser.cs" />
96 <Compile Include="JSON\JSONParser.cs" />
99 <Compile Include="JSON\JSONScanner.cs" />
97 <Compile Include="JSON\JSONScanner.cs" />
100 <Compile Include="JSON\JsonTokenType.cs" />
98 <Compile Include="JSON\JsonTokenType.cs" />
101 <Compile Include="JSON\JSONWriter.cs" />
99 <Compile Include="JSON\JSONWriter.cs" />
102 <Compile Include="JSON\JSONXmlReader.cs" />
100 <Compile Include="JSON\JSONXmlReader.cs" />
103 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
101 <Compile Include="JSON\JSONXmlReaderOptions.cs" />
104 <Compile Include="JSON\StringTranslator.cs" />
102 <Compile Include="JSON\StringTranslator.cs" />
105 <Compile Include="Parallels\DispatchPool.cs" />
103 <Compile Include="Parallels\DispatchPool.cs" />
106 <Compile Include="Parallels\ArrayTraits.cs" />
104 <Compile Include="Parallels\ArrayTraits.cs" />
107 <Compile Include="Parallels\MTQueue.cs" />
105 <Compile Include="Parallels\MTQueue.cs" />
108 <Compile Include="Parallels\WorkerPool.cs" />
106 <Compile Include="Parallels\WorkerPool.cs" />
109 <Compile Include="Parsing\Alphabet.cs" />
107 <Compile Include="Parsing\Alphabet.cs" />
110 <Compile Include="Parsing\AlphabetBase.cs" />
108 <Compile Include="Parsing\AlphabetBase.cs" />
111 <Compile Include="Parsing\AltToken.cs" />
109 <Compile Include="Parsing\AltToken.cs" />
112 <Compile Include="Parsing\BinaryToken.cs" />
110 <Compile Include="Parsing\BinaryToken.cs" />
113 <Compile Include="Parsing\CatToken.cs" />
111 <Compile Include="Parsing\CatToken.cs" />
114 <Compile Include="Parsing\CDFADefinition.cs" />
112 <Compile Include="Parsing\CDFADefinition.cs" />
115 <Compile Include="Parsing\DFABuilder.cs" />
113 <Compile Include="Parsing\DFABuilder.cs" />
116 <Compile Include="Parsing\DFADefinitionBase.cs" />
114 <Compile Include="Parsing\DFADefinitionBase.cs" />
117 <Compile Include="Parsing\DFAStateDescriptor.cs" />
115 <Compile Include="Parsing\DFAStateDescriptor.cs" />
118 <Compile Include="Parsing\DFAutomaton.cs" />
116 <Compile Include="Parsing\DFAutomaton.cs" />
119 <Compile Include="Parsing\EDFADefinition.cs" />
117 <Compile Include="Parsing\EDFADefinition.cs" />
120 <Compile Include="Parsing\EmptyToken.cs" />
118 <Compile Include="Parsing\EmptyToken.cs" />
121 <Compile Include="Parsing\EndToken.cs" />
119 <Compile Include="Parsing\EndToken.cs" />
122 <Compile Include="Parsing\EnumAlphabet.cs" />
120 <Compile Include="Parsing\EnumAlphabet.cs" />
123 <Compile Include="Parsing\Grammar.cs" />
121 <Compile Include="Parsing\Grammar.cs" />
124 <Compile Include="Parsing\IAlphabet.cs" />
122 <Compile Include="Parsing\IAlphabet.cs" />
125 <Compile Include="Parsing\IDFADefinition.cs" />
123 <Compile Include="Parsing\IDFADefinition.cs" />
126 <Compile Include="Parsing\IVisitor.cs" />
124 <Compile Include="Parsing\IVisitor.cs" />
127 <Compile Include="Parsing\ParserException.cs" />
125 <Compile Include="Parsing\ParserException.cs" />
128 <Compile Include="Parsing\Scanner.cs" />
126 <Compile Include="Parsing\Scanner.cs" />
129 <Compile Include="Parsing\StarToken.cs" />
127 <Compile Include="Parsing\StarToken.cs" />
130 <Compile Include="Parsing\SymbolToken.cs" />
128 <Compile Include="Parsing\SymbolToken.cs" />
131 <Compile Include="Parsing\Token.cs" />
129 <Compile Include="Parsing\Token.cs" />
132 <Compile Include="ServiceLocator.cs" />
130 <Compile Include="ServiceLocator.cs" />
133 <Compile Include="TaskController.cs" />
131 <Compile Include="TaskController.cs" />
134 <Compile Include="ProgressInitEventArgs.cs" />
132 <Compile Include="ProgressInitEventArgs.cs" />
135 <Compile Include="Properties\AssemblyInfo.cs" />
133 <Compile Include="Properties\AssemblyInfo.cs" />
136 <Compile Include="Parallels\AsyncPool.cs" />
134 <Compile Include="Parallels\AsyncPool.cs" />
137 <Compile Include="Safe.cs" />
135 <Compile Include="Safe.cs" />
138 <Compile Include="ValueEventArgs.cs" />
136 <Compile Include="ValueEventArgs.cs" />
139 <Compile Include="PromiseExtensions.cs" />
137 <Compile Include="PromiseExtensions.cs" />
140 <Compile Include="SyncContextPromise.cs" />
138 <Compile Include="SyncContextPromise.cs" />
141 <Compile Include="Diagnostics\OperationContext.cs" />
139 <Compile Include="Diagnostics\OperationContext.cs" />
142 <Compile Include="Diagnostics\TraceContext.cs" />
140 <Compile Include="Diagnostics\TraceContext.cs" />
143 <Compile Include="Diagnostics\LogEventArgs.cs" />
141 <Compile Include="Diagnostics\LogEventArgs.cs" />
144 <Compile Include="Diagnostics\LogEventArgsT.cs" />
142 <Compile Include="Diagnostics\LogEventArgsT.cs" />
145 <Compile Include="Diagnostics\Extensions.cs" />
143 <Compile Include="Diagnostics\Extensions.cs" />
146 <Compile Include="IComponentContainer.cs" />
144 <Compile Include="IComponentContainer.cs" />
147 <Compile Include="PromiseEventType.cs" />
145 <Compile Include="PromiseEventType.cs" />
148 <Compile Include="Parallels\MTCustomQueue.cs" />
146 <Compile Include="Parallels\MTCustomQueue.cs" />
149 <Compile Include="Parallels\MTCustomQueueNode.cs" />
147 <Compile Include="Parallels\MTCustomQueueNode.cs" />
150 <Compile Include="ComponentContainer.cs" />
148 <Compile Include="ComponentContainer.cs" />
151 <Compile Include="DisposablePool.cs" />
149 <Compile Include="DisposablePool.cs" />
152 <Compile Include="ObjectPool.cs" />
150 <Compile Include="ObjectPool.cs" />
153 <Compile Include="Parallels\AsyncQueue.cs" />
151 <Compile Include="Parallels\AsyncQueue.cs" />
154 <Compile Include="PromiseT.cs" />
152 <Compile Include="PromiseT.cs" />
155 <Compile Include="IDeferred.cs" />
153 <Compile Include="IDeferred.cs" />
156 <Compile Include="IDeferredT.cs" />
154 <Compile Include="IDeferredT.cs" />
157 <Compile Include="AbstractPromise.cs" />
155 <Compile Include="AbstractPromise.cs" />
158 <Compile Include="Promise.cs" />
156 <Compile Include="Promise.cs" />
159 <Compile Include="PromiseTransientException.cs" />
157 <Compile Include="PromiseTransientException.cs" />
160 </ItemGroup>
158 </ItemGroup>
161 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
159 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
162 <ItemGroup />
160 <ItemGroup />
163 <ProjectExtensions>
161 <ProjectExtensions>
164 <MonoDevelop>
162 <MonoDevelop>
165 <Properties>
163 <Properties>
166 <Policies>
164 <Policies>
167 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
165 <CSharpFormattingPolicy IndentSwitchBody="True" NamespaceBraceStyle="EndOfLine" ClassBraceStyle="EndOfLine" InterfaceBraceStyle="EndOfLine" StructBraceStyle="EndOfLine" EnumBraceStyle="EndOfLine" MethodBraceStyle="EndOfLine" ConstructorBraceStyle="EndOfLine" DestructorBraceStyle="EndOfLine" BeforeMethodDeclarationParentheses="False" BeforeMethodCallParentheses="False" BeforeConstructorDeclarationParentheses="False" NewLineBeforeConstructorInitializerColon="NewLine" NewLineAfterConstructorInitializerColon="SameLine" BeforeIndexerDeclarationBracket="False" BeforeDelegateDeclarationParentheses="False" NewParentheses="False" SpacesBeforeBrackets="False" inheritsSet="Mono" inheritsScope="text/x-csharp" scope="text/x-csharp" />
168 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
166 <TextStylePolicy FileWidth="120" EolMarker="Unix" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/x-csharp" />
169 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
167 <DotNetNamingPolicy DirectoryNamespaceAssociation="PrefixedHierarchical" ResourceNamePolicy="MSBuild" />
170 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
168 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="application/xml" />
171 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
169 <XmlFormattingPolicy inheritsSet="Mono" inheritsScope="application/xml" scope="application/xml" />
172 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
170 <TextStylePolicy FileWidth="120" TabsToSpaces="False" inheritsSet="VisualStudio" inheritsScope="text/plain" scope="text/plain" />
173 <NameConventionPolicy>
171 <NameConventionPolicy>
174 <Rules>
172 <Rules>
175 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
173 <NamingRule Name="Namespaces" AffectedEntity="Namespace" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
176 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
174 <NamingRule Name="Types" AffectedEntity="Class, Struct, Enum, Delegate" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
177 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
175 <NamingRule Name="Interfaces" AffectedEntity="Interface" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
178 <RequiredPrefixes>
176 <RequiredPrefixes>
179 <String>I</String>
177 <String>I</String>
180 </RequiredPrefixes>
178 </RequiredPrefixes>
181 </NamingRule>
179 </NamingRule>
182 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
180 <NamingRule Name="Attributes" AffectedEntity="CustomAttributes" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
183 <RequiredSuffixes>
181 <RequiredSuffixes>
184 <String>Attribute</String>
182 <String>Attribute</String>
185 </RequiredSuffixes>
183 </RequiredSuffixes>
186 </NamingRule>
184 </NamingRule>
187 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
185 <NamingRule Name="Event Arguments" AffectedEntity="CustomEventArgs" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
188 <RequiredSuffixes>
186 <RequiredSuffixes>
189 <String>EventArgs</String>
187 <String>EventArgs</String>
190 </RequiredSuffixes>
188 </RequiredSuffixes>
191 </NamingRule>
189 </NamingRule>
192 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
190 <NamingRule Name="Exceptions" AffectedEntity="CustomExceptions" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
193 <RequiredSuffixes>
191 <RequiredSuffixes>
194 <String>Exception</String>
192 <String>Exception</String>
195 </RequiredSuffixes>
193 </RequiredSuffixes>
196 </NamingRule>
194 </NamingRule>
197 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
195 <NamingRule Name="Methods" AffectedEntity="Methods" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
198 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
196 <NamingRule Name="Static Readonly Fields" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Protected, Public" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True" />
199 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
197 <NamingRule Name="Fields (Non Private)" AffectedEntity="Field" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
200 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
198 <NamingRule Name="ReadOnly Fields (Non Private)" AffectedEntity="ReadonlyField" VisibilityMask="Internal, Public" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False" />
201 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
199 <NamingRule Name="Fields (Private)" AffectedEntity="Field, ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
202 <RequiredPrefixes>
200 <RequiredPrefixes>
203 <String>m_</String>
201 <String>m_</String>
204 </RequiredPrefixes>
202 </RequiredPrefixes>
205 </NamingRule>
203 </NamingRule>
206 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
204 <NamingRule Name="Static Fields (Private)" AffectedEntity="Field" VisibilityMask="Private" NamingStyle="CamelCase" IncludeInstanceMembers="False" IncludeStaticEntities="True">
207 <RequiredPrefixes>
205 <RequiredPrefixes>
208 <String>_</String>
206 <String>_</String>
209 </RequiredPrefixes>
207 </RequiredPrefixes>
210 </NamingRule>
208 </NamingRule>
211 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
209 <NamingRule Name="ReadOnly Fields (Private)" AffectedEntity="ReadonlyField" VisibilityMask="Private, Protected" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="False">
212 <RequiredPrefixes>
210 <RequiredPrefixes>
213 <String>m_</String>
211 <String>m_</String>
214 </RequiredPrefixes>
212 </RequiredPrefixes>
215 </NamingRule>
213 </NamingRule>
216 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
214 <NamingRule Name="Constant Fields" AffectedEntity="ConstantField" VisibilityMask="VisibilityMask" NamingStyle="AllUpper" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
217 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
215 <NamingRule Name="Properties" AffectedEntity="Property" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
218 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
216 <NamingRule Name="Events" AffectedEntity="Event" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
219 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
217 <NamingRule Name="Enum Members" AffectedEntity="EnumMember" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
220 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
218 <NamingRule Name="Parameters" AffectedEntity="Parameter, LocalVariable" VisibilityMask="VisibilityMask" NamingStyle="CamelCase" IncludeInstanceMembers="True" IncludeStaticEntities="True" />
221 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
219 <NamingRule Name="Type Parameters" AffectedEntity="TypeParameter" VisibilityMask="VisibilityMask" NamingStyle="PascalCase" IncludeInstanceMembers="True" IncludeStaticEntities="True">
222 <RequiredPrefixes>
220 <RequiredPrefixes>
223 <String>T</String>
221 <String>T</String>
224 </RequiredPrefixes>
222 </RequiredPrefixes>
225 </NamingRule>
223 </NamingRule>
226 </Rules>
224 </Rules>
227 </NameConventionPolicy>
225 </NameConventionPolicy>
228 </Policies>
226 </Policies>
229 </Properties>
227 </Properties>
230 </MonoDevelop>
228 </MonoDevelop>
231 </ProjectExtensions>
229 </ProjectExtensions>
232 </Project> No newline at end of file
230 </Project>
@@ -1,619 +1,629
1 using System.Threading;
1 using System.Threading;
2 using System.Collections.Generic;
2 using System.Collections.Generic;
3 using System;
3 using System;
4 using System.Collections;
4 using System.Collections;
5 using System.Diagnostics;
5 using System.Diagnostics;
6
6
7 namespace Implab.Parallels {
7 namespace Implab.Parallels {
8 public class AsyncQueue<T> : IEnumerable<T> {
8 public class AsyncQueue<T> : IEnumerable<T> {
9 class Chunk {
9 class Chunk {
10 public Chunk next;
10 public Chunk next;
11
11
12 int m_low;
12 int m_low;
13 int m_hi;
13 int m_hi;
14 int m_alloc;
14 int m_alloc;
15 readonly int m_size;
15 readonly int m_size;
16 readonly T[] m_data;
16 readonly T[] m_data;
17
17
18 public Chunk(int size) {
18 public Chunk(int size) {
19 m_size = size;
19 m_size = size;
20 m_data = new T[size];
20 m_data = new T[size];
21 }
21 }
22
22
23 public Chunk(int size, T value) {
23 public Chunk(int size, T value) {
24 m_size = size;
24 m_size = size;
25 m_hi = 1;
25 m_hi = 1;
26 m_alloc = 1;
26 m_alloc = 1;
27 m_data = new T[size];
27 m_data = new T[size];
28 m_data[0] = value;
28 m_data[0] = value;
29 }
29 }
30
30
31 public Chunk(int size, T[] data, int offset, int length, int alloc) {
31 public Chunk(int size, T[] data, int offset, int length, int alloc) {
32 m_size = size;
32 m_size = size;
33 m_hi = length;
33 m_hi = length;
34 m_alloc = alloc;
34 m_alloc = alloc;
35 m_data = new T[size];
35 m_data = new T[size];
36 Array.Copy(data, offset, m_data, 0, length);
36 Array.Copy(data, offset, m_data, 0, length);
37 }
37 }
38
38
39 public int Low {
39 public int Low {
40 get { return m_low; }
40 get { return m_low; }
41 }
41 }
42
42
43 public int Hi {
43 public int Hi {
44 get { return m_hi; }
44 get { return m_hi; }
45 }
45 }
46
46
47 public int Size {
48 get { return m_size; }
49 }
50
47 public bool TryEnqueue(T value, out bool extend) {
51 public bool TryEnqueue(T value, out bool extend) {
48 var alloc = Interlocked.Increment(ref m_alloc) - 1;
52 var alloc = Interlocked.Increment(ref m_alloc) - 1;
49
53
50 if (alloc >= m_size) {
54 if (alloc >= m_size) {
51 extend = alloc == m_size;
55 extend = alloc == m_size;
52 return false;
56 return false;
53 }
57 }
54
58
55 extend = false;
59 extend = false;
56 m_data[alloc] = value;
60 m_data[alloc] = value;
57
61
58 while (alloc != Interlocked.CompareExchange(ref m_hi, alloc + 1, alloc)) {
62 while (alloc != Interlocked.CompareExchange(ref m_hi, alloc + 1, alloc)) {
59 // spin wait for commit
63 // spin wait for commit
60 }
64 }
61 return true;
65 return true;
62 }
66 }
63
67
64 /// <summary>
68 /// <summary>
65 /// Prevents from allocating new space in the chunk and waits for all write operations to complete
69 /// Prevents from allocating new space in the chunk and waits for all write operations to complete
66 /// </summary>
70 /// </summary>
67 public void Commit() {
71 public void Commit() {
68 var actual = Math.Min(Interlocked.Exchange(ref m_alloc, m_size + 1), m_size);
72 var actual = Math.Min(Interlocked.Exchange(ref m_alloc, m_size + 1), m_size);
69
73
70 while (m_hi != actual)
74 while (m_hi != actual)
71 Thread.MemoryBarrier();
75 Thread.MemoryBarrier();
72 }
76 }
73
77
74 public bool TryDequeue(out T value, out bool recycle) {
78 public bool TryDequeue(out T value, out bool recycle) {
75 int low;
79 int low;
76 do {
80 do {
77 low = m_low;
81 low = m_low;
78 if (low >= m_hi) {
82 if (low >= m_hi) {
79 value = default(T);
83 value = default(T);
80 recycle = (low == m_size);
84 recycle = (low == m_size);
81 return false;
85 return false;
82 }
86 }
83 } while(low != Interlocked.CompareExchange(ref m_low, low + 1, low));
87 } while(low != Interlocked.CompareExchange(ref m_low, low + 1, low));
84
88
85 recycle = (low == m_size - 1);
89 recycle = (low == m_size - 1);
86 value = m_data[low];
90 value = m_data[low];
87
91
88 return true;
92 return true;
89 }
93 }
90
94
91 public bool TryEnqueueBatch(T[] batch, int offset, int length, out int enqueued, out bool extend) {
95 public bool TryEnqueueBatch(T[] batch, int offset, int length, out int enqueued, out bool extend) {
92 //int alloc;
96 //int alloc;
93 //int allocSize;
97 //int allocSize;
94
98
95 var alloc = Interlocked.Add(ref m_alloc, length) - length;
99 var alloc = Interlocked.Add(ref m_alloc, length) - length;
96 if (alloc > m_size) {
100 if (alloc > m_size) {
97 // the chunk is full and someone already
101 // the chunk is full and someone already
98 // creating the new one
102 // creating the new one
99 enqueued = 0; // nothing was added
103 enqueued = 0; // nothing was added
100 extend = false; // the caller shouldn't try to extend the queue
104 extend = false; // the caller shouldn't try to extend the queue
101 return false; // nothing was added
105 return false; // nothing was added
102 }
106 }
103
107
104 enqueued = Math.Min(m_size - alloc, length);
108 enqueued = Math.Min(m_size - alloc, length);
105 extend = length > enqueued;
109 extend = length > enqueued;
106
110
107 if (enqueued == 0)
111 if (enqueued == 0)
108 return false;
112 return false;
109
113
110
114
111 Array.Copy(batch, offset, m_data, alloc, enqueued);
115 Array.Copy(batch, offset, m_data, alloc, enqueued);
112
116
113 while (alloc != Interlocked.CompareExchange(ref m_hi, alloc + enqueued, alloc)) {
117 while (alloc != Interlocked.CompareExchange(ref m_hi, alloc + enqueued, alloc)) {
114 // spin wait for commit
118 // spin wait for commit
115 }
119 }
116
120
117 return true;
121 return true;
118 }
122 }
119
123
120 public bool TryDequeueBatch(T[] buffer, int offset, int length,out int dequeued, out bool recycle) {
124 public bool TryDequeueBatch(T[] buffer, int offset, int length,out int dequeued, out bool recycle) {
121 int low, hi, batchSize;
125 int low, hi, batchSize;
122
126
123 do {
127 do {
124 low = m_low;
128 low = m_low;
125 hi = m_hi;
129 hi = m_hi;
126 if (low >= hi) {
130 if (low >= hi) {
127 dequeued = 0;
131 dequeued = 0;
128 recycle = (low == m_size); // recycling could be restarted and we need to signal again
132 recycle = (low == m_size); // recycling could be restarted and we need to signal again
129 return false;
133 return false;
130 }
134 }
131 batchSize = Math.Min(hi - low, length);
135 batchSize = Math.Min(hi - low, length);
132 } while(low != Interlocked.CompareExchange(ref m_low, low + batchSize, low));
136 } while(low != Interlocked.CompareExchange(ref m_low, low + batchSize, low));
133
137
134 recycle = (low == m_size - batchSize);
138 recycle = (low == m_size - batchSize);
135 dequeued = batchSize;
139 dequeued = batchSize;
136
140
137 Array.Copy(m_data, low, buffer, offset, batchSize);
141 Array.Copy(m_data, low, buffer, offset, batchSize);
138
142
139 return true;
143 return true;
140 }
144 }
141
145
142 public T GetAt(int pos) {
146 public T GetAt(int pos) {
143 return m_data[pos];
147 return m_data[pos];
144 }
148 }
145 }
149 }
146
150
147 public const int DEFAULT_CHUNK_SIZE = 32;
151 public const int DEFAULT_CHUNK_SIZE = 32;
148 public const int MAX_CHUNK_SIZE = 262144;
152 public const int MAX_CHUNK_SIZE = 262144;
149
153
150 Chunk m_first;
154 Chunk m_first;
151 Chunk m_last;
155 Chunk m_last;
152
156
153 /// <summary>
157 /// <summary>
154 /// Adds the specified value to the queue.
158 /// Adds the specified value to the queue.
155 /// </summary>
159 /// </summary>
156 /// <param name="value">Tha value which will be added to the queue.</param>
160 /// <param name="value">Tha value which will be added to the queue.</param>
157 public void Enqueue(T value) {
161 public void Enqueue(T value) {
158 var last = m_last;
162 var last = m_last;
159 // spin wait to the new chunk
163 // spin wait to the new chunk
160 bool extend = true;
164 bool extend = true;
161 while (last == null || !last.TryEnqueue(value, out extend)) {
165 while (last == null || !last.TryEnqueue(value, out extend)) {
162 // try to extend queue
166 // try to extend queue
163 if (extend || last == null) {
167 if (extend || last == null) {
164 var chunk = new Chunk(DEFAULT_CHUNK_SIZE, value);
168 var chunk = new Chunk(DEFAULT_CHUNK_SIZE, value);
165 if (EnqueueChunk(last, chunk))
169 if (EnqueueChunk(last, chunk))
166 break; // success! exit!
170 break; // success! exit!
167 last = m_last;
171 last = m_last;
168 } else {
172 } else {
169 while (last == m_last) {
173 while (last == m_last) {
170 Thread.MemoryBarrier();
174 Thread.MemoryBarrier();
171 }
175 }
172 last = m_last;
176 last = m_last;
173 }
177 }
174 }
178 }
175 }
179 }
176
180
177 /// <summary>
181 /// <summary>
178 /// Adds the specified data to the queue.
182 /// Adds the specified data to the queue.
179 /// </summary>
183 /// </summary>
180 /// <param name="data">The buffer which contains the data to be enqueued.</param>
184 /// <param name="data">The buffer which contains the data to be enqueued.</param>
181 /// <param name="offset">The offset of the data in the buffer.</param>
185 /// <param name="offset">The offset of the data in the buffer.</param>
182 /// <param name="length">The size of the data to read from the buffer.</param>
186 /// <param name="length">The size of the data to read from the buffer.</param>
183 public void EnqueueRange(T[] data, int offset, int length) {
187 public void EnqueueRange(T[] data, int offset, int length) {
184 if (data == null)
188 if (data == null)
185 throw new ArgumentNullException("data");
189 throw new ArgumentNullException("data");
186 if (offset < 0)
190 if (offset < 0)
187 throw new ArgumentOutOfRangeException("offset");
191 throw new ArgumentOutOfRangeException("offset");
188 if (length < 1 || offset + length > data.Length)
192 if (length < 1 || offset + length > data.Length)
189 throw new ArgumentOutOfRangeException("length");
193 throw new ArgumentOutOfRangeException("length");
190
194
191 var last = m_last;
195 var last = m_last;
192
196
193 bool extend;
197 bool extend;
194 int enqueued;
198 int enqueued;
195
199
196 while (length > 0) {
200 while (length > 0) {
197 extend = true;
201 extend = true;
198 if (last != null && last.TryEnqueueBatch(data, offset, length, out enqueued, out extend)) {
202 if (last != null && last.TryEnqueueBatch(data, offset, length, out enqueued, out extend)) {
199 length -= enqueued;
203 length -= enqueued;
200 offset += enqueued;
204 offset += enqueued;
201 }
205 }
202
206
203 if (extend) {
207 if (extend) {
204 // there was no enough space in the chunk
208 // there was no enough space in the chunk
205 // or there was no chunks in the queue
209 // or there was no chunks in the queue
206
210
207 while (length > 0) {
211 while (length > 0) {
208
212
209 var size = Math.Min(length, MAX_CHUNK_SIZE);
213 var size = Math.Min(length, MAX_CHUNK_SIZE);
210
214
211 var chunk = new Chunk(
215 var chunk = new Chunk(
212 Math.Max(size, DEFAULT_CHUNK_SIZE),
216 Math.Max(size, DEFAULT_CHUNK_SIZE),
213 data,
217 data,
214 offset,
218 offset,
215 size,
219 size,
216 length // length >= size
220 length // length >= size
217 );
221 );
218
222
219 if (!EnqueueChunk(last, chunk)) {
223 if (!EnqueueChunk(last, chunk)) {
220 // looks like the queue has been updated then proceed from the beginning
224 // looks like the queue has been updated then proceed from the beginning
221 last = m_last;
225 last = m_last;
222 break;
226 break;
223 }
227 }
224
228
225 // we have successfully added the new chunk
229 // we have successfully added the new chunk
226 last = chunk;
230 last = chunk;
227 length -= size;
231 length -= size;
228 offset += size;
232 offset += size;
229 }
233 }
230 } else {
234 } else {
231 // we don't need to extend the queue, if we successfully enqueued data
235 // we don't need to extend the queue, if we successfully enqueued data
232 if (length == 0)
236 if (length == 0)
233 break;
237 break;
234
238
235 // if we need to wait while someone is extending the queue
239 // if we need to wait while someone is extending the queue
236 // spinwait
240 // spinwait
237 while (last == m_last) {
241 while (last == m_last) {
238 Thread.MemoryBarrier();
242 Thread.MemoryBarrier();
239 }
243 }
240
244
241 last = m_last;
245 last = m_last;
242 }
246 }
243 }
247 }
244 }
248 }
245
249
246 /// <summary>
250 /// <summary>
247 /// Tries to retrieve the first element from the queue.
251 /// Tries to retrieve the first element from the queue.
248 /// </summary>
252 /// </summary>
249 /// <returns><c>true</c>, if element is dequeued, <c>false</c> otherwise.</returns>
253 /// <returns><c>true</c>, if element is dequeued, <c>false</c> otherwise.</returns>
250 /// <param name="value">The value of the dequeued element.</param>
254 /// <param name="value">The value of the dequeued element.</param>
251 public bool TryDequeue(out T value) {
255 public bool TryDequeue(out T value) {
252 var chunk = m_first;
256 var chunk = m_first;
253 bool recycle;
257 bool recycle;
254 while (chunk != null) {
258 while (chunk != null) {
255
259
256 var result = chunk.TryDequeue(out value, out recycle);
260 var result = chunk.TryDequeue(out value, out recycle);
257
261
258 if (recycle) // this chunk is waste
262 if (recycle) // this chunk is waste
259 RecycleFirstChunk(chunk);
263 RecycleFirstChunk(chunk);
260 else
264 else
261 return result; // this chunk is usable and returned actual result
265 return result; // this chunk is usable and returned actual result
262
266
263 if (result) // this chunk is waste but the true result is always actual
267 if (result) // this chunk is waste but the true result is always actual
264 return true;
268 return true;
265
269
266 // try again
270 // try again
267 chunk = m_first;
271 chunk = m_first;
268 }
272 }
269
273
270 // the queue is empty
274 // the queue is empty
271 value = default(T);
275 value = default(T);
272 return false;
276 return false;
273 }
277 }
274
278
275 /// <summary>
279 /// <summary>
276 /// Tries to dequeue the specified amount of data from the queue.
280 /// Tries to dequeue the specified amount of data from the queue.
277 /// </summary>
281 /// </summary>
278 /// <returns><c>true</c>, if data was deuqueued, <c>false</c> otherwise.</returns>
282 /// <returns><c>true</c>, if data was deuqueued, <c>false</c> otherwise.</returns>
279 /// <param name="buffer">The buffer to which the data will be written.</param>
283 /// <param name="buffer">The buffer to which the data will be written.</param>
280 /// <param name="offset">The offset in the buffer at which the data will be written.</param>
284 /// <param name="offset">The offset in the buffer at which the data will be written.</param>
281 /// <param name="length">The maximum amount of data to be retrieved.</param>
285 /// <param name="length">The maximum amount of data to be retrieved.</param>
282 /// <param name="dequeued">The actual amout of the retrieved data.</param>
286 /// <param name="dequeued">The actual amout of the retrieved data.</param>
283 public bool TryDequeueRange(T[] buffer, int offset, int length, out int dequeued) {
287 public bool TryDequeueRange(T[] buffer, int offset, int length, out int dequeued) {
284 if (buffer == null)
288 if (buffer == null)
285 throw new ArgumentNullException("buffer");
289 throw new ArgumentNullException("buffer");
286 if (offset < 0)
290 if (offset < 0)
287 throw new ArgumentOutOfRangeException("offset");
291 throw new ArgumentOutOfRangeException("offset");
288 if (length < 1 || offset + length > buffer.Length)
292 if (length < 1 || offset + length > buffer.Length)
289 throw new ArgumentOutOfRangeException("length");
293 throw new ArgumentOutOfRangeException("length");
290
294
291 var chunk = m_first;
295 var chunk = m_first;
292 bool recycle;
296 bool recycle;
293 dequeued = 0;
297 dequeued = 0;
294 while (chunk != null) {
298 while (chunk != null) {
295
299
296 int actual;
300 int actual;
297 if (chunk.TryDequeueBatch(buffer, offset, length, out actual, out recycle)) {
301 if (chunk.TryDequeueBatch(buffer, offset, length, out actual, out recycle)) {
298 offset += actual;
302 offset += actual;
299 length -= actual;
303 length -= actual;
300 dequeued += actual;
304 dequeued += actual;
301 }
305 }
302
306
303 if (recycle) // this chunk is waste
307 if (recycle) // this chunk is waste
304 RecycleFirstChunk(chunk);
308 RecycleFirstChunk(chunk);
305 else if (actual == 0)
309 else if (actual == 0)
306 break; // the chunk is usable, but doesn't contain any data (it's the last chunk in the queue)
310 break; // the chunk is usable, but doesn't contain any data (it's the last chunk in the queue)
307
311
308 if (length == 0)
312 if (length == 0)
309 return true;
313 return true;
310
314
311 // we still may dequeue something
315 // we still may dequeue something
312 // try again
316 // try again
313 chunk = m_first;
317 chunk = m_first;
314 }
318 }
315
319
316 return dequeued != 0;
320 return dequeued != 0;
317 }
321 }
318
322
319 /// <summary>
323 /// <summary>
320 /// Tries to dequeue all remaining data in the first chunk.
324 /// Tries to dequeue all remaining data in the first chunk.
321 /// </summary>
325 /// </summary>
322 /// <returns><c>true</c>, if data was dequeued, <c>false</c> otherwise.</returns>
326 /// <returns><c>true</c>, if data was dequeued, <c>false</c> otherwise.</returns>
323 /// <param name="buffer">The buffer to which the data will be written.</param>
327 /// <param name="buffer">The buffer to which the data will be written.</param>
324 /// <param name="offset">The offset in the buffer at which the data will be written.</param>
328 /// <param name="offset">The offset in the buffer at which the data will be written.</param>
325 /// <param name="length">Tha maximum amount of the data to be dequeued.</param>
329 /// <param name="length">Tha maximum amount of the data to be dequeued.</param>
326 /// <param name="dequeued">The actual amount of the dequeued data.</param>
330 /// <param name="dequeued">The actual amount of the dequeued data.</param>
327 public bool TryDequeueChunk(T[] buffer, int offset, int length, out int dequeued) {
331 public bool TryDequeueChunk(T[] buffer, int offset, int length, out int dequeued) {
328 if (buffer == null)
332 if (buffer == null)
329 throw new ArgumentNullException("buffer");
333 throw new ArgumentNullException("buffer");
330 if (offset < 0)
334 if (offset < 0)
331 throw new ArgumentOutOfRangeException("offset");
335 throw new ArgumentOutOfRangeException("offset");
332 if (length < 1 || offset + length > buffer.Length)
336 if (length < 1 || offset + length > buffer.Length)
333 throw new ArgumentOutOfRangeException("length");
337 throw new ArgumentOutOfRangeException("length");
334
338
335 var chunk = m_first;
339 var chunk = m_first;
336 bool recycle;
340 bool recycle;
337 dequeued = 0;
341 dequeued = 0;
338
342
339 while (chunk != null) {
343 while (chunk != null) {
340
344
341 int actual;
345 int actual;
342 if (chunk.TryDequeueBatch(buffer, offset, length, out actual, out recycle)) {
346 if (chunk.TryDequeueBatch(buffer, offset, length, out actual, out recycle)) {
343 dequeued = actual;
347 dequeued = actual;
344 }
348 }
345
349
346 if (recycle) // this chunk is waste
350 if (recycle) // this chunk is waste
347 RecycleFirstChunk(chunk);
351 RecycleFirstChunk(chunk);
348
352
349 // if we have dequeued any data, then return
353 // if we have dequeued any data, then return
350 if (dequeued != 0)
354 if (dequeued != 0)
351 return true;
355 return true;
352
356
353 // we still may dequeue something
357 // we still may dequeue something
354 // try again
358 // try again
355 chunk = m_first;
359 chunk = m_first;
356 }
360 }
357
361
358 return false;
362 return false;
359 }
363 }
360
364
361 bool EnqueueChunk(Chunk last, Chunk chunk) {
365 bool EnqueueChunk(Chunk last, Chunk chunk) {
362 if (Interlocked.CompareExchange(ref m_last, chunk, last) != last)
366 if (Interlocked.CompareExchange(ref m_last, chunk, last) != last)
363 return false;
367 return false;
364
368
365 if (last != null)
369 if (last != null)
366 last.next = chunk;
370 last.next = chunk;
367 else {
371 else {
368 m_first = chunk;
372 m_first = chunk;
369 }
373 }
370 return true;
374 return true;
371 }
375 }
372
376
373 void RecycleFirstChunk(Chunk first) {
377 void RecycleFirstChunk(Chunk first) {
374 var next = first.next;
378 var next = first.next;
375
379
376 if (first != Interlocked.CompareExchange(ref m_first, next, first))
380 if (first != Interlocked.CompareExchange(ref m_first, next, first))
377 return;
381 return;
378
382
379 if (next == null) {
383 if (next == null) {
380
384
381 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
385 if (first != Interlocked.CompareExchange(ref m_last, null, first)) {
382 /*while (first.next == null)
386 /*while (first.next == null)
383 Thread.MemoryBarrier();*/
387 Thread.MemoryBarrier();*/
384
388
385 // race
389 // race
386 // someone already updated the tail, restore the pointer to the queue head
390 // someone already updated the tail, restore the pointer to the queue head
387 m_first = first;
391 m_first = first;
388 }
392 }
389 // the tail is updated
393 // the tail is updated
390 }
394 }
391
395
392 // we need to update the head
396 // we need to update the head
393 //Interlocked.CompareExchange(ref m_first, next, first);
397 //Interlocked.CompareExchange(ref m_first, next, first);
394 // if the head is already updated then give up
398 // if the head is already updated then give up
395 //return;
399 //return;
396
400
397 }
401 }
398
402
399 public void Clear() {
403 public void Clear() {
400 // start the new queue
404 // start the new queue
401 var chunk = new Chunk(DEFAULT_CHUNK_SIZE);
405 var chunk = new Chunk(DEFAULT_CHUNK_SIZE);
402
406
403 do {
407 do {
404 Thread.MemoryBarrier();
408 Thread.MemoryBarrier();
405 var first = m_first;
409 var first = m_first;
406 var last = m_last;
410 var last = m_last;
407
411
408 if (last == null) // nothing to clear
412 if (last == null) // nothing to clear
409 return;
413 return;
410
414
411 if (first == null || (first.next == null && first != last)) // inconcistency
415 if (first == null || (first.next == null && first != last)) // inconcistency
412 continue;
416 continue;
413
417
414 // here we will create inconsistency which will force others to spin
418 // here we will create inconsistency which will force others to spin
415 // and prevent from fetching. chunk.next = null
419 // and prevent from fetching. chunk.next = null
416 if (first != Interlocked.CompareExchange(ref m_first, chunk, first))
420 if (first != Interlocked.CompareExchange(ref m_first, chunk, first))
417 continue;// inconsistent
421 continue;// inconsistent
418
422
419 m_last = chunk;
423 m_last = chunk;
420
424
421 return;
425 return;
422
426
423 } while(true);
427 } while(true);
424 }
428 }
425
429
426 public T[] Drain() {
430 public T[] Drain() {
427 // start the new queue
431 // start the new queue
428 var chunk = new Chunk(DEFAULT_CHUNK_SIZE);
432 var chunk = new Chunk(DEFAULT_CHUNK_SIZE);
429
433
430 do {
434 do {
431 Thread.MemoryBarrier();
435 Thread.MemoryBarrier();
432 var first = m_first;
436 var first = m_first;
433 var last = m_last;
437 var last = m_last;
434
438
435 if (last == null)
439 if (last == null)
436 return new T[0];
440 return new T[0];
437
441
438 if (first == null || (first.next == null && first != last))
442 if (first == null || (first.next == null && first != last))
439 continue;
443 continue;
440
444
441 // here we will create inconsistency which will force others to spin
445 // here we will create inconsistency which will force others to spin
442 // and prevent from fetching. chunk.next = null
446 // and prevent from fetching. chunk.next = null
443 if (first != Interlocked.CompareExchange(ref m_first, chunk, first))
447 if (first != Interlocked.CompareExchange(ref m_first, chunk, first))
444 continue;// inconsistent
448 continue;// inconsistent
445
449
446 last = Interlocked.Exchange(ref m_last, chunk);
450 last = Interlocked.Exchange(ref m_last, chunk);
447
451
448 return ReadChunks(first, last);
452 return ReadChunks(first, last);
449
453
450 } while(true);
454 } while(true);
451 }
455 }
452
456
453 T[] ReadChunks(Chunk chunk, object last) {
457 T[] ReadChunks(Chunk chunk, object last) {
454 var result = new List<T>();
458 var result = new List<T>();
455 var buffer = new T[DEFAULT_CHUNK_SIZE];
459 var buffer = new T[DEFAULT_CHUNK_SIZE];
456 int actual;
460 int actual;
457 bool recycle;
461 bool recycle;
458 while (chunk != null) {
462 while (chunk != null) {
459 // ensure all write operations on the chunk are complete
463 // ensure all write operations on the chunk are complete
460 chunk.Commit();
464 chunk.Commit();
461
465
462 // we need to read the chunk using this way
466 // we need to read the chunk using this way
463 // since some client still may completing the dequeue
467 // since some client still may completing the dequeue
464 // operation, such clients most likely won't get results
468 // operation, such clients most likely won't get results
465 while (chunk.TryDequeueBatch(buffer, 0, buffer.Length, out actual, out recycle))
469 while (chunk.TryDequeueBatch(buffer, 0, buffer.Length, out actual, out recycle))
466 result.AddRange(new ArraySegmentCollection(buffer, 0, actual));
470 result.AddRange(new ArraySegmentCollection(buffer, 0, actual));
467
471
468 if (chunk == last) {
472 if (chunk == last) {
469 chunk = null;
473 chunk = null;
470 } else {
474 } else {
471 while (chunk.next == null)
475 while (chunk.next == null)
472 Thread.MemoryBarrier();
476 Thread.MemoryBarrier();
473 chunk = chunk.next;
477 chunk = chunk.next;
474 }
478 }
475 }
479 }
476
480
477 return result.ToArray();
481 return result.ToArray();
478 }
482 }
479
483
480 struct ArraySegmentCollection : ICollection<T> {
484 struct ArraySegmentCollection : ICollection<T> {
481 readonly T[] m_data;
485 readonly T[] m_data;
482 readonly int m_offset;
486 readonly int m_offset;
483 readonly int m_length;
487 readonly int m_length;
484
488
485 public ArraySegmentCollection(T[] data, int offset, int length) {
489 public ArraySegmentCollection(T[] data, int offset, int length) {
486 m_data = data;
490 m_data = data;
487 m_offset = offset;
491 m_offset = offset;
488 m_length = length;
492 m_length = length;
489 }
493 }
490
494
491 #region ICollection implementation
495 #region ICollection implementation
492
496
493 public void Add(T item) {
497 public void Add(T item) {
494 throw new InvalidOperationException();
498 throw new InvalidOperationException();
495 }
499 }
496
500
497 public void Clear() {
501 public void Clear() {
498 throw new InvalidOperationException();
502 throw new InvalidOperationException();
499 }
503 }
500
504
501 public bool Contains(T item) {
505 public bool Contains(T item) {
502 return false;
506 return false;
503 }
507 }
504
508
505 public void CopyTo(T[] array, int arrayIndex) {
509 public void CopyTo(T[] array, int arrayIndex) {
506 Array.Copy(m_data,m_offset,array,arrayIndex, m_length);
510 Array.Copy(m_data,m_offset,array,arrayIndex, m_length);
507 }
511 }
508
512
509 public bool Remove(T item) {
513 public bool Remove(T item) {
510 throw new NotImplementedException();
514 throw new NotImplementedException();
511 }
515 }
512
516
513 public int Count {
517 public int Count {
514 get {
518 get {
515 return m_length;
519 return m_length;
516 }
520 }
517 }
521 }
518
522
519 public bool IsReadOnly {
523 public bool IsReadOnly {
520 get {
524 get {
521 return true;
525 return true;
522 }
526 }
523 }
527 }
524
528
525 #endregion
529 #endregion
526
530
527 #region IEnumerable implementation
531 #region IEnumerable implementation
528
532
529 public IEnumerator<T> GetEnumerator() {
533 public IEnumerator<T> GetEnumerator() {
530 for (int i = m_offset; i < m_length + m_offset; i++)
534 for (int i = m_offset; i < m_length + m_offset; i++)
531 yield return m_data[i];
535 yield return m_data[i];
532 }
536 }
533
537
534 #endregion
538 #endregion
535
539
536 #region IEnumerable implementation
540 #region IEnumerable implementation
537
541
538 IEnumerator IEnumerable.GetEnumerator() {
542 IEnumerator IEnumerable.GetEnumerator() {
539 return GetEnumerator();
543 return GetEnumerator();
540 }
544 }
541
545
542 #endregion
546 #endregion
543 }
547 }
544
548
545 #region IEnumerable implementation
549 #region IEnumerable implementation
546
550
547 class Enumerator : IEnumerator<T> {
551 class Enumerator : IEnumerator<T> {
548 Chunk m_current;
552 Chunk m_current;
549 int m_pos = -1;
553 int m_pos = -1;
550
554
551 public Enumerator(Chunk fisrt) {
555 public Enumerator(Chunk fisrt) {
552 m_current = fisrt;
556 m_current = fisrt;
553 }
557 }
554
558
555 #region IEnumerator implementation
559 #region IEnumerator implementation
556
560
557 public bool MoveNext() {
561 public bool MoveNext() {
558 if (m_current == null)
562 if (m_current == null)
559 return false;
563 return false;
560
564
561 if (m_pos == -1)
565 if (m_pos == -1)
562 m_pos = m_current.Low;
566 m_pos = m_current.Low;
563 else
567 else
564 m_pos++;
568 m_pos++;
569
565 if (m_pos == m_current.Hi) {
570 if (m_pos == m_current.Hi) {
571
572 m_current = m_pos == m_current.Size ? m_current.next : null;
573
566 m_pos = 0;
574 m_pos = 0;
567 m_current = m_current.next;
575
576 if (m_current == null)
577 return false;
568 }
578 }
569
579
570 return true;
580 return true;
571 }
581 }
572
582
573 public void Reset() {
583 public void Reset() {
574 throw new NotSupportedException();
584 throw new NotSupportedException();
575 }
585 }
576
586
577 object IEnumerator.Current {
587 object IEnumerator.Current {
578 get {
588 get {
579 return Current;
589 return Current;
580 }
590 }
581 }
591 }
582
592
583 #endregion
593 #endregion
584
594
585 #region IDisposable implementation
595 #region IDisposable implementation
586
596
587 public void Dispose() {
597 public void Dispose() {
588 }
598 }
589
599
590 #endregion
600 #endregion
591
601
592 #region IEnumerator implementation
602 #region IEnumerator implementation
593
603
594 public T Current {
604 public T Current {
595 get {
605 get {
596 if (m_pos == -1 || m_current == null)
606 if (m_pos == -1 || m_current == null)
597 throw new InvalidOperationException();
607 throw new InvalidOperationException();
598 return m_current.GetAt(m_pos);
608 return m_current.GetAt(m_pos);
599 }
609 }
600 }
610 }
601
611
602 #endregion
612 #endregion
603 }
613 }
604
614
605 public IEnumerator<T> GetEnumerator() {
615 public IEnumerator<T> GetEnumerator() {
606 return new Enumerator(m_first);
616 return new Enumerator(m_first);
607 }
617 }
608
618
609 #endregion
619 #endregion
610
620
611 #region IEnumerable implementation
621 #region IEnumerable implementation
612
622
613 IEnumerator IEnumerable.GetEnumerator() {
623 IEnumerator IEnumerable.GetEnumerator() {
614 return GetEnumerator();
624 return GetEnumerator();
615 }
625 }
616
626
617 #endregion
627 #endregion
618 }
628 }
619 }
629 }
General Comments 0
You need to be logged in to leave comments. Login now