Пример #1
0
        void ActivityInstanceMap.IActivityReferenceWithEnvironment.UpdateEnvironment(EnvironmentUpdateMap map, Activity activity)
        {
            Fx.Assert(this.SubState != Substate.ResolvingVariables, "We must have already performed the same validations in advance.");
            Fx.Assert(this.SubState != Substate.ResolvingArguments, "We must have already performed the same validations in advance.");

            if (this.SerializedNoSymbols)
            {
                // create a new LocationReference and this ActivityInstance becomes the owner of the
                // created environment.
                var oldParentEnvironment = this.environment;

                Fx.Assert(oldParentEnvironment != null, "environment must never be null.");

                this.environment         = new LocationEnvironment(oldParentEnvironment, map.NewArgumentCount + map.NewVariableCount + map.NewPrivateVariableCount + map.RuntimeDelegateArgumentCount);
                this.SerializedNoSymbols = false;

                // traverse the activity instance chain. Update all its non-environment-owning
                // decedent instances to point to the newly created enviroment, and, update all its
                // environment-owning decendent instances to have their environment's parent to
                // point to the newly created environment.
                UpdateLocationEnvironmentHierarchy(oldParentEnvironment, this.environment, this);
            }

            this.Environment.Update(map, activity);
        }
Пример #2
0
 void CopyRuntimeDelegateArguments(EnvironmentUpdateMap map, Location[] newLocations)
 {
     for (int i = 1; i <= map.RuntimeDelegateArgumentCount; i++)
     {
         newLocations[newLocations.Length - i] = this.locations[this.locations.Length - i];
     }
 }
Пример #3
0
        private static bool IsInvalidEnvironmentUpdate(InstanceList instanceList, DynamicUpdateMap.UpdatedActivity updatedActivity, ref Collection <ActivityBlockingUpdate> updateErrors)
        {
            if (updatedActivity.MapEntry == null || !updatedActivity.MapEntry.HasEnvironmentUpdates)
            {
                return(false);
            }

            for (int j = 0; j < instanceList.Count; j++)
            {
                ActivityInstance activityInstance = instanceList[j] as ActivityInstance;
                if (activityInstance != null)
                {
                    string error = null;
                    if (activityInstance.SubState == ActivityInstance.Substate.ResolvingVariables)
                    {
                        // if the entry has Environment update to do when the instance is in the
                        // middle of resolving variable, it is an error.
                        error = SR.CannotUpdateEnvironmentInTheMiddleOfResolvingVariables;
                    }
                    else if (activityInstance.SubState == ActivityInstance.Substate.ResolvingArguments)
                    {
                        // if the entry has Environment update to do when the instance is in the
                        // middle of resolving arguments, it is an error.
                        error = SR.CannotUpdateEnvironmentInTheMiddleOfResolvingArguments;
                    }

                    if (error != null)
                    {
                        AddBlockingActivity(ref updateErrors, updatedActivity, new QualifiedId(instanceList.ActivityId), error, activityInstance.Id);
                        return(true);
                    }
                }
                else
                {
                    LocationEnvironment environment = instanceList[j] as LocationEnvironment;
                    if (environment != null)
                    {
                        // environment that is referenced by a secondary root Adding a variable or
                        // argument that requires expression scheduling to this instanceless
                        // environment is not allowed.
                        List <int>           dummyIndexes;
                        EnvironmentUpdateMap envMap = updatedActivity.MapEntry.EnvironmentUpdateMap;

                        if ((envMap.HasVariableEntries && TryGatherSchedulableExpressions(envMap.VariableEntries, out dummyIndexes)) ||
                            (envMap.HasPrivateVariableEntries && TryGatherSchedulableExpressions(envMap.PrivateVariableEntries, out dummyIndexes)) ||
                            (envMap.HasArgumentEntries && TryGatherSchedulableExpressions(envMap.ArgumentEntries, out dummyIndexes)))
                        {
                            AddBlockingActivity(ref updateErrors, updatedActivity, new QualifiedId(instanceList.ActivityId), SR.VariableOrArgumentAdditionToReferencedEnvironmentNoDUSupported, null);
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Пример #4
0
 void UpdatePrivateVariables(EnvironmentUpdateMap map, Location[] newLocations, Activity activity)
 {
     UpdateVariables(
         map.NewArgumentCount + map.NewVariableCount,
         map.OldArgumentCount + map.OldVariableCount,
         map.NewPrivateVariableCount,
         map.OldPrivateVariableCount,
         map.PrivateVariableEntries,
         activity.ImplementationVariables,
         newLocations);
 }
Пример #5
0
 void UpdatePublicVariables(EnvironmentUpdateMap map, Location[] newLocations, Activity activity)
 {
     UpdateVariables(
         map.NewArgumentCount,
         map.OldArgumentCount,
         map.NewVariableCount,
         map.OldVariableCount,
         map.VariableEntries,
         activity.RuntimeVariables,
         newLocations);
 }
Пример #6
0
        void UnregisterRemovedVariables(EnvironmentUpdateMap map)
        {
            bool hasMappableLocationsRemaining = false;
            int  offset = map.OldArgumentCount;

            FindVariablesToUnregister(false, map, map.OldVariableCount, offset, ref hasMappableLocationsRemaining);

            offset = map.OldArgumentCount + map.OldVariableCount;

            FindVariablesToUnregister(true, map, map.OldPrivateVariableCount, offset, ref hasMappableLocationsRemaining);

            this.hasMappableLocations = hasMappableLocationsRemaining;
        }
Пример #7
0
 private void FindVariablesToUnregister(bool forImplementation, EnvironmentUpdateMap map, int oldVariableCount, int offset, ref bool hasMappableLocationsRemaining)
 {
     for (int i = 0; i < oldVariableCount; i++)
     {
         Location location = this.locations[i + offset];
         if (location.CanBeMapped)
         {
             if ((forImplementation && map.GetNewPrivateVariableIndex(i).HasValue) || (!forImplementation && map.GetNewVariableIndex(i).HasValue))
             {
                 hasMappableLocationsRemaining = true;
             }
             else
             {
                 ActivityUtilities.Add(ref this.locationsToUnregister, location);
             }
         }
     }
 }
Пример #8
0
        void UpdateArguments(EnvironmentUpdateMap map, Location[] newLocations)
        {
            if (map.HasArgumentEntries)
            {
                for (int i = 0; i < map.ArgumentEntries.Count; i++)
                {
                    EnvironmentUpdateMapEntry entry = map.ArgumentEntries[i];

                    Fx.Assert(entry.NewOffset >= 0 && entry.NewOffset < map.NewArgumentCount, "Argument offset is out of range");

                    if (entry.IsAddition)
                    {
                        // Location allocation will be performed later during ResolveDynamicallyAddedArguments().
                        // for now, simply assign a dummy location so we know not to copy over the old value.
                        newLocations[entry.NewOffset] = dummyLocation;
                    }
                    else
                    {
                        Fx.Assert(this.locations != null && this.singleLocation == null, "Caller should have copied singleLocation into locations array");

                        // rearrangement of existing arguments
                        // this entry here doesn't describe argument removal
                        newLocations[entry.NewOffset] = this.locations[entry.OldOffset];
                    }
                }
            }

            // copy over unchanged Locations, and null out DummyLocations
            for (int i = 0; i < map.NewArgumentCount; i++)
            {
                if (newLocations[i] == null)
                {
                    Fx.Assert(this.locations != null && this.locations.Length > i, "locations must be non-null and index i must be within the range of locations.");
                    newLocations[i] = this.locations[i];
                }
                else if (newLocations[i] == dummyLocation)
                {
                    newLocations[i] = null;
                }
            }
        }
Пример #9
0
 public void UpdateEnvironments(EnvironmentUpdateMap map, Activity activity)
 {
     if (base.SingleItem != null)
     {
         IActivityReferenceWithEnvironment reference = base.SingleItem as IActivityReferenceWithEnvironment;
         if (reference != null)
         {
             reference.UpdateEnvironment(map, activity);
         }
     }
     else
     {
         for (int i = 0; i < base.MultipleItems.Count; i++)
         {
             IActivityReferenceWithEnvironment reference = base.MultipleItems[i] as IActivityReferenceWithEnvironment;
             if (reference != null)
             {
                 reference.UpdateEnvironment(map, activity);
             }
         }
     }
 }
Пример #10
0
        // 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);
                    }
                }
            }
        }
Пример #11
0
        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;
        }
Пример #12
0
 void ActivityInstanceMap.IActivityReferenceWithEnvironment.UpdateEnvironment(EnvironmentUpdateMap map, Activity activity)
 {
     // LocationEnvironment.Update() is invoked through this path when this is a seondary root's environment(and in its parent chain) whose owner has already completed.
     this.Update(map, activity);
 }