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

Skip to content

Reset the type slots (split from #958) #1016

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 9 commits into from
1 change: 1 addition & 0 deletions AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
- David Lassonde ([@lassond](https://github.com/lassond))
- David Lechner ([@dlech](https://github.com/dlech))
- Dmitriy Se ([@dmitriyse](https://github.com/dmitriyse))
- Félix Bourbonnais ([@BadSingleton](https://github.com/BadSingleton))
- Florian Treurniet ([@ftreurni](https://github.com/ftreurni))
- He-chien Tsai ([@t3476](https://github.com/t3476))
- Inna Wiesel ([@inna-w](https://github.com/inna-w))
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ This document follows the conventions laid out in [Keep a CHANGELOG][].
- Added support for converting python iterators to C# arrays
- Changed usage of obselete function GetDelegateForFunctionPointer(IntPtr, Type) to GetDelegateForFunctionPointer<TDelegate>(IntPtr)
- Added support for kwarg parameters when calling .NET methods from Python
- Added cleanup logic for the managed types on shutdown.

### Fixed

Expand Down
11 changes: 10 additions & 1 deletion src/runtime/interop.cs
Original file line number Diff line number Diff line change
Expand Up @@ -509,7 +509,7 @@ internal static ThunkInfo GetThunk(MethodInfo method, string funcType = null)
}


[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
[StructLayout(LayoutKind.Sequential)]
internal struct Thunk
{
public Delegate fn;
Expand Down Expand Up @@ -537,4 +537,13 @@ public ThunkInfo(Delegate target)
Address = Marshal.GetFunctionPointerForDelegate(target);
}
}

[StructLayout(LayoutKind.Sequential)]
struct PyMethodDef
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please, add the following link as a comment: https://docs.python.org/3/c-api/structures.html#c.PyMethodDef

{
public IntPtr ml_name;
public IntPtr ml_meth;
public int ml_flags;
public IntPtr ml_doc;
}
}
17 changes: 15 additions & 2 deletions src/runtime/metatype.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,30 @@ namespace Python.Runtime
internal class MetaType : ManagedType
{
private static IntPtr PyCLRMetaType;

private static SlotsHolder _metaSlotsHodler;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just noticed the typo here. This is holding slots, not bitcoin.


/// <summary>
/// Metatype initialization. This bootstraps the CLR metatype to life.
/// </summary>
public static IntPtr Initialize()
{
PyCLRMetaType = TypeManager.CreateMetaType(typeof(MetaType));
PyCLRMetaType = TypeManager.CreateMetaType(typeof(MetaType), out _metaSlotsHodler);
return PyCLRMetaType;
}

public static void Release()
{
if (PyCLRMetaType == IntPtr.Zero)
{
throw new ObjectDisposedException("PyCLRMetaType");
}
if (Runtime.Refcount(PyCLRMetaType) > 1)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand the reasoning behind > 1 condition.
In fact, why even use Refcount? This class should have its own way to track if PyCLRMetaType is allocated.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reasoning is the same as with the similar pattern in typemanager.cs#38. The only way I can see this class tracking it's allocation is to look if the PyCLRMetaType is IntPtr.Zero or not.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The logic is: If the refcount is 1, then at line 31 when decref, it'll go to zero and the entire type will be released. In that case we don't care about clearing the slots. It's a standard optimization in a ref-counting framework.

It's correct assuming that ReleaseTypeSlots doesn't also release refcounts that otherwise won't be released.

That said: Do we have coverage on line 29? I'm not sure I really understand under what circumstance it happens.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd put the expression into bool isLastReference (don't miss the negations) or at least add a comment.

{
_metaSlotsHodler.ResetSlots();
}
Runtime.Py_CLEAR(ref PyCLRMetaType);
_metaSlotsHodler = null;
}

/// <summary>
/// Metatype __new__ implementation. This is called to create a new
Expand Down
1 change: 0 additions & 1 deletion src/runtime/methodwrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ internal class MethodWrapper
public IntPtr mdef;
public IntPtr ptr;
private bool _disposed = false;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you add this empty line back in you remove an entire file from the squash-commit.

private ThunkInfo _thunk;

public MethodWrapper(Type type, string name, string funcType = null)
Expand Down
23 changes: 23 additions & 0 deletions src/runtime/runtime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ internal static void Initialize(bool initSigs = false)
PyNone = PyObject_GetAttrString(op, "None");
PyTrue = PyObject_GetAttrString(op, "True");
PyFalse = PyObject_GetAttrString(op, "False");
PySuper_Type = PyObject_GetAttrString(op, "super");

PyBoolType = PyObject_Type(PyTrue);
PyNoneType = PyObject_Type(PyNone);
Expand Down Expand Up @@ -380,6 +381,11 @@ internal static void Shutdown()
Exceptions.Shutdown();
ImportHook.Shutdown();
Finalizer.Shutdown();

TypeManager.RemoveTypes();
MetaType.Release();
PyCLRMetaType = IntPtr.Zero;

Py_Finalize();
}

Expand All @@ -401,6 +407,7 @@ internal static int AtExit()
internal static IntPtr PyModuleType;
internal static IntPtr PyClassType;
internal static IntPtr PyInstanceType;
internal static IntPtr PySuper_Type;
internal static IntPtr PyCLRMetaType;
internal static IntPtr PyMethodType;
internal static IntPtr PyWrapperDescriptorType;
Expand Down Expand Up @@ -1905,6 +1912,22 @@ internal static IntPtr PyMem_Realloc(IntPtr ptr, long size)
[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern void PyErr_Print();

internal static void Py_CLEAR(ref IntPtr ob)
{
XDecref(ob);
ob = IntPtr.Zero;
}

//====================================================================
// Python Capsules API
//====================================================================

[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyCapsule_New(IntPtr pointer, string name, IntPtr destructor);

[DllImport(_PythonDll, CallingConvention = CallingConvention.Cdecl)]
internal static extern IntPtr PyCapsule_GetPointer(IntPtr capsule, string name);


//====================================================================
// Miscellaneous
Expand Down
Loading