モジュール jdk.incubator.foreign
パッケージ jdk.incubator.foreign

インタフェースResourceScope

すべてのスーパー・インタフェース:
AutoCloseable

public sealed interface ResourceScope extends AutoCloseable
リソース・スコープは、1つ以上のリソースのライフサイクルを管理します。 リソース・スコープに関連付けられたリソース(e.g. MemorySegment)には、リソース・スコープがaliveであり、リソース・スコープ(もしあれば)に関連付けられた「スレッド」によってのみアクセスできます。

確定的な割当て解除位置

リソース・スコープは「確定的割当て解除」をサポートしています。つまり、明示的にclosedにできます。 リソース・スコープがクローズされると、aliveではなくなり、そのスコープ(例: MemorySegmentインスタンスへのアクセスを試行しています)に関連付けられたリソースに対する後続の操作はIllegalStateExceptionで失敗します。

リソース・スコープをクローズすると、そのスコープに関連付けられたすべての「クローズ処理」がコールされます。 さらに、リソース・スコープを閉じると、そのスコープに関連付けられた基礎となるメモリー・リソースの解放がトリガーされる可能性があります。たとえば、次のようになります:

暗黙的な割当て解除

リソース・スコープをCleanerインスタンスに関連付けることができるため、スコープ・インスタンスがunreachableになったら、リソース・スコープも自動的にクローズされます。 これは、偶発的なネイティブ・メモリー・リークを防止しながら、予測可能な確定的リソース・ロケーションを許可するのに役立ちます。 管理対象リソース・スコープが明示的にクローズされている場合、スコープが到達不能になったとき、つまり、リソース・スコープに関連付けられた「クローズ処理」「正確に1回」と呼ばれます。

グローバル・スコープ

重要な暗黙的なリソース・スコープは「グローバル・スコープ」と呼ばれ、グローバル・スコープは、明示的にまたは暗黙的にクローズできないリソース・スコープです。 そのため、グローバル・スコープは、それに関連付けられたリソースの解放を試行しません。 グローバル・スコープに関連付けられたリソースの例を次に示します: つまり、グローバル・スコープは、必要に応じて1つ以上のリソースのライフサイクルをクライアントによって独立して管理する必要があることを示すために使用されます。

スレッド制限

リソース・スコープは2つのカテゴリに分類できます: thread-confinedリソース・スコープおよびsharedリソース・スコープ。

「限られたリソース・スコープ」は、強力なスレッド限定保証をサポートします。 作成時に、「所有者スレッド」(通常は作成操作を開始したスレッド)が割り当てられます。 限定されたリソース・スコープを作成すると、所有者スレッドのみが、このリソース・スコープに関連付けられたリソースを直接操作できます。 所有者スレッド以外のスレッドからリソース・アクセスを実行しようとすると、実行時エラーが発生します。

一方、「共有リソース・スコープ」には所有者スレッドがありません。つまり、共有リソース・スコープに関連付けられたリソースには複数のスレッドからアクセスできます。 これは、複数のスレッドが同じリソース (例:パラレル処理の場合)に同時にアクセスする必要がある場合に役立ちます。 たとえば、クライアントは共有スコープによってバックアップされたセグメントからSpliteratorを取得し、そのセグメントをスライスするために使用し、複数のスレッドを非結合セグメント・スライスでパラレルに動作させることができます。 次のコードを使用すると、メモリー・セグメント内のすべてのint値を並列に合計できます:

try (ResourceScope scope = ResourceScope.newSharedScope()) {
    SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT);
    MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, scope);
    int sum = segment.elements(ValueLayout.JAVA_INT).parallel()
                     .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0))
                     .sum();
}

共有リソース・スコープは強力ですが、注意して使用する必要があります: スコープが別のスレッドからクローズされている間に、1つ以上のスレッドが共有スコープに関連付けられたリソースにアクセスした場合、アクセス・スレッドとクローズ・スレッドの両方で例外が発生する可能性があります。 クライアントは、共有リソース・スコープを繰り返し (例:例外がスローされなくなるまでclose()をコールし続ける)を閉じようとしないでください。 かわりに、共有リソース・スコープのクライアントは、共有リソース・スコープをクローズするスレッドが同じスコープで管理されるリソースにアクセスするスレッドに対して競合しないように、常に適切な同期メカニズム(たとえば、一時的な依存関係の使用については、次を参照してください)が配置されるようにする必要があります。

一時的な依存関係

リソース・スコープは互いに依存できます。 さらに具体的には、スコープは、1つ以上の他のリソース・スコープで「一時的な依存関係」を機能させることができます。 このようなリソース・スコープは、allが依存するスコープもクローズされるまで(暗黙的または明示的に)をクローズできません。

これは、クライアントがメモリー・セグメントに対して重要な操作を実行する必要がある場合に便利です。その間に、そのセグメントに関連付けられたスコープが閉じないようにする必要があります。これは、次のように実行できます:

MemorySegment segment = ...
try (ResourceScope criticalScope = ResourceScope.newConfinedScope()) {
    criticalScope.keepAlive(segment.scope());
    <critical operation on segment>
}
リソース・スコープが依存するすべてのスコープがクローズされるまで、リソース・スコープはunreachableになりません。

実装要件:
このインタフェースの実装は不変、スレッド・セーフ、およびvalue-basedです。
  • メソッドのサマリー

    修飾子と型
    メソッド
    説明
    void
    リソース・スコープがクローズされたときに実行されるカスタム・クリーンアップ・アクションを追加します。
    void
    このリソース・スコープを閉じます。
    boolean
    このリソース・スコープが存続している場合、trueを返します。
    void
    このスコープとターゲット・スコープの間に一時的な依存関係を作成します。
    新しい限定スコープを作成します。
    提供されたクリーナ・インスタンスによって管理される、新しい限定されたスコープを作成します。
    プライベートCleanerインスタンスによって管理される新しい共有スコープを作成します。
    新しい共有スコープを作成します。
    提供されたクリーナ・インスタンスによって管理される新しい共有スコープを作成します。
    このリソース・スコープを所有するスレッド。
  • メソッドの詳細

    • isAlive

      boolean isAlive()
      このリソース・スコープが存続している場合、trueを返します。
      戻り値:
      true:このリソース・スコープが存続している場合
      関連項目:
    • ownerThread

      Thread ownerThread()
      このリソース・スコープを所有するスレッド。
      戻り値:
      このリソース・スコープを所有するスレッド、またはこのリソース・スコープが共有されている場合はnull
    • close

      void close()
      このリソース・スコープを閉じます。 副作用として、この操作が例外なしで完了した場合、このスコープは「生きていない」としてマークされ、このスコープに関連付けられたリソースに対する後続の操作はIllegalStateExceptionで失敗します。 また、クローズが成功すると、このリソース・スコープに関連付けられたすべてのネイティブ・リソースが解放されます。
      定義:
      close、インタフェース: AutoCloseable
      APIのノート:
      この操作はべき等ではありません。つまり、すでに閉じているリソース・スコープalwaysをクローズすると、例外がスローされます。 これは意図的な設計の選択を反映しています: リソース・スコープの状態遷移はクライアント・コードでマニフェストである必要があります。これらの遷移のいずれかが失敗すると、基礎となるアプリケーション・ロジックのバグが表示されます。
      例外:
      IllegalStateException - 次の条件のいずれかが満たされた場合:
      • このリソース・スコープはaliveではありません
      • このリソース・スコープは制限されており、このメソッドは、このリソース・スコープを所有するスレッド以外のスレッドから呼び出されます
      • このリソース・スコープは共有され、このメソッドを呼び出したときにこのスコープに関連付けられたリソースにアクセス
      • このリソース・スコープの「依存」がクローズされていない1つ以上のスコープ。
      UnsupportedOperationException - このリソース・スコープが「グローバル・スコープ」の場合。
    • addCloseAction

      void addCloseAction(Runnable runnable)
      リソース・スコープがクローズされたときに実行されるカスタム・クリーンアップ・アクションを追加します。 スコープがクローズされると、カスタム・クリーンアップ・アクションが起動される順序は指定されません。
      パラメータ:
      runnable - このスコープに関連付けられるカスタム・クリーンアップ・アクション。
      例外:
      IllegalStateException - このスコープが閉じられている場合、またはこのスコープを所有するスレッド以外のスレッドからアクセスが発生した場合。
    • keepAlive

      void keepAlive(ResourceScope target)
      このスコープとターゲット・スコープの間に一時的な依存関係を作成します。 その結果、このスコープの前にターゲット・スコープをclosedにすることはできません。
      実装上のノート:
      特定のスコープでは、保留中のキープアライブ・リクエストを最大Integer.MAX_VALUEでサポートできます。
      パラメータ:
      target - 存続する必要がある範囲。
      例外:
      IllegalArgumentException - target == thisの場合。
      IllegalStateException - このスコープまたはtargetが閉じられている場合、またはこのスコープまたはtargetを所有するスレッド以外のスレッドからアクセスが発生した場合。
    • newConfinedScope

      static ResourceScope newConfinedScope()
      新しい限定スコープを作成します。
      戻り値:
      新しい限定スコープ。
    • newConfinedScope

      static ResourceScope newConfinedScope(Cleaner cleaner)
      提供されたクリーナ・インスタンスによって管理される、新しい限定されたスコープを作成します。
      パラメータ:
      cleaner - 返されたスコープに関連付けられるクリーナ。
      戻り値:
      cleanerによって管理される新しい限定スコープ。
    • newSharedScope

      static ResourceScope newSharedScope()
      新しい共有スコープを作成します。
      戻り値:
      新しい共有スコープ。
    • newSharedScope

      static ResourceScope newSharedScope(Cleaner cleaner)
      提供されたクリーナ・インスタンスによって管理される新しい共有スコープを作成します。
      パラメータ:
      cleaner - 返されたスコープに関連付けられるクリーナ。
      戻り値:
      cleanerによって管理される新しい共有スコープ。
    • newImplicitScope

      static ResourceScope newImplicitScope()
      プライベートCleanerインスタンスによって管理される新しい共有スコープを作成します。 (ただし、より効率的である可能性があります。)と同等のコードは次のとおりです:
      newSharedScope(Cleaner.create());
      
      戻り値:
      プライベートCleanerインスタンスによって管理される共有スコープ。
    • globalScope

      static ResourceScope globalScope()
      戻り値:
      グローバル・スコープ