Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
jobily
CommunityToolkit.Dotnet
提交
91fdb777
C
CommunityToolkit.Dotnet
项目概览
jobily
/
CommunityToolkit.Dotnet
9 个月 前同步成功
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
C
CommunityToolkit.Dotnet
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
91fdb777
编写于
5月 16, 2023
作者:
S
Sergio Pedri
提交者:
GitHub
5月 16, 2023
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #701 from CommunityToolkit/dev/generator-array-pool
Improve ImmutableArrayBuilder<T> type in MVVM Toolkit generators
上级
eef21e2c
d2f77a94
变更
3
隐藏空白更改
内联
并排
Showing
3 changed file
with
29 addition
and
206 deletion
+29
-206
src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
...nerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
+0
-1
src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/ImmutableArrayBuilder{T}.cs
...Mvvm.SourceGenerators/Helpers/ImmutableArrayBuilder{T}.cs
+29
-42
src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/ObjectPool{T}.cs
...ityToolkit.Mvvm.SourceGenerators/Helpers/ObjectPool{T}.cs
+0
-163
未找到文件。
src/CommunityToolkit.Mvvm.SourceGenerators/CommunityToolkit.Mvvm.SourceGenerators.projitems
浏览文件 @
91fdb777
...
...
@@ -67,7 +67,6 @@
<Compile
Include=
"$(MSBuildThisFileDirectory)Helpers\EquatableArray{T}.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Helpers\HashCode.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Helpers\ImmutableArrayBuilder{T}.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Helpers\ObjectPool{T}.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Input\Models\CanExecuteExpressionType.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Input\Models\CommandInfo.cs"
/>
<Compile
Include=
"$(MSBuildThisFileDirectory)Input\RelayCommandGenerator.cs"
/>
...
...
src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/ImmutableArrayBuilder{T}.cs
浏览文件 @
91fdb777
...
...
@@ -6,7 +6,9 @@
// more info in ThirdPartyNotices.txt in the root of the project.
using
System
;
using
System.Buffers
;
using
System.Collections.Immutable
;
using
System.Diagnostics.CodeAnalysis
;
using
System.Runtime.CompilerServices
;
namespace
CommunityToolkit.Mvvm.SourceGenerators.Helpers
;
...
...
@@ -15,13 +17,8 @@ namespace CommunityToolkit.Mvvm.SourceGenerators.Helpers;
/// A helper type to build sequences of values with pooled buffers.
/// </summary>
/// <typeparam name="T">The type of items to create sequences for.</typeparam>
internal
struct
ImmutableArrayBuilder
<
T
>
:
IDisposable
internal
ref
struct
ImmutableArrayBuilder
<
T
>
{
/// <summary>
/// The shared <see cref="ObjectPool{T}"/> instance to share <see cref="Writer"/> objects.
/// </summary>
private
static
readonly
ObjectPool
<
Writer
>
SharedObjectPool
=
new
(
static
()
=>
new
Writer
());
/// <summary>
/// The rented <see cref="Writer"/> instance to use.
/// </summary>
...
...
@@ -33,7 +30,7 @@ internal struct ImmutableArrayBuilder<T> : IDisposable
/// <returns>A <see cref="ImmutableArrayBuilder{T}"/> instance to write data to.</returns>
public
static
ImmutableArrayBuilder
<
T
>
Rent
()
{
return
new
(
SharedObjectPool
.
Allocate
());
return
new
(
new
Writer
());
}
/// <summary>
...
...
@@ -46,7 +43,7 @@ private ImmutableArrayBuilder(Writer writer)
}
/// <inheritdoc cref="ImmutableArray{T}.Builder.Count"/>
public
int
Count
public
readonly
int
Count
{
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
get
=>
this
.
writer
!.
Count
;
...
...
@@ -55,6 +52,7 @@ public int Count
/// <summary>
/// Gets the data written to the underlying buffer so far, as a <see cref="ReadOnlySpan{T}"/>.
/// </summary>
[
UnscopedRef
]
public
readonly
ReadOnlySpan
<
T
>
WrittenSpan
{
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
...
...
@@ -71,7 +69,7 @@ public int Count
/// Adds the specified items to the end of the array.
/// </summary>
/// <param name="items">The items to add at the end of the array.</param>
public
readonly
void
AddRange
(
ReadOnlySpan
<
T
>
items
)
public
readonly
void
AddRange
(
scoped
ReadOnlySpan
<
T
>
items
)
{
this
.
writer
!.
AddRange
(
items
);
}
...
...
@@ -96,30 +94,25 @@ public int Count
return
this
.
writer
!.
WrittenSpan
.
ToString
();
}
/// <inheritdoc/>
/// <inheritdoc
cref="IDisposable.Dispose"
/>
public
void
Dispose
()
{
Writer
?
writer
=
this
.
writer
;
this
.
writer
=
null
;
if
(
writer
is
not
null
)
{
writer
.
Clear
();
SharedObjectPool
.
Free
(
writer
);
}
writer
?.
Dispose
();
}
/// <summary>
/// A class handling the actual buffer writing.
/// </summary>
private
sealed
class
Writer
private
sealed
class
Writer
:
IDisposable
{
/// <summary>
/// The underlying <typeparamref name="T"/> array.
/// </summary>
private
T
[]
array
;
private
T
?[]?
array
;
/// <summary>
/// The starting offset within <see cref="array"/>.
...
...
@@ -131,15 +124,7 @@ private sealed class Writer
/// </summary>
public
Writer
()
{
if
(
typeof
(
T
)
==
typeof
(
char
))
{
this
.
array
=
new
T
[
1024
];
}
else
{
this
.
array
=
new
T
[
8
];
}
this
.
array
=
ArrayPool
<
T
?>.
Shared
.
Rent
(
typeof
(
T
)
==
typeof
(
char
)
?
1024
:
8
);
this
.
index
=
0
;
}
...
...
@@ -154,7 +139,7 @@ public int Count
public
ReadOnlySpan
<
T
>
WrittenSpan
{
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
get
=>
new
(
this
.
array
,
0
,
this
.
index
);
get
=>
new
(
this
.
array
!
,
0
,
this
.
index
);
}
/// <inheritdoc cref="ImmutableArrayBuilder{T}.Add"/>
...
...
@@ -162,7 +147,7 @@ public void Add(T value)
{
EnsureCapacity
(
1
);
this
.
array
[
this
.
index
++]
=
value
;
this
.
array
!
[
this
.
index
++]
=
value
;
}
/// <inheritdoc cref="ImmutableArrayBuilder{T}.AddRange"/>
...
...
@@ -170,22 +155,22 @@ public void AddRange(ReadOnlySpan<T> items)
{
EnsureCapacity
(
items
.
Length
);
items
.
CopyTo
(
this
.
array
.
AsSpan
(
this
.
index
));
items
.
CopyTo
(
this
.
array
.
AsSpan
(
this
.
index
)
!
);
this
.
index
+=
items
.
Length
;
}
/// <summary>
/// Clears the items in the current writer.
/// </summary>
public
void
Clear
()
/// <inheritdoc/>
public
void
Dispose
()
{
if
(
typeof
(
T
)
!=
typeof
(
char
))
T
?[]?
array
=
this
.
array
;
this
.
array
=
null
;
if
(
array
is
not
null
)
{
this
.
array
.
AsSpan
(
0
,
this
.
index
).
Clear
(
);
ArrayPool
<
T
?>.
Shared
.
Return
(
array
,
clearArray
:
typeof
(
T
)
!=
typeof
(
char
)
);
}
this
.
index
=
0
;
}
/// <summary>
...
...
@@ -195,7 +180,7 @@ public void Clear()
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
private
void
EnsureCapacity
(
int
requestedSize
)
{
if
(
requestedSize
>
this
.
array
.
Length
-
this
.
index
)
if
(
requestedSize
>
this
.
array
!
.
Length
-
this
.
index
)
{
ResizeBuffer
(
requestedSize
);
}
...
...
@@ -209,13 +194,15 @@ private void EnsureCapacity(int requestedSize)
private
void
ResizeBuffer
(
int
sizeHint
)
{
int
minimumSize
=
this
.
index
+
sizeHint
;
int
requestedSize
=
Math
.
Max
(
this
.
array
.
Length
*
2
,
minimumSize
);
T
[]
newArray
=
new
T
[
requestedSize
];
T
?[]
oldArray
=
this
.
array
!;
T
?[]
newArray
=
ArrayPool
<
T
?>.
Shared
.
Rent
(
minimumSize
);
Array
.
Copy
(
this
.
a
rray
,
newArray
,
this
.
index
);
Array
.
Copy
(
oldA
rray
,
newArray
,
this
.
index
);
this
.
array
=
newArray
;
ArrayPool
<
T
?>.
Shared
.
Return
(
oldArray
,
clearArray
:
typeof
(
T
)
!=
typeof
(
char
));
}
}
}
...
...
src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/ObjectPool{T}.cs
已删除
100644 → 0
浏览文件 @
eef21e2c
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Ported from Roslyn, see: https://github.com/dotnet/roslyn/blob/main/src/Dependencies/PooledObjects/ObjectPool%601.cs.
using
System
;
using
System.Runtime.CompilerServices
;
using
System.Threading
;
namespace
CommunityToolkit.Mvvm.SourceGenerators.Helpers
;
/// <summary>
/// <para>
/// Generic implementation of object pooling pattern with predefined pool size limit. The main purpose
/// is that limited number of frequently used objects can be kept in the pool for further recycling.
/// </para>
/// <para>
/// Notes:
/// <list type="number">
/// <item>
/// It is not the goal to keep all returned objects. Pool is not meant for storage. If there
/// is no space in the pool, extra returned objects will be dropped.
/// </item>
/// <item>
/// It is implied that if object was obtained from a pool, the caller will return it back in
/// a relatively short time. Keeping checked out objects for long durations is ok, but
/// reduces usefulness of pooling. Just new up your own.
/// </item>
/// </list>
/// </para>
/// <para>
/// Not returning objects to the pool in not detrimental to the pool's work, but is a bad practice.
/// Rationale: if there is no intent for reusing the object, do not use pool - just use "new".
/// </para>
/// </summary>
/// <typeparam name="T">The type of objects to pool.</typeparam>
internal
sealed
class
ObjectPool
<
T
>
where
T
:
class
{
/// <summary>
/// The factory is stored for the lifetime of the pool. We will call this only when pool needs to
/// expand. compared to "new T()", Func gives more flexibility to implementers and faster than "new T()".
/// </summary>
private
readonly
Func
<
T
>
factory
;
/// <summary>
/// The array of cached items.
/// </summary>
private
readonly
Element
[]
items
;
/// <summary>
/// Storage for the pool objects. The first item is stored in a dedicated field
/// because we expect to be able to satisfy most requests from it.
/// </summary>
private
T
?
firstItem
;
/// <summary>
/// Creates a new <see cref="ObjectPool{T}"/> instance with the specified parameters.
/// </summary>
/// <param name="factory">The input factory to produce <typeparamref name="T"/> items.</param>
public
ObjectPool
(
Func
<
T
>
factory
)
:
this
(
factory
,
Environment
.
ProcessorCount
*
2
)
{
}
/// <summary>
/// Creates a new <see cref="ObjectPool{T}"/> instance with the specified parameters.
/// </summary>
/// <param name="factory">The input factory to produce <typeparamref name="T"/> items.</param>
/// <param name="size">The pool size to use.</param>
public
ObjectPool
(
Func
<
T
>
factory
,
int
size
)
{
this
.
factory
=
factory
;
this
.
items
=
new
Element
[
size
-
1
];
}
/// <summary>
/// Produces a <typeparamref name="T"/> instance.
/// </summary>
/// <returns>The returned <typeparamref name="T"/> item to use.</returns>
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
public
T
Allocate
()
{
T
?
item
=
this
.
firstItem
;
if
(
item
is
null
||
item
!=
Interlocked
.
CompareExchange
(
ref
this
.
firstItem
,
null
,
item
))
{
item
=
AllocateSlow
();
}
return
item
;
}
/// <summary>
/// Returns a given <typeparamref name="T"/> instance to the pool.
/// </summary>
/// <param name="obj">The <typeparamref name="T"/> instance to return.</param>
[
MethodImpl
(
MethodImplOptions
.
AggressiveInlining
)]
public
void
Free
(
T
obj
)
{
if
(
this
.
firstItem
is
null
)
{
this
.
firstItem
=
obj
;
}
else
{
FreeSlow
(
obj
);
}
}
/// <summary>
/// Allocates a new <typeparamref name="T"/> item.
/// </summary>
/// <returns>The returned <typeparamref name="T"/> item to use.</returns>
[
MethodImpl
(
MethodImplOptions
.
NoInlining
)]
private
T
AllocateSlow
()
{
foreach
(
ref
Element
element
in
this
.
items
.
AsSpan
())
{
T
?
instance
=
element
.
Value
;
if
(
instance
is
not
null
)
{
if
(
instance
==
Interlocked
.
CompareExchange
(
ref
element
.
Value
,
null
,
instance
))
{
return
instance
;
}
}
}
return
this
.
factory
();
}
/// <summary>
/// Frees a given <typeparamref name="T"/> item.
/// </summary>
/// <param name="obj">The <typeparamref name="T"/> item to return to the pool.</param>
[
MethodImpl
(
MethodImplOptions
.
NoInlining
)]
private
void
FreeSlow
(
T
obj
)
{
foreach
(
ref
Element
element
in
this
.
items
.
AsSpan
())
{
if
(
element
.
Value
is
null
)
{
element
.
Value
=
obj
;
break
;
}
}
}
/// <summary>
/// A container for a produced item (using a <see langword="struct"/> wrapper to avoid covariance checks).
/// </summary>
private
struct
Element
{
/// <summary>
/// The value held at the current element.
/// </summary>
internal
T
?
Value
;
}
}
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录