Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,35 @@

namespace System.Runtime.InteropServices.Java
{
/// <summary>
/// Provides helpers to create and manage GC handles used for tracking references
/// between the managed runtime and a Java VM. These APIs allow managed objects
/// to be referenced from native Java code so the runtime can participate in
/// cross-reference processing and correctly control object lifetime across
/// the managed/native boundary.
/// </summary>
[CLSCompliant(false)]
[SupportedOSPlatform("android")]
public static partial class JavaMarshal
{
/// <summary>
/// Initializes the Java marshal subsystem with a callback used when the runtime
/// needs to mark managed objects that are referenced from Java during cross-
/// reference processing.
/// </summary>
/// <param name="markCrossReferences">A pointer to an unmanaged callback that
/// will be invoked to enumerate or mark managed objects referenced from Java
/// during a cross-reference sweep. The callback is expected to accept a
/// <see cref="MarkCrossReferencesArgs"/> pointer describing the objects to mark.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="markCrossReferences"/> is null.</exception>
Copy link
Contributor

Choose a reason for hiding this comment

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

Exception text is not supposed to start with "Thrown when..." - see https://github.com/dotnet/dotnet-api-docs/wiki/Exceptions#how-to.

Copy link
Contributor

Choose a reason for hiding this comment

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

This wording needs to be changed throughout...

/// <exception cref="InvalidOperationException">Thrown when the subsystem cannot be initialized or is reinitialized.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
/// <remarks>
/// Only a single initialization is supported for the process. The runtime
/// stores the provided function pointer and will invoke it from internal
/// runtime code when cross-reference marking is required.
/// Additionally, this callback must be implemented in unmanaged code.
/// </remarks>
public static unsafe void Initialize(delegate* unmanaged<MarkCrossReferencesArgs*, void> markCrossReferences)
{
ArgumentNullException.ThrowIfNull(markCrossReferences);
Expand All @@ -20,6 +45,20 @@ public static unsafe void Initialize(delegate* unmanaged<MarkCrossReferencesArgs
}
}

/// <summary>
/// Creates a GC handle that native Java code can hold to reference a managed
/// object. The handle prevents the object from being reclaimed while the
/// native side holds the reference, and an opaque <paramref name="context"/>
/// value can be associated with the handle for later retrieval.
/// </summary>
/// <param name="obj">The managed object to be referenced from native code.</param>
/// <param name="context">An opaque pointer-sized value that will be associated
/// with the handle and can be retrieved by the runtime via <see cref="GetContext(GCHandle)"/>.
/// Callers may use this to store native-side state or identifiers alongside
/// the handle.</param>
/// <returns>A <see cref="GCHandle"/> that represents the allocated reference-tracking handle.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="obj"/> is null.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* context)
{
ArgumentNullException.ThrowIfNull(obj);
Expand All @@ -28,6 +67,18 @@ public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* co
return GCHandle.FromIntPtr(handle);
}

/// <summary>
/// Retrieves the opaque context pointer associated with a reference-tracking
/// GC handle previously created using <see cref="CreateReferenceTrackingHandle(object, void*)"/>.
/// </summary>
/// <param name="obj">The <see cref="GCHandle"/> whose context should be returned.</param>
/// <returns>The opaque context pointer associated with the handle.</returns>
/// <exception cref="InvalidOperationException">Thrown when the provided handle is null or does not represent a reference-tracking handle.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
/// <remarks>
/// The returned pointer is the exact value that was originally provided as
/// the context parameter when the handle was created.
/// </remarks>
public static unsafe void* GetContext(GCHandle obj)
{
IntPtr handle = GCHandle.ToIntPtr(obj);
Expand All @@ -40,6 +91,15 @@ public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* co
return context;
}

/// <summary>
/// Completes processing of cross references after the runtime has invoked the
/// callback provided to <see cref="Initialize" />. This notifies the runtime of
/// handles that are no longer reachable from native Java code so the runtime
/// can release or update them accordingly.
/// </summary>
/// <param name="crossReferences">A pointer to the structure containing cross-reference information produced during marking.</param>
/// <param name="unreachableObjectHandles">A span of <see cref="GCHandle"/> values that were determined to be unreachable from the native side.</param>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
public static unsafe void FinishCrossReferenceProcessing(
MarkCrossReferencesArgs* crossReferences,
ReadOnlySpan<GCHandle> unreachableObjectHandles)
Expand Down
Copy link
Contributor

Choose a reason for hiding this comment

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

Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,35 @@

namespace System.Runtime.InteropServices.Java
{
/// <summary>
/// Provides helpers to create and manage GC handles used for tracking references
Copy link
Contributor

Choose a reason for hiding this comment

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

Summaries are supposed to be a single sentence according to https://github.com/dotnet/dotnet-api-docs/wiki/Summary.

/// between the managed runtime and a Java VM. These APIs allow managed objects
/// to be referenced from native Java code so the runtime can participate in
/// cross-reference processing and correctly control object lifetime across
/// the managed/native boundary.
/// </summary>
[CLSCompliant(false)]
[SupportedOSPlatform("android")]
public static partial class JavaMarshal
{
/// <summary>
/// Initializes the Java marshal subsystem with a callback used when the runtime
/// needs to mark managed objects that are referenced from Java during cross-
/// reference processing.
/// </summary>
/// <param name="markCrossReferences">A pointer to an unmanaged callback that
/// will be invoked to enumerate or mark managed objects referenced from Java
/// during a cross-reference sweep. The callback is expected to accept a
/// <see cref="MarkCrossReferencesArgs"/> pointer describing the objects to mark.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="markCrossReferences"/> is null.</exception>
/// <exception cref="InvalidOperationException">Thrown when the subsystem cannot be initialized or is reinitialized.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
/// <remarks>
/// Only a single initialization is supported for the process. The runtime
/// stores the provided function pointer and will invoke it from internal
/// runtime code when cross-reference marking is required.
/// Additionally, this callback must be implemented in unmanaged code.
/// </remarks>
public static unsafe void Initialize(delegate* unmanaged<MarkCrossReferencesArgs*, void> markCrossReferences)
{
ArgumentNullException.ThrowIfNull(markCrossReferences);
Expand All @@ -20,12 +45,38 @@ public static unsafe void Initialize(delegate* unmanaged<MarkCrossReferencesArgs
}
}

/// <summary>
/// Creates a GC handle that native Java code can hold to reference a managed
/// object. The handle prevents the object from being reclaimed while the
/// native side holds the reference, and an opaque <paramref name="context"/>
/// value can be associated with the handle for later retrieval.
/// </summary>
/// <param name="obj">The managed object to be referenced from native code.</param>
/// <param name="context">An opaque pointer-sized value that will be associated
/// with the handle and can be retrieved by the runtime via <see cref="GetContext(GCHandle)"/>.
/// Callers may use this to store native-side state or identifiers alongside
/// the handle.</param>
/// <returns>A <see cref="GCHandle"/> that represents the allocated reference-tracking handle.</returns>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="obj"/> is null.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* context)
{
ArgumentNullException.ThrowIfNull(obj);
return GCHandle.FromIntPtr(RuntimeImports.RhHandleAllocCrossReference(obj, (IntPtr)context));
}

/// <summary>
/// Retrieves the opaque context pointer associated with a reference-tracking
/// GC handle previously created using <see cref="CreateReferenceTrackingHandle(object, void*)"/>.
/// </summary>
/// <param name="obj">The <see cref="GCHandle"/> whose context should be returned.</param>
/// <returns>The opaque context pointer associated with the handle.</returns>
/// <exception cref="InvalidOperationException">Thrown when the provided handle is null or does not represent a reference-tracking handle.</exception>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
/// <remarks>
/// The returned pointer is the exact value that was originally provided as
/// the context parameter when the handle was created.
/// </remarks>
public static unsafe void* GetContext(GCHandle obj)
{
IntPtr handle = GCHandle.ToIntPtr(obj);
Expand All @@ -37,6 +88,15 @@ public static unsafe GCHandle CreateReferenceTrackingHandle(object obj, void* co
return (void*)context;
}

/// <summary>
/// Completes processing of cross references after the runtime has invoked the
/// callback provided to <see cref="Initialize" />. This notifies the runtime of
/// handles that are no longer reachable from native Java code so the runtime
/// can release or update them accordingly.
/// </summary>
/// <param name="crossReferences">A pointer to the structure containing cross-reference information produced during marking.</param>
/// <param name="unreachableObjectHandles">A span of <see cref="GCHandle"/> values that were determined to be unreachable from the native side.</param>
/// <exception cref="PlatformNotSupportedException">Thrown when the runtime or platform does not support Java cross-reference marshalling.</exception>
public static unsafe void FinishCrossReferenceProcessing(
MarkCrossReferencesArgs* crossReferences,
ReadOnlySpan<GCHandle> unreachableObjectHandles)
Expand Down
8 changes: 8 additions & 0 deletions src/libraries/System.Console/src/System/Console.cs
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,10 @@ public static void WriteLine(string? value)
Out.WriteLine(value);
}

/// <summary>
/// Writes the specified read-only span of characters, followed by the current line terminator, to the standard output stream.
/// </summary>
/// <param name="value">The span of characters to write.</param>
[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void WriteLine(ReadOnlySpan<char> value)
{
Expand Down Expand Up @@ -975,6 +979,10 @@ public static void Write(string? value)
Out.Write(value);
}

/// <summary>
/// Writes the specified read-only span of characters to the standard output stream.
/// </summary>
/// <param name="value">The span of characters to write.</param>
[MethodImplAttribute(MethodImplOptions.NoInlining)]
public static void Write(ReadOnlySpan<char> value)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public static partial class ZipFile
/// <param name="archiveFileName">A string specifying the path on the filesystem to open the archive on. The path is permitted
/// to specify relative or absolute path information. Relative path information is interpreted as relative to the current working directory.</param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation. The task result is an opened <see cref="ZipArchive"/> in <see cref="ZipArchiveMode.Read"/> mode.</returns>
public static Task<ZipArchive> OpenReadAsync(string archiveFileName, CancellationToken cancellationToken = default) => OpenAsync(archiveFileName, ZipArchiveMode.Read, cancellationToken);

/// <summary>
Expand Down Expand Up @@ -71,6 +72,7 @@ public static partial class ZipFile
/// If the file exists and is empty or does not exist, a new Zip file will be created.
/// Note that creating a Zip file with the <code>ZipArchiveMode.Create</code> mode is more efficient when creating a new Zip file.</param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation. The task result is an opened <see cref="ZipArchive"/> in the requested <paramref name="mode"/>.</returns>
public static Task<ZipArchive> OpenAsync(string archiveFileName, ZipArchiveMode mode, CancellationToken cancellationToken = default) => OpenAsync(archiveFileName, mode, entryNameEncoding: null, cancellationToken);

/// <summary>
Expand Down Expand Up @@ -149,6 +151,7 @@ public static partial class ZipFile
/// otherwise an <see cref="ArgumentException"/> is thrown.</para>
/// </param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous operation. The task result is an opened <see cref="ZipArchive"/> in the requested <paramref name="mode"/>.</returns>
public static async Task<ZipArchive> OpenAsync(string archiveFileName, ZipArchiveMode mode, Encoding? entryNameEncoding, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Expand Down Expand Up @@ -212,6 +215,7 @@ public static async Task<ZipArchive> OpenAsync(string archiveFileName, ZipArchiv
/// <param name="sourceDirectoryName">The path to the directory on the file system to be archived. </param>
/// <param name="destinationArchiveFileName">The name of the archive to be created.</param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous create operation. The task completes when the archive has been written to disk.</returns>
public static Task CreateFromDirectoryAsync(string sourceDirectoryName, string destinationArchiveFileName, CancellationToken cancellationToken = default) =>
DoCreateFromDirectoryAsync(sourceDirectoryName, destinationArchiveFileName, compressionLevel: null, includeBaseDirectory: false, entryNameEncoding: null, cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ public static partial class ZipFile
/// <param name="sourceArchiveFileName">The path to the archive on the file system that is to be extracted.</param>
/// <param name="destinationDirectoryName">The path to the directory in which to place the extracted files, specified as a relative or absolute path. A relative path is interpreted as relative to the current working directory.</param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous extract operation. The task completes when all entries have been extracted or an error occurs.</returns>
public static Task ExtractToDirectoryAsync(string sourceArchiveFileName, string destinationDirectoryName, CancellationToken cancellationToken = default) =>
ExtractToDirectoryAsync(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: false, cancellationToken);

Expand Down Expand Up @@ -75,6 +76,7 @@ public static Task ExtractToDirectoryAsync(string sourceArchiveFileName, string
/// <param name="destinationDirectoryName">The path to the directory in which to place the extracted files, specified as a relative or absolute path. A relative path is interpreted as relative to the current working directory.</param>
/// <param name="overwriteFiles">True to indicate overwrite.</param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous extract operation. The task completes when all entries have been extracted or an error occurs.</returns>
public static Task ExtractToDirectoryAsync(string sourceArchiveFileName, string destinationDirectoryName, bool overwriteFiles, CancellationToken cancellationToken = default) =>
ExtractToDirectoryAsync(sourceArchiveFileName, destinationDirectoryName, entryNameEncoding: null, overwriteFiles: overwriteFiles, cancellationToken);

Expand Down Expand Up @@ -188,6 +190,7 @@ public static Task ExtractToDirectoryAsync(string sourceArchiveFileName, string
/// otherwise an <see cref="ArgumentException"/> is thrown.</para>
/// </param>
/// <param name="cancellationToken">The cancellation token to monitor for cancellation requests.</param>
/// <returns>A task that represents the asynchronous extract operation. The task completes when all entries have been extracted or an error occurs.</returns>
public static async Task ExtractToDirectoryAsync(string sourceArchiveFileName, string destinationDirectoryName, Encoding? entryNameEncoding, bool overwriteFiles, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
Expand Down
Loading
Loading