Skip to content

Commit c9b7a07

Browse files
committed
Implemented some safety mechanisms
1 parent 4f902dd commit c9b7a07

2 files changed

Lines changed: 46 additions & 3 deletions

File tree

ConsoleTest/Program.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,9 @@ public struct Numpy: IPythonModule<Numpy>
1717

1818
private static async Task Main(string[] args)
1919
{
20-
var core = PythonCore<PyVer3_11, DefaultPythonConfig>.INSTANCE;
21-
await core.InitializeAsync();
22-
await core.InitializeDependentPackages();
20+
var pythonCore = PythonCore<PyVer3_11, DefaultPythonConfig>.INSTANCE;
21+
await pythonCore.InitializeAsync();
22+
await pythonCore.InitializeDependentPackages();
2323

2424
using (new PythonHandle())
2525
{

PythonNETExtensions/Core/PythonCore.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.Reflection;
88
using System.Runtime.CompilerServices;
99
using System.Text.Json;
10+
using System.Threading;
1011
using System.Threading.Tasks;
1112
using Python.Runtime;
1213
using PythonNETExtensions.Helpers;
@@ -16,15 +17,50 @@
1617

1718
namespace PythonNETExtensions.Core
1819
{
20+
internal static class PythonInstance
21+
{
22+
private static int InstanceCount = 0;
23+
24+
public static void OnCreate()
25+
{
26+
if (Interlocked.Increment(ref InstanceCount) == 1)
27+
{
28+
return;
29+
}
30+
31+
throw new Exception("There may only be 1 PythonCore instance!");
32+
}
33+
}
34+
1935
public class PythonCore<PyVersionT, PyConfigT>
2036
where PyVersionT: struct, IPythonVersion<PyVersionT>
2137
where PyConfigT: struct, IPythonConfig<PyConfigT>
2238
{
2339
public static readonly PythonCore<PyVersionT, PyConfigT> INSTANCE = new PythonCore<PyVersionT, PyConfigT>();
2440

41+
static PythonCore()
42+
{
43+
PythonInstance.OnCreate();
44+
}
45+
2546
private PythonCore() { }
2647

2748
private static readonly HttpClient HTTP_CLIENT = new HttpClient();
49+
50+
private enum InitializationState: int
51+
{
52+
Uninitialized = 0,
53+
Initialized = -1
54+
}
55+
56+
private static int IsInitialized = (int) InitializationState.Uninitialized;
57+
58+
private static bool TryInitialize()
59+
{
60+
var oldVal = (InitializationState) Interlocked.CompareExchange(ref IsInitialized, (int) InitializationState.Initialized, (int) InitializationState.Uninitialized);
61+
62+
return oldVal == InitializationState.Uninitialized;
63+
}
2864

2965
public Task InitializeAsync()
3066
{
@@ -36,6 +72,8 @@ public Task InitializeAsync()
3672
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
3773
private static async Task InitializeAsyncInternal()
3874
{
75+
TryInitialize();
76+
3977
var pythonBundleDirectory = PyConfigT.PythonHomePath;
4078

4179
if (Directory.Exists(pythonBundleDirectory))
@@ -97,6 +135,11 @@ public Task InitializeDependentPackages()
97135
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
98136
private static async Task InitializeDependentPackagesInternal()
99137
{
138+
if ((InitializationState) IsInitialized == InitializationState.Uninitialized)
139+
{
140+
throw new Exception($"Please run {nameof(InitializeAsync)}() first!");
141+
}
142+
100143
// Apparently this causes stackoverflow when PythonExtensions.GetCachedPythonModule<>() is invoked...
101144
// // TODO: Consider asynchronous awaiting of pip process
102145
// await Task.Yield();

0 commit comments

Comments
 (0)