Skip to content

Commit 4f3b51a

Browse files
authored
Merge pull request #74 from Ted-Jin-Lab/development
Release
2 parents 61296c8 + beace2a commit 4f3b51a

6 files changed

Lines changed: 57 additions & 33 deletions

File tree

Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<?xml version="1.0" encoding="utf-8"?>
22
<Project>
33
<PropertyGroup>
4-
<Version>2025.11.25.0</Version>
4+
<Version>2025.12.9.0</Version>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
77
<LangVersion>preview</LangVersion>

TedToolkit.slnx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@
7474
</Folder>
7575
<Folder Name="/src/Scopes/">
7676
<Project Path="src/libraries/TedToolkit.Scopes/TedToolkit.Scopes.csproj" />
77+
<Project Path="tests/TedToolkit.Scopes.Tests/TedToolkit.Scopes.Tests.csproj" />
7778
</Folder>
7879
<Folder Name="/src/ValidResults/">
7980
<Project Path="src/analyzers/TedToolkit.ValidResults.SourceGenerator/TedToolkit.ValidResults.SourceGenerator.csproj" />
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
namespace TedToolkit.Scopes.Tests;
2+
3+
public class ScopesTests
4+
{
5+
[Test]
6+
[MatrixDataSource]
7+
public async Task ScopeCreateTest([MatrixRange<int>(-1000, 1000)]int value)
8+
{
9+
using var scope = new TestScope(value);
10+
await Task.Delay(1000);
11+
await Assert.That(TestScope.Current?.Value).IsEqualTo(value);
12+
}
13+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
<ItemGroup>
3+
<ProjectReference Include="..\..\src\libraries\TedToolkit.Scopes\TedToolkit.Scopes.csproj" />
4+
</ItemGroup>
5+
</Project>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace TedToolkit.Scopes.Tests;
2+
3+
public class TestScope(int value) : ScopeBase<TestScope>
4+
{
5+
public int Value => value;
6+
}

src/libraries/TedToolkit.CppInteropGen/NativeFunctionLoader.cs

Lines changed: 31 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,41 @@ namespace TedToolkit.CppInteropGen;
88

99
public sealed class NativeFunctionLoader : IDisposable
1010
{
11-
private static readonly ConcurrentDictionary<string, NativeFunctionLoader> Loaders = [];
12-
private readonly ConcurrentDictionary<string, IntPtr> _exportCache = new(StringComparer.Ordinal);
13-
private readonly Lazy<IntPtr> _libHandle;
14-
private bool _disposed;
11+
private static readonly ConcurrentDictionary<string, NativeFunctionLoader> Loaders = [];
12+
private readonly ConcurrentDictionary<string, IntPtr> _exportCache = new(StringComparer.Ordinal);
13+
private readonly IntPtr _libHandle;
14+
private bool _disposed;
1515

16-
private NativeFunctionLoader(string libraryPath)
17-
{
18-
_libHandle = new Lazy<IntPtr>(() =>
19-
{
20-
var handle = NativeLibrary.Load(libraryPath);
21-
if (handle != IntPtr.Zero) return handle;
22-
throw new InvalidOperationException($"Failed to load native library: {libraryPath}");
23-
});
24-
}
16+
private NativeFunctionLoader(string libraryPath)
17+
{
18+
_libHandle = NativeLibrary.Load(libraryPath);
19+
if (_libHandle != IntPtr.Zero) return;
20+
throw new InvalidOperationException($"Failed to load native library: {libraryPath}");
21+
}
2522

26-
public void Dispose()
27-
{
28-
if (_disposed) return;
29-
_disposed = true;
30-
if (_libHandle.IsValueCreated) NativeLibrary.Free(_libHandle.Value);
31-
}
23+
public void Dispose()
24+
{
25+
if (_disposed) return;
26+
_disposed = true;
27+
NativeLibrary.Free(_libHandle);
28+
}
3229

33-
internal static NativeFunctionLoader GetLoader(string libName)
34-
{
35-
if (string.IsNullOrEmpty(libName))
36-
throw new ArgumentException("The libName is null or empty.", nameof(libName));
37-
var loader = Loaders.GetOrAdd(libName, n => new NativeFunctionLoader(n));
38-
if (!loader._disposed) return loader;
39-
return Loaders[libName] = new NativeFunctionLoader(libName);
40-
}
30+
internal static NativeFunctionLoader GetLoader(string libName)
31+
{
32+
if (string.IsNullOrEmpty(libName))
33+
throw new ArgumentException("The libName is null or empty.", nameof(libName));
4134

42-
public IntPtr GetFunctionPointer(string name)
43-
{
44-
if (_disposed) throw new ObjectDisposedException(nameof(NativeFunctionLoader));
45-
return _exportCache.GetOrAdd(name, n => NativeLibrary.GetExport(_libHandle.Value, n));
46-
}
35+
return Loaders.AddOrUpdate(
36+
key: libName,
37+
addValueFactory: n => new(n),
38+
updateValueFactory: (n, existingLoader) => existingLoader._disposed ? new(n) : existingLoader);
39+
}
40+
41+
public IntPtr GetFunctionPointer(string name)
42+
{
43+
if (_disposed) throw new ObjectDisposedException(nameof(NativeFunctionLoader));
44+
return _exportCache.GetOrAdd(name, n => NativeLibrary.GetExport(_libHandle, n));
45+
}
4746
}
4847

4948
#if NETSTANDARD || NETFRAMEWORK

0 commit comments

Comments
 (0)