Skip to content

Commit

Permalink
Merge pull request dotnet#2860 from dotnet/ARC
Browse files Browse the repository at this point in the history
[SwiftBindings] Added pinvokes for handling ARC
  • Loading branch information
stephen-hawley authored Dec 9, 2024
2 parents b2369e1 + 6ceb4ba commit 23d0cff
Showing 1 changed file with 167 additions and 0 deletions.
167 changes: 167 additions & 0 deletions src/Swift.Runtime/src/Library/Arc.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System;
using System.Runtime.InteropServices;

namespace Swift.Runtime;

/// <summary>
/// Arc is a class containing p/invokes for Swift Automatic Reference Counting and memory management.
/// </summary>
public static class Arc {
const string swiftCore = "/usr/lib/swift/libswiftCore.dylib";

/// <summary>
/// Retain a heap-allocated Swift object
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern void swift_retain(IntPtr p);

/// <summary>
/// Retain a heap-allocated Swift object
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The pointer passed in.</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static IntPtr Retain(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
swift_retain(p);
return p;
}

/// <summary>
/// Check to see if a pointer is in the process of being deallocated.
/// </summary>
/// <param name="p">A non-null pointer to an unmanaged Swift object</param>
/// <returns>True if and only if the pointer in the process of being deallocated.</returns>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool swift_isDeallocating(IntPtr p);

/// <summary>
/// Check to see if a pointer is in the process of being deallocated.
/// </summary>
/// <param name="p">A non-null pointer to an unmanaged Swift object</param>
/// <returns>True if and only if the pointer in the process of being deallocated.</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static bool IsDeallocating(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
return swift_isDeallocating(p);
}

/// <summary>
/// Releases a heap-allocated Swift object
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern void swift_release(IntPtr p);

/// <summary>
/// Releases a heap-allocated Swift object
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The pointer passed in</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
/// <exception cref="Exception">Throws if p points to an object that has been deinitialized</exception>
public static IntPtr Release(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
if (swift_isDeallocating(p))
{
throw new Exception(string.Format ("Attempt to release a Swift object that has been deinitialized {0}", p.ToString($"X{IntPtr.Size * 2}")));
}
swift_release(p);
return p;
}

/// <summary>
/// Retains an 'unowned' heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern void swift_unownedRetain(IntPtr p);

/// <summary>
/// Retains an 'unowned' heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The pointer passed in</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static IntPtr UnownedRetain(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
swift_unownedRetain(p);
return p;
}

/// <summary>
/// Releases an 'unowned' heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern void swift_unownedRelease(IntPtr p);

/// <summary>
/// Releases an 'unowned' heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The pointer passed in</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static IntPtr UnownedRelease(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
swift_unownedRelease(p);
return p;
}

/// <summary>
/// Returns the retain count for the heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The retain count</returns>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern nint swift_retainCount(IntPtr p);

/// <summary>
/// Returns the retain count for the heap-allocated Swift object
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The retain count</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static nint RetainCount(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
return swift_retainCount(p);
}

/// <summary>
/// Returns the 'unowned' retain count for the heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The unowned retain count</returns>
[DllImport(swiftCore, CallingConvention = CallingConvention.Cdecl)]
static extern nint swift_unownedRetainCount(IntPtr p);

/// <summary>
/// Returns the 'unowned' retain count for the heap-allocated Swift object.
/// </summary>
/// <param name="p">Pointer to an unmanaged Swift object, must be non-null.</param>
/// <returns>The unowned retain count</returns>
/// <exception cref="ArgumentNullException">Throws if p is null</exception>
public static nint UnownedRetainCount(IntPtr p)
{
if (p == IntPtr.Zero)
throw new ArgumentNullException(nameof(p));
return swift_unownedRetainCount(p);
}
}

0 comments on commit 23d0cff

Please sign in to comment.