1717
1818import com .mongodb .annotations .NotThreadSafe ;
1919import com .mongodb .internal .async .SingleResultCallback ;
20+ import com .mongodb .internal .async .function .CallbackChain .Element ;
2021import com .mongodb .lang .Nullable ;
2122
2223import java .util .function .Supplier ;
3940 */
4041@ NotThreadSafe
4142public final class AsyncCallbackLoop implements AsyncCallbackRunnable {
42- @ Nullable
43- private final CallbackChain chain ;
4443 private final LoopState state ;
45- private final AsyncCallbackRunnable body ;
44+ private final Body body ;
4645
4746 /**
4847 * @param state The {@link LoopState} to be deemed as initial for the purpose of the new {@link AsyncCallbackLoop}.
@@ -53,43 +52,67 @@ public AsyncCallbackLoop(final LoopState state, final AsyncCallbackRunnable body
5352 }
5453
5554 public AsyncCallbackLoop (final boolean optimized , final LoopState state , final AsyncCallbackRunnable body ) {
56- this .chain = optimized ? new CallbackChain () : null ;
5755 this .state = state ;
58- this .body = body ;
56+ this .body = new Body ( optimized , body ) ;
5957 }
6058
6159 @ Override
6260 public void run (final SingleResultCallback <Void > callback ) {
6361 body .run (new LoopingCallback (callback ));
6462 }
6563
64+ private static final class Body {
65+ private final AsyncCallbackRunnable wrapped ;
66+ @ Nullable
67+ private final CallbackChain chain ;
68+
69+ private Body (final boolean optimized , final AsyncCallbackRunnable body ) {
70+ this .wrapped = body ;
71+ this .chain = optimized ? new CallbackChain () : null ;
72+ }
73+
74+ @ Nullable
75+ Element run (final LoopingCallback loopingCallback ) {
76+ Element [] mutableElement = new Element [1 ];
77+ wrapped .run ((r , t ) -> {
78+ Element nextCallbackToComplete = loopingCallback .onResult (r , t );
79+ if (!CallbackChain .execute (chain , nextCallbackToComplete )) {
80+ mutableElement [0 ] = nextCallbackToComplete ;
81+ }
82+ });
83+ return mutableElement [0 ];
84+ }
85+ }
86+
6687 /**
6788 * This callback is allowed to be completed more than once.
6889 */
6990 @ NotThreadSafe
70- private class LoopingCallback implements SingleResultCallback < Void > {
91+ private class LoopingCallback {
7192 private final SingleResultCallback <Void > wrapped ;
7293
7394 LoopingCallback (final SingleResultCallback <Void > callback ) {
7495 wrapped = callback ;
7596 }
7697
77- @ Override
78- public void onResult (@ Nullable final Void result , @ Nullable final Throwable t ) {
98+ @ Nullable
99+ public Element onResult (@ Nullable final Void result , @ Nullable final Throwable t ) {
79100 if (t != null ) {
80101 wrapped .onResult (null , t );
102+ return null ;
81103 } else {
82104 boolean continueLooping ;
83105 try {
84106 continueLooping = state .advance ();
85107 } catch (Throwable e ) {
86108 wrapped .onResult (null , e );
87- return ;
109+ return null ;
88110 }
89111 if (continueLooping ) {
90- CallbackChain . execute ( chain , () -> body .run (this ) );
112+ return () -> body .run (this );
91113 } else {
92114 wrapped .onResult (result , null );
115+ return null ;
93116 }
94117 }
95118 }
0 commit comments