Exemplo n.º 1
0
        /// <summary>
        /// Registers a transition into this group.
        /// </summary>
        /// <param name="transition">The transition you want to register.</param>
        /// <param name="type">The type of the registered transition.</param>
        public void RegisterTransition(PNTransition transition, PetriNet.PNTransitionType type)
        {
            this.transitions.Add(transition, type);

            /// Every transition is fireable at the beginning.
            TransitionBecameFireable(transition, true);
        }
Exemplo n.º 2
0
 /// <summary>
 /// Creates an edge from this place to the given transition with the given weight.
 /// </summary>
 /// <param name="target">The target transition of the edge.</param>
 /// <param name="weight">The weight of the edge.</param>
 public void CreateOutputEdge(PNTransition target, int weight)
 {
     if (!this.outputEdges.ContainsKey(target))
     {
         this.outputEdges.Add(target, weight);
     }
     else
     {
         throw new ArgumentException("Output edge to the given target already exists!");
     }
 }
Exemplo n.º 3
0
 /// <summary>
 /// This function is called by a transition that is being fired, when it wants to remove the tokens from it's
 /// input places.
 /// </summary>
 /// <param name="caller">
 /// The transition that called this function.
 /// </param>
 public void RequestTokens(PNTransition caller)
 {
     if (this.outputEdges.ContainsKey(caller))
     {
         int tokenNum = this.outputEdges[caller];
         this.tokens = (this.tokens >= tokenNum) ? (this.tokens - tokenNum) : (0);
         foreach (KeyValuePair <PNTransition, int> edge in this.outputEdges)
         {
             if (this.tokens < edge.Value)
             {
                 edge.Key.FireConditionChange(this, false);
             }
         }
     }
     else
     {
         throw new PetriNetException("Not enough tokens for the given transition!");
     }
 }
Exemplo n.º 4
0
 /// <summary>
 /// This function is called if a transition became fireable or unfireable.
 /// </summary>
 /// <param name="caller">The caller transition.</param>
 /// <param name="fireable">True if the transition became fireable, false if it became unfireable.</param>
 public void TransitionBecameFireable(PNTransition caller, bool fireable)
 {
     if (fireable)
     {
         /// Add the transition to the fireable transition set, and release the event if this is the first
         /// fireable transition.
         if (this.fireableTransitions.Count == 0)
         {
             this.releaseEvent.Set();
         }
         this.fireableTransitions.Add(caller);
     }
     else
     {
         /// Remove the transition from the fireable transition set and reset the release event if necessary.
         this.fireableTransitions.Remove(caller);
         if (this.fireableTransitions.Count == 0)
         {
             this.releaseEvent.Reset();
         }
     }
 }
Exemplo n.º 5
0
        /// <summary>
        /// Call this function from a thread to attach that thread to the Petri-network. The Petri-network will automatically
        /// synchronize the attached threads depending on it's structure.
        /// </summary>
        /// <param name="externalTransitions">
        /// List of the external transitions that the thread wants to fire. The thread will be blocked until at least one
        /// of these transitions becomes fireable.
        /// </param>
        /// <param name="callbackFunctions">
        /// This map has to assign a callback function for each callback transitions.
        /// </param>
        /// <remarks>
        /// The caller thread will be blocked until at least one of the given external transitions becomes fireable. Then
        /// the Petri-network will synchronize the thread while a callback transition becomes fireable. Then this transition
        /// will be fired, the assigned callback function will be called, and the thread will be detached from the
        /// Petri-network.
        /// </remarks>
        public void AttachThread(int[] externalTransitions, Dictionary <int, PNCallback> callbackFunctions)
        {
            lock (this.disposeLock) { if (this.pnDisposed)
                                      {
                                          throw new ObjectDisposedException("PetriNet");
                                      }
            }
            if (!this.buildFinished)
            {
                throw new PetriNetException("Petri-network is under construction!");
            }
            if (externalTransitions == null || externalTransitions.Length == 0)
            {
                throw new ArgumentNullException("externalTransitions");
            }
            if (callbackFunctions == null || callbackFunctions.Count == 0)
            {
                throw new ArgumentNullException("callbackFunctions");
            }

            RCSet <PNTransition> extTransitions             = new RCSet <PNTransition>();
            Dictionary <PNTransition, PNCallback> callbacks = new Dictionary <PNTransition, PNCallback>();
            PNTransition firstExt = null;

            for (int i = 0; i < externalTransitions.Length; ++i)
            {
                int trIdx = externalTransitions[i];
                if (trIdx >= 0 && trIdx < this.transitions.Length)
                {
                    if (!callbackFunctions.ContainsKey(trIdx))
                    {
                        extTransitions.Add(this.transitions[trIdx]);
                        if (firstExt == null)
                        {
                            firstExt = this.transitions[trIdx];
                        }
                    }
                    else
                    {
                        throw new ArgumentException("Transition " + trIdx + " already exists in externalTransitions[" + i + "]!", "callbackFunctions");
                    }
                }
                else
                {
                    throw new ArgumentException("Transition " + trIdx + " doesn't exist!", "externalTransitions[" + i + "]");
                }
            }

            foreach (KeyValuePair <int, PNCallback> item in callbackFunctions)
            {
                int trIdx = item.Key;
                if (trIdx >= 0 && trIdx < this.transitions.Length)
                {
                    callbacks.Add(this.transitions[trIdx], item.Value);
                }
                else
                {
                    throw new ArgumentException("Transition " + trIdx + " doesn't exist!", "callbackFunctions");
                }
            }

            firstExt.Group.AttachThread(extTransitions, callbacks);
        }
Exemplo n.º 6
0
        /// <see cref="PetriNet.AttachThread"/>
        public void AttachThread(RCSet <PNTransition> extTransitions, Dictionary <PNTransition, PetriNet.PNCallback> callbacks)
        {
            if (this.threadAttached.WaitOne(0))
            {
                try
                {
                    /// Check the parameters.
                    CheckThreadAttachParameters(extTransitions, callbacks);

                    /// First we only allowed to fire external transitions.
                    PetriNet.PNTransitionType stage = PetriNet.PNTransitionType.EXTERNAL;

                    /// Start the thread control loop.
                    while (true)
                    {
                        /// Wait for a fireable transition.
                        this.releaseEvent.WaitOne();

                        lock (this.lockObject)
                        {
                            while (this.fireableTransitions.Count > 0)
                            {
                                if (stage == PetriNet.PNTransitionType.EXTERNAL)
                                {
                                    /// Find the first fireable external transition
                                    PNTransition firstExtTr = null;
                                    foreach (PNTransition fireableTr in this.fireableTransitions)
                                    {
                                        if (this.transitions[fireableTr] == PetriNet.PNTransitionType.CALLBACK)
                                        {
                                            throw new PetriNetException("Invalid type of fireable transition detected!");
                                        }

                                        if (firstExtTr == null && this.transitions[fireableTr] == PetriNet.PNTransitionType.EXTERNAL &&
                                            extTransitions.Contains(fireableTr))
                                        {
                                            firstExtTr = fireableTr;
                                        }
                                    }

                                    /// Fire the transition.
                                    if (firstExtTr != null)
                                    {
                                        firstExtTr.Fire();
                                        stage = PetriNet.PNTransitionType.INTERNAL;
                                    }
                                    else
                                    {
                                        /// No fireable external transitions have been found.
                                        break;
                                    }
                                }
                                else if (stage == PetriNet.PNTransitionType.INTERNAL)
                                {
                                    /// Find the first fireable internal transition or a callback transition
                                    PNTransition trToFire = null;
                                    foreach (PNTransition fireableTr in this.fireableTransitions)
                                    {
                                        if (this.transitions[fireableTr] == PetriNet.PNTransitionType.INTERNAL)
                                        {
                                            if (trToFire == null)
                                            {
                                                trToFire = fireableTr;
                                            }
                                        }
                                        else if (this.transitions[fireableTr] == PetriNet.PNTransitionType.CALLBACK)
                                        {
                                            if (this.fireableTransitions.Count == 1)
                                            {
                                                /// End of thread attach: fire the transition, invoke the callback and return.
                                                fireableTr.Fire();
                                                callbacks[fireableTr](fireableTr.Index);

                                                /// Detach the thread and exit from the function.
                                                this.threadAttached.Release();
                                                return;
                                            }
                                            else
                                            {
                                                throw new PetriNetException("Invalid state during a thread attach!");
                                            }
                                        }
                                        else
                                        {
                                            throw new PetriNetException("Invalid type of fireable transition detected!");
                                        }
                                    }

                                    if (trToFire != null)
                                    {
                                        trToFire.Fire();
                                    }
                                    else
                                    {
                                        /// No fireable internal transitions have been found.
                                        break;
                                    }
                                }
                            }
                        }
                    }
                }
                catch
                {
                    /// Error occured --> Detach the thread and re-throw the exception.
                    this.threadAttached.Release();
                    throw;
                }
            }
            else
            {
                throw new PetriNetException("You cannot attach more than one threads to the same transition group at the same time!");
            }
        }