11/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
22 *
3- * Copyright © 2023–2024 microBean™.
3+ * Copyright © 2023–2025 microBean™.
44 *
55 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
66 * the License. You may obtain a copy of the License at
1919
2020import java .util .function .Supplier ;
2121
22- import org .microbean .bean .Request ;
22+ import org .microbean .bean .Destruction ;
2323
2424import static java .lang .invoke .MethodHandles .lookup ;
2525
2626/**
2727 * An {@link AutoCloseable} pairing of a contextual instance that can be destroyed with a {@link Destructor} that can
28- * destroy it, an {@link AutoCloseable} that can release its dependent objects when needed, and a {@link Request} that
29- * caused it to be created.
28+ * destroy it and a {@link Destruction} view of the {@link org.microbean.bean.Creation} that caused it to be created.
3029 *
31- * @param <I> the type of the instance
30+ * @param <I> the contextual instance type
3231 *
3332 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
3433 *
3534 * @see Instance.Destructor
3635 *
37- * @see Request
36+ * @see Destruction
3837 */
3938public final class Instance <I > implements AutoCloseable , Supplier <I > {
4039
40+
41+ /*
42+ * Static fields.
43+ */
44+
45+
4146 private static final VarHandle CLOSED ;
4247
4348 static {
@@ -48,16 +53,26 @@ public final class Instance<I> implements AutoCloseable, Supplier<I> {
4853 }
4954 }
5055
56+
57+ /*
58+ * Instance fields.
59+ */
60+
61+
5162 private final I object ;
5263
5364 private final Destructor <I > destructor ;
5465
55- private final AutoCloseable releaser ;
56-
57- private final Request <I > creationRequest ;
66+ private final Destruction destruction ;
5867
5968 private volatile boolean closed ;
6069
70+
71+ /*
72+ * Constructors.
73+ */
74+
75+
6176 /**
6277 * Creates a new {@link Instance}.
6378 *
@@ -66,70 +81,28 @@ public final class Instance<I> implements AutoCloseable, Supplier<I> {
6681 * @param destructor a {@link Destructor} capable of (eventually) destroying the supplied {@code contextualInstance};
6782 * may be {@code null}
6883 *
69- * @param creationRequest a {@link Request} that is the reason for this creation ; may be {@code null}
84+ * @param destruction a {@link Destruction} ; may be {@code null}
7085 */
7186 public Instance (final I contextualInstance ,
7287 final Destructor <I > destructor ,
73- final Request <I > creationRequest ) {
74- this (contextualInstance , destructor , creationRequest instanceof AutoCloseable ac ? ac : null , creationRequest );
75- }
76-
77- private Instance (final I object ,
78- final Destructor <I > destructor ,
79- final AutoCloseable releaser , // often the same object as creationRequest
80- final Request <I > creationRequest ) { // often the same object as releaser
88+ final Destruction destruction ) {
8189 super ();
82- // All of these things are nullable on purpose.
83- this .object = object ;
84- this .releaser = releaser == null ? Instance ::sink : releaser ;
90+ this .destruction = destruction ;
91+ this .object = contextualInstance ;
8592 this .destructor = destructor == null ? Instance ::sink : destructor ;
86- this .creationRequest = creationRequest ;
8793 }
8894
89- /**
90- * Returns the contextual instance this {@link Instance} holds, which may be {@code null}.
91- *
92- * @return the contextual instance this {@link Instance} holds, which may be {@code null}
95+
96+ /*
97+ * Instance methods.
9398 */
94- @ Override // Supplier<I>
95- public final I get () {
96- if (this .closed ()) { // volatile read, effectively
97- throw new IllegalStateException ("closed" );
98- }
99- return this .object ;
100- }
99+
101100
102101 @ Override // AutoCloseable
103102 public final void close () {
104103 if (CLOSED .compareAndSet (this , false , true )) { // volatile read/write
105- RuntimeException t = null ;
106- try {
107- this .destructor .destroy (this .object , this .creationRequest );
108- } catch (final RuntimeException e ) {
109- t = e ;
110- } finally {
111- try {
112- this .releaser .close ();
113- } catch (final RuntimeException e ) {
114- if (t == null ) {
115- throw e ;
116- }
117- t .addSuppressed (e );
118- } catch (final InterruptedException e ) {
119- Thread .currentThread ().interrupt ();
120- if (t == null ) {
121- throw new ScopeletException (e .getMessage (), e );
122- }
123- t .addSuppressed (e );
124- } catch (final Exception e ) {
125- if (t == null ) {
126- throw new ScopeletException (e .getMessage (), e );
127- }
128- t .addSuppressed (e );
129- }
130- }
131- if (t != null ) {
132- throw t ;
104+ try (this .destruction ) {
105+ this .destructor .destroy (this .object , this .destruction );
133106 }
134107 }
135108 }
@@ -143,14 +116,7 @@ public final boolean closed() {
143116 return this .closed ; // volatile read
144117 }
145118
146- @ Override
147- public final int hashCode () {
148- // We don't want "closedness" to factor in here because it isn't part of equals(). But we want to use the results of
149- // get(). Fortunately, that method is final. So we can just use direct field access.
150- return this .object .hashCode ();
151- }
152-
153- @ Override
119+ @ Override // Object
154120 public final boolean equals (final Object other ) {
155121 if (other == this ) {
156122 return true ;
@@ -163,11 +129,37 @@ public final boolean equals(final Object other) {
163129 }
164130 }
165131
166- @ Override
132+ /**
133+ * Returns the contextual instance this {@link Instance} holds, which may be {@code null}.
134+ *
135+ * @return the contextual instance this {@link Instance} holds, which may be {@code null}
136+ */
137+ @ Override // Supplier<I>
138+ public final I get () {
139+ if (this .closed ()) { // volatile read, effectively
140+ throw new IllegalStateException ("closed" );
141+ }
142+ return this .object ;
143+ }
144+
145+ @ Override // Object
146+ public final int hashCode () {
147+ // We don't want "closedness" to factor in here because it isn't part of equals(). But we want to use the results of
148+ // get(). Fortunately, that method is final. So we can just use direct field access.
149+ return this .object .hashCode ();
150+ }
151+
152+ @ Override // Object
167153 public final String toString () {
168154 return String .valueOf (this .object );
169155 }
170156
157+
158+ /*
159+ * Static methods.
160+ */
161+
162+
171163 private static final void sink () {
172164
173165 }
@@ -176,12 +168,25 @@ private static final <A, B> void sink(final A a, final B b) {
176168
177169 }
178170
171+
172+ /*
173+ * Inner and nested classes.
174+ */
175+
176+
179177 /**
180178 * An interface whose implementations can destroy contextual instances.
181179 *
182- * @param <I> the type borne by instances
180+ * <p>This is commonly implemented in terms of a method reference to the {@link
181+ * org.microbean.bean.Factory#destroy(Object, Destruction)} method.</p>
182+ *
183+ * @param <I> the contextual instance type
183184 *
184185 * @author <a href="https://about.me/lairdnelson" target="_top">Laird Nelson</a>
186+ *
187+ * @see Destruction
188+ *
189+ * @see org.microbean.bean.Factory#destroy(Object, Destruction)
185190 */
186191 @ FunctionalInterface
187192 public static interface Destructor <I > {
@@ -191,9 +196,10 @@ public static interface Destructor<I> {
191196 *
192197 * @param i the contextual instance to destroy; may be {@code null}
193198 *
194- * @param creationRequest the {@link Request} that caused the contextual instance to be created; may be {@code null}
199+ * @param creation the {@link Destruction} view of the {@link org.microbean.bean.Creation} implementation that
200+ * caused the contextual instance to be created; may be {@code null}
195201 */
196- public void destroy (final I i , final Request < I > creationRequest );
202+ public void destroy (final I i , final Destruction creation );
197203
198204 }
199205
0 commit comments