/// <summary>Update the Task with the state of a ready Future</summary> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion() { if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES Debug.WriteLine("FutureArray<" + typeof(T).Name + ">.Callback(...) handling completion on thread #" + Thread.CurrentThread.ManagedThreadId.ToString()); #endif try { UnregisterCancellationRegistration(); List <Exception>?errors = null; bool cancellation = false; var selector = m_resultSelector; var results = selector != null ? new T[m_handles.Length] : null; for (int i = 0; i < m_handles.Length; i++) { var handle = m_handles[i]; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err) !; (errors ??= new List <Exception>()).Add(ex); } else { cancellation = true; break; } } else { // it succeeded... // try to get the result... if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... results ![i] = selector(handle);
/// <summary>Update the Task with the state of a ready Future</summary> /// <param name="fromCallback">If true, we are called from the network thread</param> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion(bool fromCallback) { // note: if fromCallback is true, we are running on the network thread // this means that we have to signal the TCS from the threadpool, if not continuations on the task may run inline. // this is very frequent when we are called with await, or ContinueWith(..., TaskContinuationOptions.ExecuteSynchronously) if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES var sw = Stopwatch.StartNew(); #endif try { var handle = m_handle; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { UnregisterCancellationRegistration(); FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has FAILED: " + err); #endif if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err); SetFaulted(ex, fromCallback); return; } //else: will be handle below } else { // it succeeded... // try to get the result... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has completed successfully"); #endif var selector = m_resultSelector; if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... var result = selector(handle); SetResult(result, fromCallback); return; } //else: it will be handled below } } // most probably the future was cancelled or we are shutting down... SetCanceled(fromCallback); } catch (Exception e) { // something went wrong if (e is ThreadAbortException) { SetCanceled(fromCallback); throw; } SetFaulted(e, fromCallback); } finally { #if DEBUG_FUTURES sw.Stop(); Debug.WriteLine("Future<" + typeof(T).Name + "> callback completed in " + sw.Elapsed.TotalMilliseconds.ToString() + " ms"); #endif TryCleanup(); } }
/// <summary>Update the Task with the state of a ready Future</summary> /// <returns>True if we got a result, or false in case of error (or invalid state)</returns> private void HandleCompletion() { if (HasAnyFlags(FdbFuture.Flags.DISPOSED | FdbFuture.Flags.COMPLETED)) { return; } #if DEBUG_FUTURES var sw = Stopwatch.StartNew(); #endif try { var handle = m_handle; if (handle != null && !handle.IsClosed && !handle.IsInvalid) { UnregisterCancellationRegistration(); FdbError err = FdbNative.FutureGetError(handle); if (Fdb.Failed(err)) { // it failed... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has FAILED: " + err); #endif if (err != FdbError.OperationCancelled) { // get the exception from the error code var ex = Fdb.MapToException(err) !; TrySetException(ex); return; } //else: will be handle below } else { // it succeeded... // try to get the result... #if DEBUG_FUTURES Debug.WriteLine("Future<" + typeof(T).Name + "> has completed successfully"); #endif var selector = m_resultSelector; if (selector != null) { //note: result selector will execute from network thread, but this should be our own code that only calls into some fdb_future_get_XXXX(), which should be safe... var result = selector(handle); TrySetResult(result); return; } //else: it will be handled below } } // most probably the future was cancelled or we are shutting down... TrySetCanceled(); } catch (Exception e) { // something went wrong if (e is ThreadAbortException) { TrySetCanceled(); throw; } TrySetException(e); } finally { #if DEBUG_FUTURES sw.Stop(); Debug.WriteLine("Future<" + typeof(T).Name + "> callback completed in " + sw.Elapsed.TotalMilliseconds.ToString() + " ms"); #endif TryCleanup(); } }