/// <summary> /// Acquires a resource according to the specified resource request, either blocking until successful, or /// returning <null> if the resource is not immediately available. /// </summary> /// <param name="resourceRequest">The IResourceRequest that specifies the criteria by which to select the resource.</param> /// <param name="blockAwaitingAcquisition">If true, request will suspend until granted. If false, will return false if unable to fulfill.</param> /// <returns>True if granted, false if not granted.</returns> public bool Acquire(IResourceRequest resourceRequest, bool blockAwaitingAcquisition) { if (blockAwaitingAcquisition) { IDetachableEventController dec = Model.Executive.CurrentEventController; if (dec == null) { throw new ApplicationException("Someone tried to call Acquire(..., true) while not in a detachable event. This is not allowed."); } dec.SetAbortHandler(resourceRequest.AbortHandler); resourceRequest.ResourceRequestAborting += m_onResourceRequestAborting; while (true) { if (Acquire(resourceRequest)) { break; } m_waiters.Add(dec); dec.Suspend(); dec.ClearAbortHandler(); } return(true); } else { return(Acquire(resourceRequest)); } }
public BlockTilKeyGoneHandler(Exchange exchange, ITuple tuple) { m_exchange = exchange; m_idec = m_exchange.m_exec.CurrentEventController; m_tuple = tuple; m_myEvent = m_exchange_TupleTaken; }
/// <summary> /// Releases the resource held under this resource request back into the resource pool. /// </summary> /// <param name="resourceRequest">The resource request under which the resource has previously /// been acquired.</param> public void Release(IResourceRequest resourceRequest) { if (resourceRequest.ResourceObtained != null) { if (s_diagnostics) { string fromWhom = resourceRequest.ToString(); if (resourceRequest.ResourceObtained != null) { fromWhom = resourceRequest.ResourceObtained.Name; } _Debug.WriteLine(Name + " servicing request to release " + resourceRequest.QuantityDesired + " units of " + fromWhom); } IResource resourceReleased = resourceRequest.ResourceObtained; resourceRequest.ResourceObtained?.Release(resourceRequest); resourceRequest.Status = RequestStatus.Free; ResourceReleased?.Invoke(resourceRequest, resourceReleased); while (m_waiters.Count > 0) { IDetachableEventController dec = (IDetachableEventController)m_waiters[0]; m_waiters.RemoveAt(0); if (dec.IsWaiting()) { dec.Resume(); // We might be releasing all resources as a part of an abort. } } } }
/// <summary> /// Acquires the resource and quantity specifed by the resource request, blocking /// until it can return successfully. /// </summary> /// <param name="request">The resource request that describes the desired resource and quantity.</param> /// <returns>Always true.</returns> protected bool AcquireWithWait(IResourceRequest request) { IDetachableEventController dec = Model.Executive.CurrentEventController; if (dec == null) { throw new ApplicationException("Someone tried to call AcquireWithWait() while not in a detachable event. This is not allowed."); } dec.SetAbortHandler(request.AbortHandler); request.ResourceRequestAborting += m_onResourceRequestAborting; while (!Acquire(request, false)) { m_waiters.Add(request, dec); dec.Suspend(); dec.ClearAbortHandler(); } if (request.ResourceObtained != null) { ResourceAcquired?.Invoke(request, request.ResourceObtained); return(true); } else { return(false); } }
private void idec_AbortionEvent(IExecutive exec, IDetachableEventController idec, params object[] args) { string narrative = "A synchronizer failed to complete. It had " + m_synchChannels.Count + " synch channels - following is the stack trace:\r\n" + new StackTrace(true); m_model.AddWarning(new GenericModelWarning("Synchronizer Aborted", narrative, this, null)); }
private ITuple BlockingTake(object key) { #region Ensure that this is a Detachable Event. #if DEBUG if (m_exec.CurrentEventType != ExecEventType.Detachable) { throw new ApplicationException("Attempt to do a blocking take with an executive event that is not Detachable."); } #endif #endregion while (true) { ITuple tuple = NonBlockingTake(key); if (tuple != null) { return(tuple); } #region Wait 'til next take against this key. IDetachableEventController idec = m_exec.CurrentEventController; m_waitersToTake.Add(key, idec); idec.Suspend(); #endregion } }
private void FinishRewiringDisposal(IExecutive exec, object userData) { IDetachableEventController plumbersIDEC = (IDetachableEventController)userData; Console.WriteLine("{0} : {1} is done fixing the disposal.", exec.Now, Name); plumbersIDEC.Resume(); Console.WriteLine("{0} : {1} is leaving.", exec.Now, Name); }
/// <summary> /// Creates a new instance of the <see cref="T:TerminalResourceRequestAbortedWarning"/> class. /// </summary> /// <param name="exec">The executive under whose control this warning occurred.</param> /// <param name="mgr">The Resource Manager from which the resource was obtained.</param> /// <param name="req">The request through which the resource was obtained.</param> /// <param name="idec">The <see cref="Highpoint.Sage.SimCore.IDetachableEventController"/> that controls the thread in which the resource was last manipulated.</param> public TerminalResourceRequestAbortedWarning(IExecutive exec, IResourceManager mgr, IResourceRequest req, IDetachableEventController idec) { m_idec = idec; ResourceRequest = req; ResourceManager = mgr; m_exec = exec; Narrative = GetNarrative(); }
public Dispensary(IExecutive executive, Mixture mixture) { m_executive = executive; m_getProcessor = s_dummyIdec; m_waiters = new List <IDetachableEventController>(); PeekMixture = mixture; executive.ExecutiveStarted += delegate { m_waiters.Clear(); PeekMixture.Clear(); }; }
/// <summary> /// Blocks the caller's detachable event thread until this transfer has started. /// </summary> public void BlockTilStart() { _Debug.Assert(m_model.Executive.CurrentEventType == ExecEventType.Detachable); if (m_completionKey == long.MinValue /*i.e. it has not started*/) { IDetachableEventController waiter = m_model.Executive.CurrentEventController; m_startWaiters.Add(waiter); waiter.Suspend(); } }
public PfcStepJoiner(PfcExecutionContext rootStepPfcec, IProcedureFunctionChart[] childPfCs) { Debug.Assert(rootStepPfcec.IsStepCentric); m_rootStepEc = rootStepPfcec; m_model = m_rootStepEc.Model; m_idec = null; m_onTransitionStateChanged = new TransitionStateMachineEvent(OnTransitionStateChanged); m_pendingActions = new List <IProcedureFunctionChart>(childPfCs); m_pendingActions.ForEach(delegate(IProcedureFunctionChart kid) { kid.GetFinishTransition().MyTransitionStateMachine.TransitionStateChanged += m_onTransitionStateChanged; }); }
public void Add(IResourceRequest rreq, IDetachableEventController idec) { if (!m_supportsPriorities) { base.Add(idec); } else { rreq.PriorityChangeEvent += m_rreqPriorityChangeEvent; m_dirty = true; // TODO: Not necessarily base.Add(new RscWaiterListEntry(rreq, idec, m_seqNum++)); } }
private void ProcessGetters(IExecutive exec, object userData) { m_getProcessor = exec.CurrentEventController; IDetachableEventController waiter = null; while (m_waiters.Count > 0 && m_waiters[0] != waiter) { waiter = m_waiters[0]; waiter.Resume(); m_getProcessor.Suspend(); } m_getFlushEventId = -1; m_getProcessor = s_dummyIdec; }
/// <summary> /// Releases the specified request. Returns it to availability and the resource pool. /// </summary> /// <param name="request">The request.</param> public void Release(IResourceRequest request) { lock (this) { DoRollback(request); ReleasedEvent?.Invoke(request, this); ResourceReleased?.Invoke(request, this); } while (m_waiters.Count > 0) { IDetachableEventController dec = (IDetachableEventController)m_waiters[0]; m_waiters.RemoveAt(0); dec.Resume(); } }
protected void GetPermissionToStart(PfcExecutionContext myPfcec, StepStateMachine ssm) { PfcExecutionContext root = myPfcec; int ascents = m_rootHeight; while (ascents > 0) { root = (PfcExecutionContext)myPfcec.Parent.Payload; ascents--; } Exchange exchange = null; if (m_myIndex == 0) { //Console.WriteLine(myPfcec.Name + " is creating an exchange and injecting it into pfcec " + root.Name + " under key " + m_sequenceKey); exchange = new Exchange(myPfcec.Model.Executive); root.Add(m_sequenceKey, exchange); } else { //Console.WriteLine(myPfcec.Name + " is looking for an exchange in pfcec " + root.Name + " under key " + m_sequenceKey); DictionaryChange dc = new DictionaryChange(myPfcec_EntryAdded); while (true) { exchange = (Exchange)root[m_sequenceKey]; if (exchange == null) { root.EntryAdded += dc; m_idec = myPfcec.Model.Executive.CurrentEventController; m_idec.Suspend(); } else { root.EntryAdded -= dc; break; } } exchange.Take(m_myKey, true); // Only indices 1,2, ... take (and wait?). Index 0 only posts. //Console.WriteLine(myPfcec.Name + " got the key I was looking for!"); } Guid nextGuysKey = GuidOps.Increment(m_myKey); exchange.Post(nextGuysKey, nextGuysKey, false); //Console.WriteLine(myPfcec.Name + " posted the key the next guy is looking for!"); }
private void TimeSeparatedTask(IExecutive exec, object userData) { IDetachableEventController dec = exec.CurrentEventController; Debug.WriteLine(exec.Now + " : " + userData.ToString() + " performing initialization of detachable task on thread " + System.Threading.Thread.CurrentThread.GetHashCode()); while (m_random.Next(3) < 2) { DateTime when = exec.Now + TimeSpan.FromDays(1.5); Debug.WriteLine("Suspending task until " + when); dec.SuspendUntil(when); Debug.WriteLine(exec.Now + " : " + userData.ToString() + " performing continuation of detachable task on thread " + System.Threading.Thread.CurrentThread.GetHashCode()); } }
private void BlockingPost(ITuple tuple) { #region Ensure that this is a Detachable Event. #if DEBUG if (m_exec.CurrentEventType != ExecEventType.Detachable) { throw new ApplicationException("Attempt to do a blocking post with an executive event that is not Detachable."); } #endif #endregion NonBlockingPost(tuple); #region Wait 'til next take against this key. IDetachableEventController idec = m_exec.CurrentEventController; m_blockedPosters.Add(tuple.Key, idec); idec.Suspend(); #endregion }
internal void GetStartPermission(PfcExecutionContext pfcec) { IDetachableEventController currentEventController = m_myStep.Model.Executive.CurrentEventController; SsmData ssmData = GetSsmData(pfcec); if (!ssmData.State.Equals(StepState.Idle)) { ssmData.QueueIdec.Enqueue(currentEventController); if (s_diagnostics) { Console.WriteLine(m_myStep.Model.Executive.Now + " : suspending awaiting start of " + m_myStep.Name + " ..."); } currentEventController.Suspend(); if (s_diagnostics) { Console.WriteLine(m_myStep.Model.Executive.Now + " : resuming the starting of " + m_myStep.Name + " ..."); } } }
private ITuple BlockingRead(object key) { lock ( m_ts ) { while (true) { ITuple tuple = NonBlockingRead(key); if (tuple != null) { return(tuple); } #region Wait 'til next post against this key. IDetachableEventController idec = m_exec.CurrentEventController; m_waitersToRead.Add(key, idec); idec.Suspend(); #endregion } } }
private void LogSynchronization(object sortKey, IDetachableEventController idec, SynchChannel sc) { if (m_waiters.ContainsValue(idec)) { throw new ApplicationException("Synchronize(...) called on a SynchChannel that is already waiting."); } if (!m_synchChannels.Contains(sc)) { throw new ApplicationException("SynchChannel applied to a synchronizer that did not own it - serious error."); } if ((m_waiters.Count + 1) == m_synchChannels.Count) { m_exec.RequestEvent(new ExecEventReceiver(LaunchAll), m_exec.Now, m_exec.CurrentPriorityLevel, null); } m_waiters.Add(sortKey, idec); idec.SetAbortHandler(new DetachableEventAbortHandler(idec_AbortionEvent)); idec.Suspend(); idec.ClearAbortHandler(); }
/// <summary> /// Unreserves a quantity of resource from this pool that was previously reserved under the provided /// resource request. /// </summary> /// <param name="resourceRequest">The resource request under which some resource was previously reserved.</param> public void Unreserve(IResourceRequest resourceRequest) { if (s_diagnostics) { _Debug.WriteLine(Name + " servicing request to unreserve " + resourceRequest.QuantityDesired + " units of " + resourceRequest); } if (resourceRequest.ResourceObtained != null) { resourceRequest.ResourceObtained.Unreserve(resourceRequest); resourceRequest.Status = RequestStatus.Free; } while (m_waiters.Count > 0) { IDetachableEventController dec = (IDetachableEventController)m_waiters[0]; m_waiters.RemoveAt(0); if (dec.IsWaiting()) { dec.Resume(); // We might be releasing all resources as a part of an abort. } } }
public void FixTheSink(IExecutive exec, object userData) { IDetachableEventController idec = exec.CurrentEventController; Console.WriteLine("{0} : {1} is starting to fix the sink.", exec.Now, Name); idec.SuspendFor(TimeSpan.FromMinutes(10.0)); // When the suspend call returns, 10 minutes have passed. Console.WriteLine("{0} : {1} discovered that the disposal needed rewiring.", exec.Now, Name); DateTime when = exec.Now + TimeSpan.FromMinutes(5.0); exec.RequestEvent(new Electrician("Edgar").RewireDisposal, when, idec); Console.WriteLine("{0} : {1} called the electrician and is starting to eat lunch.", exec.Now, Name); idec.Suspend(); // When the suspend call returns (from the electrician calling "Resume",) // the electrician is done, and presumably the sink is fixed. Console.WriteLine("{0} : {1} was told by the electrician that the disposal is fixed.", exec.Now, Name); Console.WriteLine("{0} : {1} is resuming fixing the sink.", exec.Now, Name); idec.SuspendFor(TimeSpan.FromMinutes(40.0)); // Finishing fixing the sink requires 40 minutes, // and on return from this call, that time has passed. Console.WriteLine("{0} : {1} is done fixing the sink.", exec.Now, Name); }
private ITuple NonBlockingTake(object key) { ITuple tuple; lock ( m_ts ) { tuple = (ITuple)m_ts[key]; if (tuple != null) { m_ts.Remove(key); tuple.OnTaken(this); TupleTaken?.Invoke(this, tuple); IDetachableEventController blockedPoster = (IDetachableEventController)m_blockedPosters[tuple.Key]; if (blockedPoster != null) { m_blockedPosters.Remove(tuple.Key); blockedPoster.Resume(s_postPriority); } } } return(tuple); }
private void WaitForAllActionsToComplete(IExecutive exec) { m_myIDEC = exec.CurrentEventController; m_myIDEC.Suspend(); }
public RscWaiterListEntry(IResourceRequest request, IDetachableEventController idec, int seq) { Request = request; Idec = idec; Sequence = seq; }
private void OnResourceRequestAborting(IResourceRequest request, IExecutive exec, IDetachableEventController idec) { m_model.AddWarning(new TerminalResourceRequestAbortedWarning(exec, this, request, idec)); }
public void RunAndWait() { m_idec = m_model.Executive.CurrentEventController; m_idec.Suspend(); }
/// <summary> /// Called by a synch channel to indicate that it is ready to proceed. It will be /// allowed to do so once all clients have called this method. /// </summary> public void Synchronize() { IDetachableEventController idec = m_ds.m_exec.CurrentEventController; m_ds.LogSynchronization(m_sortKey, idec, this); }
private void OnRequestAborting(IExecutive exec, IDetachableEventController idec, params object[] args) { ResourceRequestAborting?.Invoke(this, exec, idec); }