private static bool TryNumericConversion <T>(object source, out T result) { Fx.Assert(source != null, "caller must verify"); TypeCode sourceTypeCode = source.GetType().GetTypeCode(); TypeCode destinationTypeCode = typeof(T).GetTypeCode(); switch (sourceTypeCode) { case TypeCode.SByte: { SByte sbyteSource = (SByte)source; switch (destinationTypeCode) { case TypeCode.Int16: result = (T)(object)(Int16)sbyteSource; return(true); case TypeCode.Int32: result = (T)(object)(Int32)sbyteSource; return(true); case TypeCode.Int64: result = (T)(object)(Int64)sbyteSource; return(true); case TypeCode.Single: result = (T)(object)(Single)sbyteSource; return(true); case TypeCode.Double: result = (T)(object)(Double)sbyteSource; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)sbyteSource; return(true); } break; } case TypeCode.Byte: { Byte byteSource = (Byte)source; switch (destinationTypeCode) { case TypeCode.Int16: result = (T)(object)(Int16)byteSource; return(true); case TypeCode.UInt16: result = (T)(object)(UInt16)byteSource; return(true); case TypeCode.Int32: result = (T)(object)(Int32)byteSource; return(true); case TypeCode.UInt32: result = (T)(object)(UInt32)byteSource; return(true); case TypeCode.Int64: result = (T)(object)(Int64)byteSource; return(true); case TypeCode.UInt64: result = (T)(object)(UInt64)byteSource; return(true); case TypeCode.Single: result = (T)(object)(Single)byteSource; return(true); case TypeCode.Double: result = (T)(object)(Double)byteSource; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)byteSource; return(true); } break; } case TypeCode.Int16: { Int16 int16Source = (Int16)source; switch (destinationTypeCode) { case TypeCode.Int32: result = (T)(object)(Int32)int16Source; return(true); case TypeCode.Int64: result = (T)(object)(Int64)int16Source; return(true); case TypeCode.Single: result = (T)(object)(Single)int16Source; return(true); case TypeCode.Double: result = (T)(object)(Double)int16Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)int16Source; return(true); } break; } case TypeCode.UInt16: { UInt16 uint16Source = (UInt16)source; switch (destinationTypeCode) { case TypeCode.Int32: result = (T)(object)(Int32)uint16Source; return(true); case TypeCode.UInt32: result = (T)(object)(UInt32)uint16Source; return(true); case TypeCode.Int64: result = (T)(object)(Int64)uint16Source; return(true); case TypeCode.UInt64: result = (T)(object)(UInt64)uint16Source; return(true); case TypeCode.Single: result = (T)(object)(Single)uint16Source; return(true); case TypeCode.Double: result = (T)(object)(Double)uint16Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)uint16Source; return(true); } break; } case TypeCode.Int32: { Int32 int32Source = (Int32)source; switch (destinationTypeCode) { case TypeCode.Int64: result = (T)(object)(Int64)int32Source; return(true); case TypeCode.Single: result = (T)(object)(Single)int32Source; return(true); case TypeCode.Double: result = (T)(object)(Double)int32Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)int32Source; return(true); } break; } case TypeCode.UInt32: { UInt32 uint32Source = (UInt32)source; switch (destinationTypeCode) { case TypeCode.UInt32: result = (T)(object)(UInt32)uint32Source; return(true); case TypeCode.Int64: result = (T)(object)(Int64)uint32Source; return(true); case TypeCode.UInt64: result = (T)(object)(UInt64)uint32Source; return(true); case TypeCode.Single: result = (T)(object)(Single)uint32Source; return(true); case TypeCode.Double: result = (T)(object)(Double)uint32Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)uint32Source; return(true); } break; } case TypeCode.Int64: { Int64 int64Source = (Int64)source; switch (destinationTypeCode) { case TypeCode.Single: result = (T)(object)(Single)int64Source; return(true); case TypeCode.Double: result = (T)(object)(Double)int64Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)int64Source; return(true); } break; } case TypeCode.UInt64: { UInt64 uint64Source = (UInt64)source; switch (destinationTypeCode) { case TypeCode.Single: result = (T)(object)(Single)uint64Source; return(true); case TypeCode.Double: result = (T)(object)(Double)uint64Source; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)uint64Source; return(true); } break; } case TypeCode.Char: { Char charSource = (Char)source; switch (destinationTypeCode) { case TypeCode.UInt16: result = (T)(object)(UInt16)charSource; return(true); case TypeCode.Int32: result = (T)(object)(Int32)charSource; return(true); case TypeCode.UInt32: result = (T)(object)(UInt32)charSource; return(true); case TypeCode.Int64: result = (T)(object)(Int64)charSource; return(true); case TypeCode.UInt64: result = (T)(object)(UInt64)charSource; return(true); case TypeCode.Single: result = (T)(object)(Single)charSource; return(true); case TypeCode.Double: result = (T)(object)(Double)charSource; return(true); case TypeCode.Decimal: result = (T)(object)(Decimal)charSource; return(true); } break; } case TypeCode.Single: { if (destinationTypeCode == TypeCode.Double) { result = (T)(object)(Double)(Single)source; return(true); } break; } } result = default(T); return(false); }
private static bool CanCompensationOrConfirmationHandlerReferenceAddedSymbols(InstanceList instanceList, DynamicUpdateMap rootUpdateMap, IdSpace rootIdSpace, List <ActivityInstance> secondaryRootInstances, ref Collection <ActivityBlockingUpdate> updateErrors) { for (int j = 0; j < instanceList.Count; j++) { ActivityInstance activityInstance = instanceList[j] as ActivityInstance; if (activityInstance == null || !IsNonDefaultSecondaryRoot(activityInstance, secondaryRootInstances)) { continue; } // here, find out if the given non-default secondary root references an environment to which a symbol is to be added via DU. // we start from a secondary root instead of starting from the enviroment with the already completed owner that was added symbols. // It is becuase for the case of adding symbols to noSymbols activities, the environment doesn't even exist from which we can start looking for referencing secondary root. int[] secondaryRootOriginalQID = new QualifiedId(instanceList.ActivityId).AsIDArray(); Fx.Assert(secondaryRootOriginalQID != null && secondaryRootOriginalQID.Length > 1, "CompensationParticipant is always an implementation child of a CompensableActivity, therefore it's IdSpace must be at least one level deep."); int[] parentOfSecondaryRootOriginalQID = new int[secondaryRootOriginalQID.Length - 1]; Array.Copy(secondaryRootOriginalQID, parentOfSecondaryRootOriginalQID, secondaryRootOriginalQID.Length - 1); List <int> currentQIDBuilder = new List <int>(); for (int i = 0; i < parentOfSecondaryRootOriginalQID.Length; i++) { // // for each iteration of this for-loop, // we are finding out if at every IdSpace level the map has any map entry whose activity has the CompensableActivity as an implementation decendant. // The map may not exist for every IdSpace between the root and the CompensableActivity. // If the matching map and the entry is found, then we find out if that matching entry's activity is a public decendant of any NoSymbols activity DU is to add variables or arguments to. // // This walk on the definition activity tree determines the hypothetical execution-time chain of instances and environments. // The ultimate goal is to prevent adding variables or arguments to a NoSymbols activity which has already completed, // but its decendant CompensableActivity's compensation or confirmation handlers in the future may need to reference the added variables or arguments. currentQIDBuilder.Add(parentOfSecondaryRootOriginalQID[i]); DynamicUpdateMap.UpdatedActivity updatedActivity = rootUpdateMap.GetUpdatedActivity(new QualifiedId(currentQIDBuilder.ToArray()), rootIdSpace); if (updatedActivity.MapEntry != null) { // the activity of this entry either has the CompensableActivity as an implementation decendant, or is the CompensableActivity itself. // walk the same-IdSpace-parent chain of the entry, // look for an entry whose EnvironmentUpdateMap.IsAdditionToNoSymbols is true. DynamicUpdateMapEntry entry = updatedActivity.MapEntry; do { if (!entry.IsRemoval && entry.HasEnvironmentUpdates && entry.EnvironmentUpdateMap.IsAdditionToNoSymbols) { int[] noSymbolAddActivityIDArray = currentQIDBuilder.ToArray(); noSymbolAddActivityIDArray[noSymbolAddActivityIDArray.Length - 1] = entry.OldActivityId; QualifiedId noSymbolAddActivityQID = new QualifiedId(noSymbolAddActivityIDArray); DynamicUpdateMap.UpdatedActivity noSymbolAddUpdatedActivity = rootUpdateMap.GetUpdatedActivity(noSymbolAddActivityQID, rootIdSpace); AddBlockingActivity(ref updateErrors, noSymbolAddUpdatedActivity, noSymbolAddActivityQID, SR.VariableOrArgumentAdditionToReferencedEnvironmentNoDUSupported, null); return(true); } entry = entry.Parent; } while (entry != null); } } } return(false); }
// this is called after all instances have been loaded and fixedup public void UpdateInstanceByActivityParticipation(ActivityExecutor activityExecutor, DynamicUpdateMap rootMap, ref Collection <ActivityBlockingUpdate> updateErrors) { foreach (InstanceListNeedingUpdate participant in this.updateList) { if (participant.NothingChanged || participant.ParentIdShiftOnly) { Fx.Assert(participant.UpdateMap == null && participant.MapEntry == null, "UpdateMap and MapEntry must be null if we are here."); // create a temporary NoChanges UpdateMap as well as a temporary no change MapEntry // so that we can create a NativeActivityUpdateContext object in order to invoke UpdateInstance() on an activity which // doesn't have a corresponding map and an map entry. // The scenario enabled here is scheduling a newly added reference branch to a Parallel inside an activity's implementation. participant.UpdateMap = DynamicUpdateMap.DummyMap; participant.MapEntry = DynamicUpdateMapEntry.DummyMapEntry; } // now let activities participate in update for (int i = 0; i < participant.InstanceList.Count; i++) { ActivityInstance instance = participant.InstanceList[i] as ActivityInstance; if (instance == null) { continue; } IInstanceUpdatable activity = instance.Activity as IInstanceUpdatable; if (activity != null && instance.SubState == ActivityInstance.Substate.Executing) { NativeActivityUpdateContext updateContext = new NativeActivityUpdateContext(this, activityExecutor, instance, participant.UpdateMap, participant.MapEntry, rootMap); try { activity.InternalUpdateInstance(updateContext); if (updateContext.IsUpdateDisallowed) { ActivityBlockingUpdate.AddBlockingActivity(ref updateErrors, instance.Activity, new QualifiedId(participant.OriginalId).ToString(), updateContext.DisallowedReason, instance.Id); continue; } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.NativeActivityUpdateInstanceThrewException(e.Message), e)); } finally { updateContext.Dispose(); } } } } // Schedule evaluation of newly added arguments and newly added variables. // This needs to happen after all the invokations of UpdateInstance above, so that newly // added arguments and newly added variables get evaluated before any newly added activities get executed. // We iterate the list in reverse so that parents are always scheduled after (and thus // execute before) their children, which may depend on the parents. for (int i = this.updateList.Count - 1; i >= 0; i--) { InstanceListNeedingUpdate participant = this.updateList[i]; if (!participant.MapEntryExists) { // if the given InstanceList has no map entry, // then there is no new LocationReferences to resolve. continue; } Fx.Assert(participant.MapEntry != null, "MapEntry must be non-null here."); if (!participant.MapEntry.HasEnvironmentUpdates) { // if there is no environment updates for this MapEntry, // then there is no new LocationReferences to resolve. continue; } for (int j = 0; j < participant.InstanceList.Count; j++) { ActivityInstance instance = participant.InstanceList[j] as ActivityInstance; if (instance == null || instance.SubState != ActivityInstance.Substate.Executing) { // if the given ActivityInstance is not in Substate.Executing, // then, do not try to resolve new LocationReferences continue; } List <int> addedArgumentIndexes; List <int> addedVariableIndexes; List <int> addedPrivateVariableIndexes; EnvironmentUpdateMap envMap = participant.MapEntry.EnvironmentUpdateMap; if (envMap.HasVariableEntries && TryGatherSchedulableExpressions(envMap.VariableEntries, out addedVariableIndexes)) { // schedule added variable default expressions instance.ResolveNewVariableDefaultsDuringDynamicUpdate(activityExecutor, addedVariableIndexes, false); } if (envMap.HasPrivateVariableEntries && TryGatherSchedulableExpressions(envMap.PrivateVariableEntries, out addedPrivateVariableIndexes)) { // schedule added private variable default expressions // HasPrivateMemberChanged() check disallows addition of private variable default that offsets the private IdSpace, // However, the added private variable default expression can be an imported activity, which has no affect on the private IdSpace. // For such case, we want to be able to schedule the imported default expressions here. instance.ResolveNewVariableDefaultsDuringDynamicUpdate(activityExecutor, addedPrivateVariableIndexes, true); } if (envMap.HasArgumentEntries && TryGatherSchedulableExpressions(envMap.ArgumentEntries, out addedArgumentIndexes)) { // schedule added arguments instance.ResolveNewArgumentsDuringDynamicUpdate(activityExecutor, addedArgumentIndexes); } } } }
internal void PurgeSingleBookmark(Bookmark bookmark) { Fx.Assert(this.bookmarks.ContainsKey(bookmark) && object.ReferenceEquals(bookmark, this.bookmarks[bookmark].Bookmark), "Something went wrong with our housekeeping - it must exist and must be our intenral reference"); UpdateExclusiveHandleList(bookmark); this.bookmarks.Remove(bookmark); }
internal void Update(EnvironmentUpdateMap map, Activity activity) { // arguments public variables private variables RuntimeDelegateArguments // Locations array: AAAAAAAAAA VVVVVVVVVVVVVVVVVVVVVV PPPPPPPPPPPPPPPPPPP DDDDDDDDDDDDDDDDDDDDDDDDDDDDDD int actualRuntimeDelegateArgumentCount = activity.HandlerOf == null ? 0 : activity.HandlerOf.RuntimeDelegateArguments.Count; if (map.NewArgumentCount != activity.RuntimeArguments.Count || map.NewVariableCount != activity.RuntimeVariables.Count || map.NewPrivateVariableCount != activity.ImplementationVariables.Count || map.RuntimeDelegateArgumentCount != actualRuntimeDelegateArgumentCount) { throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidUpdateMap( SR.WrongEnvironmentCount(activity, map.NewArgumentCount, map.NewVariableCount, map.NewPrivateVariableCount, map.RuntimeDelegateArgumentCount, activity.RuntimeArguments.Count, activity.RuntimeVariables.Count, activity.ImplementationVariables.Count, actualRuntimeDelegateArgumentCount)))); } int expectedLocationCount = map.OldArgumentCount + map.OldVariableCount + map.OldPrivateVariableCount + map.RuntimeDelegateArgumentCount; int actualLocationCount; if (this.locations == null) { if (this.singleLocation == null) { // we can hit this condition when the root activity instance has zero symbol. actualLocationCount = 0; } else { actualLocationCount = 1; // temporarily normalize to locations array for the sake of environment update processing this.locations = new Location[] { this.singleLocation }; this.singleLocation = null; } } else { Fx.Assert(this.singleLocation == null, "locations and singleLocations cannot be non-null at the same time."); actualLocationCount = this.locations.Length; } if (expectedLocationCount != actualLocationCount) { throw FxTrace.Exception.AsError(new InstanceUpdateException(SR.InvalidUpdateMap( SR.WrongOriginalEnvironmentCount(activity, map.OldArgumentCount, map.OldVariableCount, map.OldPrivateVariableCount, map.RuntimeDelegateArgumentCount, expectedLocationCount, actualLocationCount)))); } Location[] newLocations = null; // If newTotalLocations == 0, update will leave us with an empty LocationEnvironment, // which is something the runtime would normally never create. This is harmless, but it // is a loosening of normal invariants. int newTotalLocations = map.NewArgumentCount + map.NewVariableCount + map.NewPrivateVariableCount + map.RuntimeDelegateArgumentCount; if (newTotalLocations > 0) { newLocations = new Location[newTotalLocations]; } UpdateArguments(map, newLocations); UnregisterRemovedVariables(map); UpdatePublicVariables(map, newLocations, activity); UpdatePrivateVariables(map, newLocations, activity); CopyRuntimeDelegateArguments(map, newLocations); Location newSingleLocation = null; if (newTotalLocations == 1) { newSingleLocation = newLocations[0]; newLocations = null; } this.singleLocation = newSingleLocation; this.locations = newLocations; }
public void CheckForCancelation() { Fx.Assert(this.callbackWrapper != null, "We must have a callback wrapper if we are calling this."); this.callbackWrapper.CheckForCancelation(); }
public override bool Execute(ActivityExecutor executor, BookmarkManager bookmarkManager) { Fx.Assert("Empty work items should never been executed."); return(true); }
private void SetDeadline() { Fx.Assert(!_deadlineSet, "TimeoutHelper deadline set twice."); _deadline = DateTime.UtcNow + _originalTimeout; _deadlineSet = true; }
protected void Complete(bool completedSynchronously) { if (this.IsCompleted) { throw Fx.Exception.AsError(new InvalidOperationException(SR.AsyncResultCompletedTwice(this.GetType()))); } //#if DEBUG // this.marker.AsyncResult = null; // this.marker = null; // if (!Fx.FastDebug && completeStack == null) // { // completeStack = new StackTrace(); // } //#endif this.CompletedSynchronously = completedSynchronously; if (this.OnCompleting != null) { // Allow exception replacement, like a catch/throw pattern. try { this.OnCompleting(this, this._exception); } catch (Exception exception) { if (Fx.IsFatal(exception)) { throw; } this._exception = exception; } } if (completedSynchronously) { // If we completedSynchronously, then there's no chance that the manualResetEvent // was created so we don't need to worry about a race condition Fx.Assert(this._manualResetEvent == null, "No ManualResetEvent should be created for a synchronous AsyncResult."); this.IsCompleted = true; } else { lock (this.ThisLock) { this.IsCompleted = true; if (this._manualResetEvent != null) { this._manualResetEvent.Set(); } } } if (this._callback != null) { try { if (this.VirtualCallback != null) { this.VirtualCallback(this._callback, this); } else { this._callback(this); } } #pragma warning disable 1634 #pragma warning suppress 56500 // transferring exception to another thread catch (Exception e) { if (Fx.IsFatal(e)) { throw; } throw Fx.Exception.AsError(new CallbackException(SR.AsyncCallbackThrewException, e)); } #pragma warning restore 1634 } }
public BookmarkResumptionResult TryGenerateWorkItem(ActivityExecutor executor, ref Bookmark bookmark, BookmarkScope scope, object value, ActivityInstance isolationInstance, bool nonScopedBookmarksExist, out ActivityExecutionWorkItem workItem) { Fx.Assert(scope != null, "We should never have a null sub instance."); workItem = null; BookmarkScope lookupScope = scope; if (scope.IsDefault) { lookupScope = this.defaultScope; } // We don't really care about the return value since we'll // use null to know we should check uninitialized sub instances this.bookmarkManagers.TryGetValue(lookupScope, out BookmarkManager manager); if (manager == null) { Fx.Assert(lookupScope != null, "The sub instance should not be default if we are here."); BookmarkResumptionResult finalResult = BookmarkResumptionResult.NotFound; // Check the uninitialized sub instances for a matching bookmark if (this.uninitializedScopes != null) { for (int i = 0; i < this.uninitializedScopes.Count; i++) { BookmarkScope uninitializedScope = this.uninitializedScopes[i]; Fx.Assert(this.bookmarkManagers.ContainsKey(uninitializedScope), "We must always have the uninitialized sub instances."); BookmarkResumptionResult resumptionResult; if (!this.bookmarkManagers[uninitializedScope].TryGetBookmarkFromInternalList(bookmark, out Bookmark internalBookmark, out BookmarkCallbackWrapper callbackWrapper)) { resumptionResult = BookmarkResumptionResult.NotFound; } else if (IsExclusiveScopeUnstable(internalBookmark)) { resumptionResult = BookmarkResumptionResult.NotReady; } else { resumptionResult = this.bookmarkManagers[uninitializedScope].TryGenerateWorkItem(executor, true, ref bookmark, value, isolationInstance, out workItem); } if (resumptionResult == BookmarkResumptionResult.Success) { // We are using InitializeBookmarkScopeWithoutKeyAssociation because we know this is a new uninitialized scope and // the key we would associate is already associated. And if we did the association here, the subsequent call to // FlushBookmarkScopeKeys would try to flush it out, but it won't have the transaction correct so will hang waiting for // the transaction that has the PersistenceContext locked to complete. But it won't complete successfully until // we finish processing here. InitializeBookmarkScopeWithoutKeyAssociation(uninitializedScope, scope.Id); // We've found what we were looking for return(BookmarkResumptionResult.Success); } else if (resumptionResult == BookmarkResumptionResult.NotReady) { // This uninitialized sub-instance has a matching bookmark but // it can't currently be resumed. We won't return BookmarkNotFound // because of this. finalResult = BookmarkResumptionResult.NotReady; } else { if (finalResult == BookmarkResumptionResult.NotFound) { // If we still are planning on returning failure then // we'll incur the cost of seeing if this scope is // stable or not. if (!IsStable(uninitializedScope, nonScopedBookmarksExist)) { // There exists an uninitialized scope which is unstable. // At the very least this means we'll return NotReady since // this uninitialized scope might eventually contain this // bookmark. finalResult = BookmarkResumptionResult.NotReady; } } } } }