/// <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); }
/// <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!"); } }