Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7a9e411

Browse files
committed
switched state serialization to new reference types (untested)
1 parent e295679 commit 7a9e411

17 files changed

+261
-209
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Python.Runtime.StateSerialization;
5+
6+
[Serializable]
7+
internal class ClassManagerState
8+
{
9+
public Dictionary<PyType, InterDomainContext> Contexts { get; set; }
10+
public Dictionary<MaybeType, ClassBase> Cache { get; set; }
11+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Python.Runtime.StateSerialization;
5+
6+
[Serializable]
7+
internal class ImportHookState
8+
{
9+
public PyModule PyCLRModule { get; set; }
10+
public PyObject Root { get; set; }
11+
public Dictionary<PyString, PyObject> Modules { get; set; }
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using System;
2+
3+
namespace Python.Runtime.StateSerialization;
4+
5+
[Serializable]
6+
internal class MetatypeState
7+
{
8+
public PyType CLRMetaType { get; set; }
9+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
3+
namespace Python.Runtime.StateSerialization;
4+
5+
[Serializable]
6+
internal class PythonNetState
7+
{
8+
public MetatypeState Metatype { get; set; }
9+
public SharedObjectsState SharedObjects { get; set; }
10+
public TypeManagerState Types { get; set; }
11+
public ClassManagerState Classes { get; set; }
12+
public ImportHookState ImportHookState { get; set; }
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Python.Runtime.StateSerialization;
5+
6+
[Serializable]
7+
internal class SharedObjectsState
8+
{
9+
public List<CLRObject> InternalStores { get; set; }
10+
public List<ManagedType> Extensions { get; set; }
11+
public RuntimeDataStorage Wrappers { get; set; }
12+
public Dictionary<PyObject, InterDomainContext> Contexts { get; set; }
13+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System;
2+
using System.Collections.Generic;
3+
4+
namespace Python.Runtime.StateSerialization;
5+
6+
[Serializable]
7+
internal class TypeManagerState
8+
{
9+
public Dictionary<MaybeType, PyType> Cache { get; set; }
10+
public Dictionary<MaybeType, Type> SlotImplementations { get; set; }
11+
}

src/runtime/classbase.cs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -405,8 +405,7 @@ protected override void OnSave(InterDomainContext context)
405405
if (!this.IsClrMetaTypeInstance())
406406
{
407407
BorrowedReference dict = GetObjectDict(ObjectReference);
408-
Runtime.XIncref(dict);
409-
context.Storage.AddValue("dict", dict);
408+
context.Storage.AddValue("dict", PyObject.FromNullableReference(dict));
410409
}
411410
}
412411

@@ -415,8 +414,8 @@ protected override void OnLoad(InterDomainContext context)
415414
base.OnLoad(context);
416415
if (!this.IsClrMetaTypeInstance())
417416
{
418-
IntPtr dict = context.Storage.GetValue<IntPtr>("dict");
419-
SetObjectDict(ObjectReference, dict);
417+
var dict = context.Storage.GetValue<PyObject>("dict");
418+
SetObjectDict(ObjectReference, dict.NewReferenceOrNull().StealNullable());
420419
}
421420
gcHandle = AllocGCHandle();
422421
SetGCHandle(ObjectReference, gcHandle);

src/runtime/classmanager.cs

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using System.Runtime.InteropServices;
88
using System.Security;
99

10+
using Python.Runtime.StateSerialization;
11+
1012
namespace Python.Runtime
1113
{
1214
/// <summary>
@@ -93,21 +95,16 @@ private static int TraverseTypeClear(BorrowedReference ob, IntPtr arg)
9395
return 0;
9496
}
9597

96-
internal static void SaveRuntimeData(RuntimeDataStorage storage)
98+
internal static ClassManagerState SaveRuntimeData()
9799
{
98-
var contexts = storage.AddValue("contexts",
99-
new Dictionary<PyType, InterDomainContext>(PythonReferenceComparer.Instance));
100-
storage.AddValue("cache", cache);
100+
var contexts = new Dictionary<PyType, InterDomainContext>(PythonReferenceComparer.Instance);
101101
foreach (var cls in cache)
102102
{
103103
if (!cls.Key.Valid)
104104
{
105105
// Don't serialize an invalid class
106106
continue;
107107
}
108-
// This incref is for cache to hold the cls,
109-
// thus no need for decreasing it at RestoreRuntimeData.
110-
Runtime.XIncref(cls.Value.pyHandle);
111108
var context = contexts[cls.Value.pyHandle] = new InterDomainContext();
112109
cls.Value.Save(context);
113110

@@ -137,13 +134,19 @@ internal static void SaveRuntimeData(RuntimeDataStorage storage)
137134
// We modified the Type object, notify it we did.
138135
Runtime.PyType_Modified(cls.Value.TypeReference);
139136
}
137+
138+
return new()
139+
{
140+
Contexts = contexts,
141+
Cache = cache,
142+
};
140143
}
141144

142-
internal static Dictionary<ManagedType, InterDomainContext> RestoreRuntimeData(RuntimeDataStorage storage)
145+
internal static Dictionary<ManagedType, InterDomainContext> RestoreRuntimeData(ClassManagerState storage)
143146
{
144-
cache = storage.GetValue<Dictionary<MaybeType, ClassBase>>("cache");
147+
cache = storage.Cache;
145148
var invalidClasses = new List<KeyValuePair<MaybeType, ClassBase>>();
146-
var contexts = storage.GetValue <Dictionary<PyType, InterDomainContext>>("contexts");
149+
var contexts = storage.Contexts;
147150
var loadedObjs = new Dictionary<ManagedType, InterDomainContext>();
148151
foreach (var pair in cache)
149152
{
@@ -171,7 +174,7 @@ internal static Dictionary<ManagedType, InterDomainContext> RestoreRuntimeData(R
171174
foreach (var pair in invalidClasses)
172175
{
173176
cache.Remove(pair.Key);
174-
Runtime.XDecref(pair.Value.pyHandle);
177+
pair.Value.pyHandle.Dispose();
175178
}
176179

177180
return loadedObjs;

src/runtime/clrobject.cs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ internal CLRObject(object ob, PyType tp)
1616
using var py = Runtime.PyType_GenericAlloc(tp, 0);
1717

1818
tpHandle = tp;
19-
pyHandle = py;
19+
pyHandle = py.MoveToPyObject();
2020
inst = ob;
2121

2222
GCHandle gc = AllocGCHandle(TrackTypes.Wrapper);
@@ -45,44 +45,34 @@ static CLRObject GetInstance(object ob)
4545

4646
internal static NewReference GetReference(object ob, BorrowedReference pyType)
4747
{
48-
CLRObject co = GetInstance(ob, pyType.DangerousGetAddress());
49-
return NewReference.DangerousFromPointer(co.pyHandle);
50-
}
51-
internal static IntPtr GetInstHandle(object ob, IntPtr pyType)
52-
{
53-
CLRObject co = GetInstance(ob, pyType);
54-
return co.pyHandle;
48+
CLRObject co = GetInstance(ob, new PyType(pyType));
49+
return new NewReference(co.pyHandle);
5550
}
5651

57-
58-
internal static IntPtr GetInstHandle(object ob, Type type)
52+
internal static NewReference GetReference(object ob, Type type)
5953
{
6054
ClassBase cc = ClassManager.GetClass(type);
6155
CLRObject co = GetInstance(ob, cc.tpHandle);
62-
return co.pyHandle;
56+
return new NewReference(co.pyHandle);
6357
}
6458

6559

66-
internal static IntPtr GetInstHandle(object ob)
60+
internal static NewReference GetReference(object ob)
6761
{
6862
CLRObject co = GetInstance(ob);
69-
return co.pyHandle;
63+
return new NewReference(co.pyHandle);
7064
}
7165

72-
internal static NewReference GetReference(object ob)
73-
=> NewReference.DangerousFromPointer(GetInstHandle(ob));
74-
internal static NewReference GetReference(object ob, Type type)
75-
=> NewReference.DangerousFromPointer(GetInstHandle(ob, type));
76-
77-
internal static CLRObject Restore(object ob, IntPtr pyHandle, InterDomainContext context)
66+
internal static CLRObject Restore(object ob, BorrowedReference pyHandle, InterDomainContext context)
7867
{
68+
var pyObj = new PyObject(pyHandle);
7969
CLRObject co = new CLRObject()
8070
{
8171
inst = ob,
82-
pyHandle = pyHandle,
83-
tpHandle = Runtime.PyObject_TYPE(pyHandle)
72+
pyHandle = pyObj,
73+
tpHandle = pyObj.GetPythonType(),
8474
};
85-
Debug.Assert(co.tpHandle != IntPtr.Zero);
75+
Debug.Assert(co.tpHandle != null);
8676
co.Load(context);
8777
return co;
8878
}

src/runtime/extensiontype.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ public ExtensionType()
3030
NewReference py = Runtime.PyType_GenericAlloc(tp, 0);
3131

3232
// Borrowed reference. Valid as long as pyHandle is valid.
33-
tpHandle = tp.DangerousGetAddress();
34-
pyHandle = py.DangerousMoveToPointer();
33+
tpHandle = new PyType(tp, prevalidated: true);
34+
pyHandle = py.MoveToPyObject();
3535

3636
#if DEBUG
3737
GetGCHandle(ObjectReference, TypeReference, out var existing);
@@ -79,26 +79,26 @@ protected virtual void Clear()
7979
public static int tp_setattro(BorrowedReference ob, BorrowedReference key, BorrowedReference val)
8080
{
8181
var message = "type does not support setting attributes";
82-
if (val == IntPtr.Zero)
82+
if (val == null)
8383
{
8484
message = "readonly attribute";
8585
}
8686
Exceptions.SetError(Exceptions.AttributeError, message);
8787
return -1;
8888
}
8989

90-
public static void tp_dealloc(IntPtr ob)
90+
public static void tp_dealloc(NewReference ob)
9191
{
9292
// Clean up a Python instance of this extension type. This
9393
// frees the allocated Python object and decrefs the type.
94-
var self = (ExtensionType)GetManagedObject(ob);
94+
var self = (ExtensionType?)GetManagedObject(ob.Borrow());
9595
self?.Clear();
9696
self?.Dealloc();
9797
}
9898

99-
public static int tp_clear(IntPtr ob)
99+
public static int tp_clear(BorrowedReference ob)
100100
{
101-
var self = (ExtensionType)GetManagedObject(ob);
101+
var self = (ExtensionType?)GetManagedObject(ob);
102102
self?.Clear();
103103
return 0;
104104
}

src/runtime/importhook.cs

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
22
using System.Collections.Concurrent;
3+
using System.Collections.Generic;
4+
5+
using Python.Runtime.StateSerialization;
36

47
namespace Python.Runtime
58
{
@@ -84,29 +87,63 @@ internal static void Shutdown()
8487
TeardownNameSpaceTracking();
8588
Runtime.Py_CLEAR(ref py_clr_module!);
8689

87-
Runtime.XDecref(root.pyHandle);
90+
root.pyHandle.Dispose();
8891
root = null!;
8992
CLRModule.Reset();
9093
}
9194

92-
internal static void SaveRuntimeData(RuntimeDataStorage storage)
95+
private static Dictionary<PyString, PyObject> GetDotNetModules()
9396
{
94-
// Increment the reference counts here so that the objects don't
95-
// get freed in Shutdown.
96-
Runtime.XIncref(py_clr_module);
97-
Runtime.XIncref(root.pyHandle);
98-
storage.AddValue("py_clr_module", py_clr_module);
99-
storage.AddValue("root", root.pyHandle);
97+
BorrowedReference pyModules = Runtime.PyImport_GetModuleDict();
98+
using var items = Runtime.PyDict_Items(pyModules);
99+
nint length = Runtime.PyList_Size(items.BorrowOrThrow());
100+
var modules = new Dictionary<PyString, PyObject>();
101+
for (nint i = 0; i < length; i++)
102+
{
103+
BorrowedReference item = Runtime.PyList_GetItem(items.Borrow(), i);
104+
BorrowedReference name = Runtime.PyTuple_GetItem(item, 0);
105+
BorrowedReference module = Runtime.PyTuple_GetItem(item, 1);
106+
if (ManagedType.IsInstanceOfManagedType(module))
107+
{
108+
modules.Add(new PyString(name), new PyObject(module));
109+
}
110+
}
111+
return modules;
112+
}
113+
internal static ImportHookState SaveRuntimeData()
114+
{
115+
return new()
116+
{
117+
PyCLRModule = py_clr_module,
118+
Root = root.pyHandle,
119+
Modules = GetDotNetModules(),
120+
};
100121
}
101122

102-
internal static void RestoreRuntimeData(RuntimeDataStorage storage)
123+
private static void RestoreDotNetModules(Dictionary<PyString, PyObject> modules)
124+
{
125+
var pyMoudles = Runtime.PyImport_GetModuleDict();
126+
foreach (var item in modules)
127+
{
128+
var moduleName = item.Key;
129+
var module = item.Value;
130+
int res = Runtime.PyDict_SetItem(pyMoudles, moduleName, module);
131+
PythonException.ThrowIfIsNotZero(res);
132+
item.Key.Dispose();
133+
item.Value.Dispose();
134+
}
135+
modules.Clear();
136+
}
137+
internal static void RestoreRuntimeData(ImportHookState storage)
103138
{
104-
storage.GetValue("py_clr_module", out py_clr_module);
105-
var rootHandle = storage.GetValue<IntPtr>("root");
106-
root = (CLRModule)ManagedType.GetManagedObject(rootHandle);
139+
py_clr_module = storage.PyCLRModule;
140+
var rootHandle = storage.Root;
141+
root = (CLRModule)ManagedType.GetManagedObject(rootHandle)!;
107142
BorrowedReference dict = Runtime.PyImport_GetModuleDict();
108143
Runtime.PyDict_SetItemString(dict, "clr", ClrModuleReference);
109144
SetupNamespaceTracking();
145+
146+
RestoreDotNetModules(storage.Modules);
110147
}
111148

112149
static void SetupImportHook()

src/runtime/managedtype.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ internal enum TrackTypes
2727
internal PyObject pyHandle; // PyObject *
2828
internal PyType tpHandle; // PyType *
2929

30+
[NonSerialized]
3031
internal bool clearReentryGuard;
3132

3233
internal BorrowedReference ObjectReference

src/runtime/metatype.cs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
using System.Runtime.InteropServices;
33
using System.Runtime.Serialization;
44

5+
using Python.Runtime.StateSerialization;
6+
57
namespace Python.Runtime
68
{
79
/// <summary>
@@ -39,19 +41,14 @@ public static void Release()
3941
_metaSlotsHodler.ResetSlots();
4042
}
4143
PyCLRMetaType.Dispose();
42-
_metaSlotsHodler = null;
44+
_metaSlotsHodler = null!;
4345
}
4446

45-
internal static void SaveRuntimeData(RuntimeDataStorage storage)
46-
{
47-
#warning needs handling
48-
Runtime.XIncref(PyCLRMetaType);
49-
storage.PushValue(PyCLRMetaType);
50-
}
47+
internal static MetatypeState SaveRuntimeData() => new() { CLRMetaType = PyCLRMetaType };
5148

52-
internal static PyObject RestoreRuntimeData(RuntimeDataStorage storage)
49+
internal static PyType RestoreRuntimeData(MetatypeState storage)
5350
{
54-
PyCLRMetaType = storage.PopValue<IntPtr>();
51+
PyCLRMetaType = storage.CLRMetaType;
5552
_metaSlotsHodler = new SlotsHolder(PyCLRMetaType);
5653
TypeManager.InitializeSlots(PyCLRMetaType, typeof(MetaType), _metaSlotsHodler);
5754

0 commit comments

Comments
 (0)