public void EventSchExec(QueueItemStruct QIS) { if (QIS.ID == null || QIS.ID.Script == null) { return; } if (!QIS.ID.Running) { //do only state_entry and on_rez if (QIS.functionName != "state_entry" || QIS.functionName != "on_rez") { return; } } //Check the versionID so that we can kill events if (QIS.functionName != "link_message" && QIS.VersionID != Interlocked.Read(ref QIS.ID.VersionID)) { MainConsole.Instance.WarnFormat("FOUND BAD VERSION ID, OLD {0}, NEW {1}, FUNCTION NAME {2}", QIS.VersionID, Interlocked.Read(ref QIS.ID.VersionID), QIS.functionName); //return; } MainConsole.Instance.Trace("[ADNE]: Running Event " + QIS.functionName + " in object " + QIS.ID.Part.ToString() + " in region " + QIS.ID.Part.ParentEntity.Scene.RegionInfo.RegionName); if (!EventSchProcessQIS(ref QIS)) //Execute the event { //All done QIS.EventsProcData.State = ScriptEventsState.Idle; } else { if (QIS.CurrentlyAt.SleepTo.Ticks != 0) { QIS.EventsProcData.TimeCheck = QIS.CurrentlyAt.SleepTo; QIS.EventsProcData.State = ScriptEventsState.Sleep; //If it is greater, we need to check sooner for this one if (NextSleepersTest.Ticks > QIS.CurrentlyAt.SleepTo.Ticks) { NextSleepersTest = QIS.CurrentlyAt.SleepTo; } lock (SleepingScriptEvents) { SleepingScriptEvents.Enqueue(QIS, QIS.CurrentlyAt.SleepTo.Ticks); SleepingScriptEventCount++; } } else { QIS.EventsProcData.State = ScriptEventsState.Running; lock (ScriptEvents) { this.ScriptEvents.Enqueue(QIS); ScriptEventCount++; } } } }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, EventPriority priority, params object[] param) { QueueItemStruct QIS = new QueueItemStruct { EventsProcData = new ScriptEventsProcData(), ID = ID, functionName = FunctionName, llDetectParams = qParams, param = param, VersionID = Interlocked.Read(ref ID.VersionID), State = ID.State, CurrentlyAt = null }; if (ID == null || ID.Script == null || ID.IgnoreNew) { return; } if (!ID.SetEventParams(QIS)) // check events delay rules { return; } ScriptEvents.Enqueue(QIS); long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEvents.Count + (SleepingScriptEventCount / 2)) * EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } }
public bool EventSchProcessQIS(ref QueueItemStruct QIS) { try { Exception ex = null; EnumeratorInfo Running = QIS.ID.Script.ExecuteEvent(QIS.State, QIS.functionName, QIS.param, QIS.CurrentlyAt, out ex); if (ex != null) { //Check exceptions, some are ours to deal with, and others are to be logged if (ex.Message.Contains("SelfDeleteException")) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) { IBackupModule backup = QIS.ID.Part.ParentEntity.Scene.RequestModuleInterface <IBackupModule>(); if (backup != null) { backup.DeleteSceneObjects( new ISceneEntity[1] { QIS.ID.Part.ParentEntity }, true, true); } } } else if (ex.Message.Contains("ScriptDeleteException")) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) { QIS.ID.Part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); } } //Log it for the user else if (!(ex.Message.Contains("EventAbortException")) && !(ex.Message.Contains("MinEventDelayException"))) { QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } EventManager.EventComplete(QIS); return(false); } else if (Running != null) { //Did not finish so requeue it QIS.CurrentlyAt = Running; QIS.RunningNumber++; return(true); //Do the return... otherwise we open the queue for this event back up } } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return(false); }
public void AddEventSchQIS(QueueItemStruct QIS) { if (QIS.ID == null || QIS.ID.Script == null || QIS.ID.IgnoreNew) { EventManager.EventComplete(QIS); return; } if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules { EventManager.EventComplete(QIS); return; } QIS.CurrentlyAt = null; lock (ScriptEvents) { ScriptEvents.Enqueue(QIS); ScriptEventCount++; #if Debug MainConsole.Instance.Warn(ScriptEventCount + ", " + QIS.functionName); #endif } long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEventCount + (SleepingScriptEventCount / 2)) * EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, int VersionID, EventPriority priority, params object[] param) { QueueItemStruct QIS; if (ID == null || ID.EventsProcData.IgnoreNew) { return; } if (!ID.SetEventParams(FunctionName, qParams)) // check events delay rules { return; } QIS = new QueueItemStruct(); QIS.ID = ID; QIS.functionName = FunctionName; QIS.llDetectParams = qParams; QIS.param = param; QIS.VersionID = VersionID; QIS.State = ID.State; QIS.CurrentlyAt = null; Interlocked.Exchange(ref ID.EventsProcDataLocked, 1); lock (ID.EventsProcData) { if (ID.EventsProcData.EventsQueue.Count > 100) { Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); return; } ID.EventsProcData.EventsQueue.Enqueue(QIS); lock (ScriptIDs) { if (!ID.InEventsProcData) { ID.EventsProcData.State = (int)ScriptEventsState.Idle; ID.EventsProcData.thread = null; ScriptIDs.AddLast(ID); ID.InEventsProcData = true; Interlocked.Increment(ref nScriptIDs); Interlocked.Increment(ref nEventScripts); } } Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); } lock (WorkersLock) { if (WorkersLock.nWorkers < MaxScriptThreads && WorkersLock.nWorkers < nScriptIDs) { Scriptthreadpool.QueueEvent(loop, 2); } } }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, int VersionID, params object[] param) { QueueItemStruct QIS = new QueueItemStruct(); QIS.ID = ID; QIS.functionName = FunctionName; QIS.llDetectParams = qParams; QIS.param = param; QIS.VersionID = VersionID; QIS.State = ID.State; AddEventSchQIS(QIS); }
/// <summary> /// This removes the event from the queue and allows it to be fired again /// </summary> /// <param name="QIS"></param> public void EventComplete(QueueItemStruct QIS) { if (QIS.functionName == "timer") { QIS.ID.TimerQueued = false; } else if (QIS.functionName == "control") { if (QIS.ID.ControlEventsInQueue > 0) { QIS.ID.ControlEventsInQueue--; } } else if (QIS.functionName == "collision") { QIS.ID.CollisionInQueue = false; } else if (QIS.functionName == "collision_end") { QIS.ID.CollisionInQueue = false; } else if (QIS.functionName == "moving_end") { QIS.ID.MovingInQueue = false; } else if (QIS.functionName == "touch") { QIS.ID.TouchInQueue = false; } else if (QIS.functionName == "touch_end") { QIS.ID.TouchInQueue = false; } else if (QIS.functionName == "land_collision") { QIS.ID.LandCollisionInQueue = false; } else if (QIS.functionName == "changed") { Changed changed; if (QIS.param[0] is Changed) { changed = (Changed)QIS.param[0]; } else { changed = (Changed)(((LSL_Types.LSLInteger)QIS.param[0]).value); } QIS.ID.ChangedInQueue.Remove(changed); } }
public void AddEventSchQIS(QueueItemStruct QIS) { ScriptData ID; ID = QIS.ID; if (ID == null || ID.EventsProcData.IgnoreNew) { return; } if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules { return; } QIS.CurrentlyAt = null; Interlocked.Exchange(ref ID.EventsProcDataLocked, 1); lock (ID.EventsProcData) { if (ID.EventsProcData.EventsQueue.Count > 100) { Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); return; } ID.EventsProcData.EventsQueue.Enqueue(QIS); lock (ScriptIDs) { if (!ID.InEventsProcData) { ID.EventsProcData.State = (int)ScriptEventsState.Idle; ID.EventsProcData.thread = null; ScriptIDs.AddLast(ID); Interlocked.Increment(ref nScriptIDs); Interlocked.Increment(ref nEventScripts); ID.InEventsProcData = true; } } Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); } lock (WorkersLock) { if (WorkersLock.nWorkers < MaxScriptThreads && WorkersLock.nWorkers < nScriptIDs) { Scriptthreadpool.QueueEvent(loop, 2); } } }
public bool AddEventSchQIS(QueueItemStruct QIS, EventPriority priority) { if (QIS.ID == null || QIS.ID.IgnoreNew) { EventManager.EventComplete(QIS); return(false); } if (QIS.ID.Script == null) { QIS.ID.CheckAddEventToQueue(QIS); return(false); } if (!QIS.ID.SetEventParams(QIS)) // check events delay rules { EventManager.EventComplete(QIS); return(false); } QIS.CurrentlyAt = null; if (priority == EventPriority.Suspended || priority == EventPriority.Continued) { lock (SleepingScriptEvents) { long time = priority == EventPriority.Suspended ? DateTime.Now.AddMilliseconds(10).Ticks : DateTime.Now.Ticks; //Let it sleep for 10ms so that other scripts can process before it, any repeating plugins ought to use this SleepingScriptEvents.Enqueue(QIS, time); SleepingScriptEventCount++; #if Debug MainConsole.Instance.Warn(ScriptEventCount + ", " + QIS.functionName); #endif } } else { ScriptEvents.Enqueue(QIS); } long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEvents.Count + (SleepingScriptEventCount / 2)) * EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } return(true); }
public bool EventSchProcessQIS(ref QueueItemStruct QIS) { try { if (QIS.ID.Script == null) { return(false); } QIS.ID.Script.ExecuteEvent(QIS.State, QIS.functionName, QIS.param); // if (QIS.ID.VersionID != QIS.VersionID) // return false; /*if (ex != null) * { * //Check exceptions, some are ours to deal with, and others are to be logged * if (ex is SelfDeleteException) * { * if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) * { * IBackupModule backup = QIS.ID.Part.ParentEntity.Scene.RequestModuleInterface<IBackupModule> (); * if (backup != null) * backup.DeleteSceneObjects( * new ISceneEntity[1] { QIS.ID.Part.ParentEntity }, true); * } * } * else if (ex is ScriptDeleteException) * { * if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) * QIS.ID.Part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); * } * //Log it for the user * else if (!(ex is EventAbortException) && * !(ex is MinEventDelayException)) * QIS.ID.DisplayUserNotification(ex.ToString(), "", false, true); * return false; * }*/ } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return(false); }
public void AddEventSchQIS(QueueItemStruct QIS) { ScriptData ID; ID = QIS.ID; if (ID == null) { return; } if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules { return; } EventSchProcessQIS(ref QIS); }
public bool CheckAddEventToQueue(QueueItemStruct itm) { if (funcsToDrop.Contains(itm.functionName)) { return(false);//Drop them, don't enqueue } lock (m_eventQueueLock) { if (m_eventQueueTimer == null)//Have it try again in 5ms { m_eventQueueTimer = new Timer(EventQueuePoke, null, 5, 5); } m_eventQueue.Enqueue(itm); } return(false); }
public bool CheckAddEventToQueue(QueueItemStruct itm) { if (funcsToDrop.Contains(itm.functionName)) return false;//Drop them, don't enqueue lock (m_eventQueueLock) { if (m_eventQueueTimer == null)//Have it try again in 5ms m_eventQueueTimer = new Timer(EventQueuePoke, null, 5, 5); m_eventQueue.Enqueue(itm); } return false; }
public void AddEvent(QueueItemStruct QIS, EventPriority priority) { AddEventSchQIS(QIS); }
public bool SetEventParams(QueueItemStruct itm) { if (Suspended || !Running) return false; //No suspended scripts... if (itm.llDetectParams.Length > 0) LastDetectParams = itm.llDetectParams; if (itm.functionName == "state_entry" || itm.functionName == "state_exit" || itm.functionName == "on_rez") return true; long NowTicks = Util.EnvironmentTickCount(); if (EventDelayTicks != 0) { if (NowTicks < NextEventTimeTicks) return false; NextEventTimeTicks = NowTicks + EventDelayTicks; } switch (itm.functionName) { //Times pulled from http://wiki.secondlife.com/wiki/LSL_Delay case "touch": //Limits for 0.1 seconds case "touch_start": case "touch_end": if (NowTicks < NextEventDelay[itm.functionName]) return CheckAddEventToQueue(itm); NextEventDelay[itm.functionName] = NowTicks + (long) (TouchEventDelayTicks*TicksPerMillisecond); break; case "timer": //Settable timer limiter if (NowTicks < NextEventDelay[itm.functionName]) return CheckAddEventToQueue(itm); NextEventDelay[itm.functionName] = NowTicks + (long) (TimerEventDelayTicks*TicksPerMillisecond); break; case "collision": case "collision_start": case "collision_end": case "land_collision": case "land_collision_start": case "land_collision_end": if (NowTicks < NextEventDelay[itm.functionName]) return CheckAddEventToQueue(itm); NextEventDelay[itm.functionName] = NowTicks + (long) (CollisionEventDelayTicks*TicksPerMillisecond); break; case "control": if (NowTicks < NextEventDelay[itm.functionName]) return CheckAddEventToQueue(itm); NextEventDelay[itm.functionName] = NowTicks + (long) (0.05f*TicksPerMillisecond); break; default: //Default is 0.05 seconds for event limiting if (!NextEventDelay.ContainsKey(itm.functionName)) break; //If it doesn't exist, we don't limit it if (NowTicks < NextEventDelay[itm.functionName]) return CheckAddEventToQueue(itm); NextEventDelay[itm.functionName] = NowTicks + (long) (DefaultEventDelayTicks*TicksPerMillisecond); break; } //Add the event to the stats ScriptScore++; m_ScriptEngine.ScriptEPS++; return true; }
public void eventLoop() { int numberOfEmptyWork = 0; while (!m_ScriptEngine.ConsoleDisabled && !m_ScriptEngine.Disabled && m_ScriptEngine.Scene.ShouldRunHeartbeat) { //int numScriptsProcessed = 0; int numSleepScriptsProcessed = 0; //const int minNumScriptsToProcess = 1; //processMoreScripts: QueueItemStruct QIS = new QueueItemStruct(); bool found = false; //Check whether it is time, and then do the thread safety piece if (Interlocked.CompareExchange(ref m_CheckingSleepers, 1, 0) == 0) { lock (SleepingScriptEvents) { restart: if (SleepingScriptEvents.Count > 0) { QIS = SleepingScriptEvents.Dequeue().Value; found = true; if (QIS.RunningNumber > 2 && SleepingScriptEventCount > 0 && numSleepScriptsProcessed < SleepingScriptEventCount) { QIS.RunningNumber = 1; SleepingScriptEvents.Enqueue(QIS, QIS.EventsProcData.TimeCheck.Ticks); numSleepScriptsProcessed++; found = false; found = false; goto restart; } } } if (found) { if (QIS.EventsProcData.TimeCheck.Ticks < DateTime.Now.Ticks) { DateTime NextTime = DateTime.MaxValue; lock (SleepingScriptEvents) { if (SleepingScriptEvents.Count > 0) { NextTime = SleepingScriptEvents.Peek().Value.EventsProcData.TimeCheck; } //Now add in the next sleep time NextSleepersTest = NextTime; //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } //Execute the event EventSchExec(QIS); lock (SleepingScriptEvents) SleepingScriptEventCount--; //numScriptsProcessed++; } else { lock (SleepingScriptEvents) { NextSleepersTest = QIS.EventsProcData.TimeCheck; SleepingScriptEvents.Enqueue(QIS, QIS.EventsProcData.TimeCheck.Ticks); //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } } } else //No more left, don't check again { lock (SleepingScriptEvents) { NextSleepersTest = DateTime.MaxValue; //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } } } int timeToSleep = 5; //If we can, get the next event if (Interlocked.CompareExchange(ref m_CheckingEvents, 1, 0) == 0) { if (ScriptEvents.TryDequeue(out QIS)) { Interlocked.Exchange(ref m_CheckingEvents, 0); #if Debug MainConsole.Instance.Warn(QIS.functionName + "," + ScriptEvents.Count); #endif EventSchExec(QIS); //numScriptsProcessed++; } else { Interlocked.Exchange(ref m_CheckingEvents, 0); } } //Process a bunch each time //if (ScriptEventCount > 0 && numScriptsProcessed < minNumScriptsToProcess) // goto processMoreScripts; if (ScriptEvents.Count == 0 && NextSleepersTest.Ticks != DateTime.MaxValue.Ticks) { timeToSleep = (int)(NextSleepersTest - DateTime.Now).TotalMilliseconds; } if (timeToSleep < 5) { timeToSleep = 5; } if (timeToSleep > 50) { timeToSleep = 50; } if (SleepingScriptEventCount == 0 && ScriptEvents.Count == 0) { numberOfEmptyWork++; if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME) //Don't break immediately, otherwise we have to wait to spawn more threads { break; //No more events, end } else if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME / 20) { timeToSleep += 10; } } else if (Interlocked.Read(ref scriptThreadpool.nthreads) > (ScriptEvents.Count + (int)((SleepingScriptEventCount / 2f + 0.5f))) || Interlocked.Read(ref scriptThreadpool.nthreads) > MaxScriptThreads) { numberOfEmptyWork++; if (numberOfEmptyWork > (EMPTY_WORK_KILL_THREAD_TIME / 2)) //Don't break immediately { break; //Too many threads, kill some off } else if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME / 20) { timeToSleep += 5; } } else { numberOfEmptyWork /= 2; //Cut it down, but don't zero it out, as this may just be one event } #if Debug MainConsole.Instance.Warn("Sleep: " + timeToSleep); #endif Interlocked.Increment(ref scriptThreadpool.nSleepingthreads); Thread.Sleep(timeToSleep); Interlocked.Decrement(ref scriptThreadpool.nSleepingthreads); } }
/// <summary> /// Processes and fires an event /// </summary> /// <param name="QIS"></param> /// <returns>Returns whether the calling thread should sleep after processing this request</returns> public bool ProcessQIS(QueueItemStruct QIS) { //Disabled, not running, suspended, null scripts, or loading scripts dont get events fired. if (QIS.ID.Suspended || QIS.ID.Script == null || QIS.ID.Loading || QIS.ID.Disabled) return true; if (!QIS.ID.Running) { //Readd only state_entry and on_rez if (QIS.functionName == "state_entry" || QIS.functionName == "on_rez") EventProcessorQueue.Add(QIS, EventPriority.Continued); return true; } //Check if this event was fired with an old versionID if (NeedsRemoved.ContainsKey(QIS.ID.ItemID)) if(NeedsRemoved[QIS.ID.ItemID] >= QIS.VersionID) return true; try { //Either its currently doing something, or the script has set the event params for the new event if (QIS.CurrentlyAt != null || QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) { //If this is true, there is/was a sleep occuring if (QIS.CurrentlyAt != null && QIS.CurrentlyAt.SleepTo.Ticks != 0) { DateTime nowTicks = DateTime.Now; if ((QIS.CurrentlyAt.SleepTo - nowTicks).TotalMilliseconds > 0) { //Its supposed to be sleeping.... // No processing! EventProcessorQueue.Add(QIS, EventPriority.Continued); return true; } else { //Reset the time so we don't keep checking QIS.CurrentlyAt.SleepTo = DateTime.MinValue; } } Exception ex = null; EnumeratorInfo Running = QIS.ID.Script.ExecuteEvent(QIS.ID.State, QIS.functionName, QIS.param, QIS.CurrentlyAt, out ex); if (ex != null) { //Check exceptions, some are ours to deal with, and others are to be logged if (ex is SelfDeleteException) { if (QIS.ID.part != null && QIS.ID.part.ParentGroup != null) QIS.ID.part.ParentGroup.Scene.DeleteSceneObject( QIS.ID.part.ParentGroup, false, true); } else if (ex is ScriptDeleteException) { if (QIS.ID.part != null && QIS.ID.part.ParentGroup != null) QIS.ID.part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); } //Log it for the user else if(!(ex is EventAbortException) && !(ex is MinEventDelayException)) QIS.ID.DisplayUserNotification(ex.ToString(), "", false, true); return false; } else if (Running != null) { //Did not finish so requeue it QIS.CurrentlyAt = Running; EventProcessorQueue.Add(QIS, EventPriority.Continued); return false; //Do the return... otherwise we open the queue for this event back up } } } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return false; }
public void AddEventSchQIS(QueueItemStruct QIS) { ScriptData ID; ID = QIS.ID; if (ID == null) return; if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules return; EventSchProcessQIS(ref QIS); }
public void AddEventSchQIS(QueueItemStruct QIS) { ScriptData ID; ID = QIS.ID; if (ID == null || ID.EventsProcData.IgnoreNew) return; if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules return; QIS.CurrentlyAt = null; lock (ID.EventsProcData) { ID.EventsProcDataLocked = true; if (ID.EventsProcData.EventsQueue.Count > 100) { ID.EventsProcDataLocked = false; return; } ID.EventsProcData.EventsQueue.Enqueue(QIS); lock (ScriptIDs) { if (!ScriptIDs.Contains(ID)) { ID.EventsProcData.State = (int)ScriptEventsState.Idle; ID.EventsProcData.thread = null; ScriptIDs.AddLast(ID); NScriptIDs++; ID.InEventsProcData = true; } } } ID.EventsProcDataLocked = false; lock (WorkersLock) { if (WorkersLock.nWorkers < MaxScriptThreads) { Scriptthreadpool.QueueEvent(loop, 2); } } }
public bool EventSchProcessQIS(ref QueueItemStruct QIS) { try { Exception ex = null; EnumeratorInfo Running = QIS.ID.Script.ExecuteEvent(QIS.State, QIS.functionName, QIS.param, QIS.CurrentlyAt, out ex); if (ex != null) { //Check exceptions, some are ours to deal with, and others are to be logged if (ex.Message.Contains("SelfDeleteException")) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) { IBackupModule backup = QIS.ID.Part.ParentEntity.Scene.RequestModuleInterface<IBackupModule>(); if (backup != null) backup.DeleteSceneObjects( new ISceneEntity[1] {QIS.ID.Part.ParentEntity}, true, true); } } else if (ex.Message.Contains("ScriptDeleteException")) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) QIS.ID.Part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); } //Log it for the user else if (!(ex.Message.Contains("EventAbortException")) && !(ex.Message.Contains("MinEventDelayException"))) QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); EventManager.EventComplete(QIS); return false; } else if (Running != null) { //Did not finish so requeue it QIS.CurrentlyAt = Running; QIS.RunningNumber++; return true; //Do the return... otherwise we open the queue for this event back up } } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return false; }
public void EventComplete(QueueItemStruct QIS) { if (QIS.functionName == "timer") QIS.ID.TimerQueued = false; else if (QIS.functionName == "control") { if (QIS.ID.ControlEventsInQueue > 0) QIS.ID.ControlEventsInQueue--; } else if (QIS.functionName == "collision") QIS.ID.CollisionInQueue = false; else if (QIS.functionName == "moving_end") QIS.ID.MovingInQueue = false; else if (QIS.functionName == "touch") QIS.ID.TouchInQueue = false; else if (QIS.functionName == "land_collision") QIS.ID.LandCollisionInQueue = false; else if (QIS.functionName == "changed") { Changed changed = (Changed)Enum.Parse(typeof(Changed),QIS.param[0].ToString()); QIS.ID.ChangedInQueue.Remove(changed); } }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, EventPriority priority, params object[] param) { QueueItemStruct QIS; if (ID == null || ID.Script == null || ID.IgnoreNew) return; if (!ID.SetEventParams(FunctionName, qParams)) // check events delay rules return; QIS = new QueueItemStruct { EventsProcData = new ScriptEventsProcData(), ID = ID, functionName = FunctionName, llDetectParams = qParams, param = param, VersionID = Interlocked.Read(ref ID.VersionID), State = ID.State, CurrentlyAt = null }; ScriptEvents.Enqueue(QIS); long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEvents.Count + (SleepingScriptEventCount/2))*EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } }
public void eventLoop() { int numberOfEmptyWork = 0; while (!m_ScriptEngine.ConsoleDisabled && !m_ScriptEngine.Disabled && m_ScriptEngine.Scene.ShouldRunHeartbeat) { //int numScriptsProcessed = 0; int numSleepScriptsProcessed = 0; //const int minNumScriptsToProcess = 1; //processMoreScripts: QueueItemStruct QIS = new QueueItemStruct(); bool found = false; //Check whether it is time, and then do the thread safety piece if (Interlocked.CompareExchange(ref m_CheckingSleepers, 1, 0) == 0) { lock (SleepingScriptEvents) { restart: if (SleepingScriptEvents.Count > 0) { QIS = SleepingScriptEvents.Dequeue().Value; found = true; if (QIS.RunningNumber > 2 && SleepingScriptEventCount > 0 && numSleepScriptsProcessed < SleepingScriptEventCount) { QIS.RunningNumber = 1; SleepingScriptEvents.Enqueue(QIS, QIS.EventsProcData.TimeCheck.Ticks); numSleepScriptsProcessed++;found = false; found = false; goto restart; } } } if (found) { if (QIS.EventsProcData.TimeCheck.Ticks < DateTime.Now.Ticks) { DateTime NextTime = DateTime.MaxValue; lock (SleepingScriptEvents) { if (SleepingScriptEvents.Count > 0) NextTime = SleepingScriptEvents.Peek().Value.EventsProcData.TimeCheck; //Now add in the next sleep time NextSleepersTest = NextTime; //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } //Execute the event EventSchExec(QIS); lock (SleepingScriptEvents) SleepingScriptEventCount--; //numScriptsProcessed++; } else { lock (SleepingScriptEvents) { NextSleepersTest = QIS.EventsProcData.TimeCheck; SleepingScriptEvents.Enqueue(QIS, QIS.EventsProcData.TimeCheck.Ticks); //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } } } else //No more left, don't check again { lock (SleepingScriptEvents) { NextSleepersTest = DateTime.MaxValue; //All done Interlocked.Exchange(ref m_CheckingSleepers, 0); } } } int timeToSleep = 5; //If we can, get the next event if (Interlocked.CompareExchange(ref m_CheckingEvents, 1, 0) == 0) { if (ScriptEvents.TryDequeue(out QIS)) { Interlocked.Exchange(ref m_CheckingEvents, 0); #if Debug MainConsole.Instance.Warn(QIS.functionName + "," + ScriptEvents.Count); #endif EventSchExec(QIS); //numScriptsProcessed++; } else Interlocked.Exchange(ref m_CheckingEvents, 0); } //Process a bunch each time //if (ScriptEventCount > 0 && numScriptsProcessed < minNumScriptsToProcess) // goto processMoreScripts; if (ScriptEvents.Count == 0 && NextSleepersTest.Ticks != DateTime.MaxValue.Ticks) timeToSleep = (int) (NextSleepersTest - DateTime.Now).TotalMilliseconds; if (timeToSleep < 5) timeToSleep = 5; if (timeToSleep > 50) timeToSleep = 50; if (SleepingScriptEventCount == 0 && ScriptEvents.Count == 0) { numberOfEmptyWork++; if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME) //Don't break immediately, otherwise we have to wait to spawn more threads { break; //No more events, end } else if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME/20) timeToSleep += 10; } else if (Interlocked.Read(ref scriptThreadpool.nthreads) > (ScriptEvents.Count + (int) ((SleepingScriptEventCount/2f + 0.5f))) || Interlocked.Read(ref scriptThreadpool.nthreads) > MaxScriptThreads) { numberOfEmptyWork++; if (numberOfEmptyWork > (EMPTY_WORK_KILL_THREAD_TIME/2)) //Don't break immediately { break; //Too many threads, kill some off } else if (numberOfEmptyWork > EMPTY_WORK_KILL_THREAD_TIME/20) timeToSleep += 5; } else numberOfEmptyWork /= 2; //Cut it down, but don't zero it out, as this may just be one event #if Debug MainConsole.Instance.Warn ("Sleep: " + timeToSleep); #endif Interlocked.Increment(ref scriptThreadpool.nSleepingthreads); Thread.Sleep(timeToSleep); Interlocked.Decrement(ref scriptThreadpool.nSleepingthreads); } }
public bool SetEventParams(QueueItemStruct itm) { if (Suspended || !Running) { return(false); //No suspended scripts... } if (itm.llDetectParams.Length > 0) { LastDetectParams = itm.llDetectParams; } if (itm.functionName == "state_entry" || itm.functionName == "state_exit" || itm.functionName == "on_rez") { return(true); } long NowTicks = Util.EnvironmentTickCount(); if (EventDelayTicks != 0) { if (NowTicks < NextEventTimeTicks) { return(false); } NextEventTimeTicks = NowTicks + EventDelayTicks; } switch (itm.functionName) { //Times pulled from http://wiki.secondlife.com/wiki/LSL_Delay case "touch": //Limits for 0.1 seconds case "touch_start": case "touch_end": if (NowTicks < NextEventDelay[itm.functionName]) { return(CheckAddEventToQueue(itm)); } NextEventDelay[itm.functionName] = NowTicks + (long)(TouchEventDelayTicks * TicksPerMillisecond); break; case "timer": //Settable timer limiter if (NowTicks < NextEventDelay[itm.functionName]) { return(CheckAddEventToQueue(itm)); } NextEventDelay[itm.functionName] = NowTicks + (long)(TimerEventDelayTicks * TicksPerMillisecond); break; case "collision": case "collision_start": case "collision_end": case "land_collision": case "land_collision_start": case "land_collision_end": if (NowTicks < NextEventDelay[itm.functionName]) { return(CheckAddEventToQueue(itm)); } NextEventDelay[itm.functionName] = NowTicks + (long)(CollisionEventDelayTicks * TicksPerMillisecond); break; case "control": if (NowTicks < NextEventDelay[itm.functionName]) { return(CheckAddEventToQueue(itm)); } NextEventDelay[itm.functionName] = NowTicks + (long)(0.05f * TicksPerMillisecond); break; default: //Default is 0.05 seconds for event limiting if (!NextEventDelay.ContainsKey(itm.functionName)) { break; //If it doesn't exist, we don't limit it } if (NowTicks < NextEventDelay[itm.functionName]) { return(CheckAddEventToQueue(itm)); } NextEventDelay[itm.functionName] = NowTicks + (long)(DefaultEventDelayTicks * TicksPerMillisecond); break; } //Add the event to the stats ScriptScore++; m_ScriptEngine.ScriptEPS++; return(true); }
public bool EventSchProcessQIS(ref QueueItemStruct QIS) { try { Exception ex = null; EnumeratorInfo Running = QIS.ID.Script.ExecuteEvent(QIS.State, QIS.functionName, QIS.param, QIS.CurrentlyAt, out ex); if (QIS.ID.VersionID != QIS.VersionID) return false; if (ex != null) { //Check exceptions, some are ours to deal with, and others are to be logged if (ex is SelfDeleteException) { if (QIS.ID.part != null && QIS.ID.part.ParentGroup != null) QIS.ID.part.ParentGroup.Scene.DeleteSceneObject( QIS.ID.part.ParentGroup, false, true); } else if (ex is ScriptDeleteException) { if (QIS.ID.part != null && QIS.ID.part.ParentGroup != null) QIS.ID.part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); } //Log it for the user else if (!(ex is EventAbortException) && !(ex is MinEventDelayException)) QIS.ID.DisplayUserNotification(ex.Message, "", false, true); return false; } else if (Running != null) { //Did not finish so requeue it QIS.CurrentlyAt = Running; return true; //Do the return... otherwise we open the queue for this event back up } } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.Message, "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return false; }
public void AddEventSchQIS(QueueItemStruct QIS) { ScriptData ID; ID = QIS.ID; if (ID == null || ID.EventsProcData.IgnoreNew) return; if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules return; QIS.CurrentlyAt = null; Interlocked.Exchange(ref ID.EventsProcDataLocked, 1); lock (ID.EventsProcData) { if (ID.EventsProcData.EventsQueue.Count > 100) { Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); return; } ID.EventsProcData.EventsQueue.Enqueue(QIS); lock (ScriptIDs) { if (!ID.InEventsProcData) { ID.EventsProcData.State = (int)ScriptEventsState.Idle; ID.EventsProcData.thread = null; ScriptIDs.AddLast(ID); Interlocked.Increment(ref nScriptIDs); Interlocked.Increment(ref nEventScripts); ID.InEventsProcData = true; } } Interlocked.Exchange(ref ID.EventsProcDataLocked, 0); } lock (WorkersLock) { if (WorkersLock.nWorkers < MaxScriptThreads && WorkersLock.nWorkers < nScriptIDs) { Scriptthreadpool.QueueEvent(loop, 2); } } }
/// <summary> /// This removes the event from the queue and allows it to be fired again /// </summary> /// <param name="QIS"></param> public void EventComplete(QueueItemStruct QIS) { lock (QIS.ID.ScriptEventLock) { scriptEvents eventType = (scriptEvents)Enum.Parse(typeof(scriptEvents), QIS.functionName); switch (eventType) { case scriptEvents.timer: QIS.ID.TimerInQueue = false; break; case scriptEvents.control: if (QIS.ID.ControlEventsInQueue > 0) { QIS.ID.ControlEventsInQueue--; } break; case scriptEvents.collision: QIS.ID.CollisionInQueue = false; break; case scriptEvents.collision_end: QIS.ID.CollisionInQueue = false; break; case scriptEvents.moving_end: QIS.ID.MovingInQueue = false; break; case scriptEvents.touch: QIS.ID.TouchInQueue = false; break; case scriptEvents.touch_end: QIS.ID.TouchInQueue = false; break; case scriptEvents.land_collision: QIS.ID.LandCollisionInQueue = false; break; case scriptEvents.land_collision_end: QIS.ID.LandCollisionInQueue = false; break; case scriptEvents.sensor: QIS.ID.SensorInQueue = false; break; case scriptEvents.no_sensor: QIS.ID.NoSensorInQueue = false; break; case scriptEvents.at_target: QIS.ID.AtTargetInQueue = false; break; case scriptEvents.not_at_target: QIS.ID.NotAtTargetInQueue = false; break; case scriptEvents.at_rot_target: QIS.ID.AtRotTargetInQueue = false; break; case scriptEvents.not_at_rot_target: QIS.ID.NotAtRotTargetInQueue = false; break; case scriptEvents.changed: Changed changed; if (QIS.param[0] is Changed) { changed = (Changed)QIS.param[0]; } else { changed = (Changed)(((LSL_Types.LSLInteger)QIS.param[0]).value); } QIS.ID.ChangedInQueue.Remove(changed); break; } } }
public void AddEvent(QueueItemStruct QIS, EventPriority priority) { if (RunInMainProcessingThread) { ProcessQIS(QIS); } else { EventProcessorQueue.Add(QIS, priority); if (!EventProcessorIsRunning) StartThread("Event"); } }
public bool EventSchProcessQIS(ref QueueItemStruct QIS) { try { if(QIS.ID.Script == null) return false; QIS.ID.Script.ExecuteEvent(QIS.State, QIS.functionName, QIS.param); // if (QIS.ID.VersionID != QIS.VersionID) // return false; /*if (ex != null) { //Check exceptions, some are ours to deal with, and others are to be logged if (ex is SelfDeleteException) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) { IBackupModule backup = QIS.ID.Part.ParentEntity.Scene.RequestModuleInterface<IBackupModule> (); if (backup != null) backup.DeleteSceneObjects( new ISceneEntity[1] { QIS.ID.Part.ParentEntity }, true); } } else if (ex is ScriptDeleteException) { if (QIS.ID.Part != null && QIS.ID.Part.ParentEntity != null) QIS.ID.Part.Inventory.RemoveInventoryItem(QIS.ID.ItemID); } //Log it for the user else if (!(ex is EventAbortException) && !(ex is MinEventDelayException)) QIS.ID.DisplayUserNotification(ex.ToString(), "", false, true); return false; }*/ } catch (Exception ex) { //Error, tell the user QIS.ID.DisplayUserNotification(ex.ToString(), "executing", false, true); } //Tell the event manager about it so that the events will be removed from the queue EventManager.EventComplete(QIS); return false; }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, int VersionID, EventPriority priority, params object[] param) { QueueItemStruct QIS; if (ID == null || ID.EventsProcData.IgnoreNew) return; if (!ID.SetEventParams(FunctionName, qParams)) // check events delay rules return; QIS = new QueueItemStruct(); QIS.ID = ID; QIS.functionName = FunctionName; QIS.llDetectParams = qParams; QIS.param = param; QIS.VersionID = VersionID; QIS.State = ID.State; QIS.CurrentlyAt = null; lock (ID.EventsProcData) { ID.EventsProcDataLocked = true; if (ID.EventsProcData.EventsQueue.Count > 100) { ID.EventsProcDataLocked = false; return; } ID.EventsProcData.EventsQueue.Enqueue(QIS); lock (ScriptIDs) { if (!ScriptIDs.Contains(ID)) { ID.EventsProcData.State = (int)ScriptEventsState.Idle; ID.EventsProcData.thread = null; ScriptIDs.AddLast(ID); NScriptIDs++; ID.InEventsProcData = true; } } } ID.EventsProcDataLocked = false; lock (WorkersLock) { if (WorkersLock.nWorkers < MaxScriptThreads) { Scriptthreadpool.QueueEvent(loop, 2); } } }
public void AddEventSchQIS(QueueItemStruct QIS) { if (QIS.ID == null || QIS.ID.Script == null || QIS.ID.IgnoreNew) { EventManager.EventComplete(QIS); return; } if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules { EventManager.EventComplete(QIS); return; } QIS.CurrentlyAt = null; lock (ScriptEvents) { ScriptEvents.Enqueue(QIS); ScriptEventCount++; #if Debug MainConsole.Instance.Warn (ScriptEventCount + ", " + QIS.functionName); #endif } long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEventCount + (SleepingScriptEventCount/2))*EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } }
/// <summary> /// This removes the event from the queue and allows it to be fired again /// </summary> /// <param name = "QIS"></param> public void EventComplete(QueueItemStruct QIS) { lock (QIS.ID.ScriptEventLock) { scriptEvents eventType = (scriptEvents)Enum.Parse(typeof(scriptEvents), QIS.functionName); switch (eventType) { case scriptEvents.timer: QIS.ID.TimerInQueue = false; break; case scriptEvents.control: if (QIS.ID.ControlEventsInQueue > 0) QIS.ID.ControlEventsInQueue--; break; case scriptEvents.collision: QIS.ID.CollisionInQueue = false; break; case scriptEvents.collision_end: QIS.ID.CollisionInQueue = false; break; case scriptEvents.moving_end: QIS.ID.MovingInQueue = false; break; case scriptEvents.touch: QIS.ID.TouchInQueue = false; break; case scriptEvents.touch_end: QIS.ID.TouchInQueue = false; break; case scriptEvents.land_collision: QIS.ID.LandCollisionInQueue = false; break; case scriptEvents.land_collision_end: QIS.ID.LandCollisionInQueue = false; break; case scriptEvents.sensor: QIS.ID.SensorInQueue = false; break; case scriptEvents.no_sensor: QIS.ID.NoSensorInQueue = false; break; case scriptEvents.at_target: QIS.ID.AtTargetInQueue = false; break; case scriptEvents.not_at_target: QIS.ID.NotAtTargetInQueue = false; break; case scriptEvents.at_rot_target: QIS.ID.AtRotTargetInQueue = false; break; case scriptEvents.not_at_rot_target: QIS.ID.NotAtRotTargetInQueue = false; break; case scriptEvents.changed: Changed changed; if (QIS.param[0] is Changed) { changed = (Changed) QIS.param[0]; } else { changed = (Changed) (((LSL_Types.LSLInteger) QIS.param[0]).value); } QIS.ID.ChangedInQueue.Remove(changed); break; } } }
public bool AddEventSchQIS(QueueItemStruct QIS, EventPriority priority) { if (QIS.ID == null || QIS.ID.Script == null || QIS.ID.IgnoreNew) { EventManager.EventComplete(QIS); return false; } if (!QIS.ID.SetEventParams(QIS.functionName, QIS.llDetectParams)) // check events delay rules { EventManager.EventComplete(QIS); return false; } QIS.CurrentlyAt = null; if (priority == EventPriority.Suspended || priority == EventPriority.Continued) { lock (SleepingScriptEvents) { long time = priority == EventPriority.Suspended ? DateTime.Now.AddMilliseconds(10).Ticks : DateTime.Now.Ticks; //Let it sleep for 10ms so that other scripts can process before it, any repeating plugins ought to use this SleepingScriptEvents.Enqueue(QIS, time); SleepingScriptEventCount++; #if Debug MainConsole.Instance.Warn (ScriptEventCount + ", " + QIS.functionName); #endif } } else ScriptEvents.Enqueue(QIS); long threadCount = Interlocked.Read(ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEvents.Count + (SleepingScriptEventCount/2))*EventPerformance) { scriptThreadpool.QueueEvent(eventLoop, 2); } return true; }
public void AddEventSchQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, EventPriority priority, params object[] param) { QueueItemStruct QIS; if (ID == null || ID.Script == null || ID.IgnoreNew) return; if (!ID.SetEventParams(FunctionName, qParams)) // check events delay rules return; QIS = new QueueItemStruct(); QIS.EventsProcData = new ScriptEventsProcData (); QIS.ID = ID; QIS.functionName = FunctionName; QIS.llDetectParams = qParams; QIS.param = param; QIS.VersionID = Interlocked.Read(ref ID.VersionID); QIS.State = ID.State; QIS.CurrentlyAt = null; lock (ScriptEvents) { ScriptEvents.Enqueue (QIS); ScriptEventCount++; #if Debug m_log.Warn (ScriptEventCount + ", " + QIS.functionName); #endif } long threadCount = Interlocked.Read (ref scriptThreadpool.nthreads); if (threadCount == 0 || threadCount < (ScriptEventCount + (SleepingScriptEventCount / 2)) * EventPerformance) { scriptThreadpool.QueueEvent (eventLoop, 2); } }
public void EventSchExec(QueueItemStruct QIS) { if (QIS.ID == null || QIS.ID.Script == null) return; if (!QIS.ID.Running) { //do only state_entry and on_rez if (QIS.functionName != "state_entry" || QIS.functionName != "on_rez") { return; } } //Check the versionID so that we can kill events if (QIS.functionName != "link_message" && QIS.VersionID != Interlocked.Read(ref QIS.ID.VersionID)) { MainConsole.Instance.WarnFormat("FOUND BAD VERSION ID, OLD {0}, NEW {1}, FUNCTION NAME {2}", QIS.VersionID, Interlocked.Read(ref QIS.ID.VersionID), QIS.functionName); //return; } if(MainConsole.Instance.IsTraceEnabled) MainConsole.Instance.TraceFormat("[ADNE]: Running Event {0} in object {1} in region {2}", QIS.functionName, QIS.ID.Part.ToString(), QIS.ID.Part.ParentEntity.Scene.RegionInfo.RegionName); if (!EventSchProcessQIS(ref QIS)) //Execute the event { //All done QIS.EventsProcData.State = ScriptEventsState.Idle; } else { if (QIS.CurrentlyAt.SleepTo.Ticks != 0) { QIS.EventsProcData.TimeCheck = QIS.CurrentlyAt.SleepTo; QIS.EventsProcData.State = ScriptEventsState.Sleep; //If it is greater, we need to check sooner for this one if (NextSleepersTest.Ticks > QIS.CurrentlyAt.SleepTo.Ticks) NextSleepersTest = QIS.CurrentlyAt.SleepTo; lock (SleepingScriptEvents) { SleepingScriptEvents.Enqueue(QIS, QIS.CurrentlyAt.SleepTo.Ticks); SleepingScriptEventCount++; } } else { QIS.EventsProcData.State = ScriptEventsState.Running; this.ScriptEvents.Enqueue(QIS); } } }
public void EventSchExec (QueueItemStruct QIS) { if (QIS.ID == null) return; if (!QIS.ID.Running) { //do only state_entry and on_rez if (QIS.functionName != "state_entry" || QIS.functionName != "on_rez") { return; } } //Check the versionID so that we can kill events if (QIS.VersionID != Interlocked.Read(ref QIS.ID.VersionID)) { m_log.WarnFormat ("FOUND BAD VERSION ID, OLD {0}, NEW {1}, FUNCTION NAME {2}", QIS.VersionID, Interlocked.Read(ref QIS.ID.VersionID), QIS.functionName); return; } if (!EventSchProcessQIS(ref QIS)) //Execute the event { //All done QIS.EventsProcData.State = ScriptEventsState.Idle; } else { if (QIS.CurrentlyAt.SleepTo.Ticks != 0) { QIS.EventsProcData.TimeCheck = QIS.CurrentlyAt.SleepTo; QIS.EventsProcData.State = ScriptEventsState.Sleep; //If it is greater, we need to check sooner for this one if (NextSleepersTest.Ticks > QIS.CurrentlyAt.SleepTo.Ticks) NextSleepersTest = QIS.CurrentlyAt.SleepTo; lock (SleepingScriptEvents) { SleepingScriptEvents.Enqueue (QIS, QIS.CurrentlyAt.SleepTo.Ticks); SleepingScriptEventCount++; } } else { QIS.EventsProcData.State = ScriptEventsState.Running; lock (ScriptEvents) { this.ScriptEvents.Enqueue (QIS); ScriptEventCount++; } } } }
/// <summary> /// This removes the event from the queue and allows it to be fired again /// </summary> /// <param name="QIS"></param> public void EventComplete(QueueItemStruct QIS) { lock (QIS.ID.ScriptEventLock) { if (QIS.functionName == "timer") QIS.ID.TimerQueued = false; else if (QIS.functionName == "control") { if (QIS.ID.ControlEventsInQueue > 0) QIS.ID.ControlEventsInQueue--; } else if (QIS.functionName == "collision") QIS.ID.CollisionInQueue = false; else if (QIS.functionName == "collision_end") QIS.ID.CollisionInQueue = false; else if (QIS.functionName == "moving_end") QIS.ID.MovingInQueue = false; else if (QIS.functionName == "touch") QIS.ID.TouchInQueue = false; else if (QIS.functionName == "touch_end") QIS.ID.TouchInQueue = false; else if (QIS.functionName == "land_collision") QIS.ID.LandCollisionInQueue = false; else if (QIS.functionName == "changed") { Changed changed; if (QIS.param[0] is Changed) { changed = (Changed)QIS.param[0]; } else { changed = (Changed)(((LSL_Types.LSLInteger)QIS.param[0]).value); } QIS.ID.ChangedInQueue.Remove (changed); } } }
/// <summary> /// Posts the event to the given object. /// </summary> /// <param name="ID"></param> /// <param name="FunctionName"></param> /// <param name="qParams"></param> /// <param name="param"></param> /// <returns></returns> public bool AddToScriptQueue(ScriptData ID, string FunctionName, DetectParams[] qParams, int VersionID, EventPriority priority, params object[] param) { // Create a structure and add data QueueItemStruct QIS = new QueueItemStruct(); QIS.ID = ID; QIS.functionName = FunctionName; QIS.llDetectParams = qParams; QIS.param = param; QIS.VersionID = VersionID; QIS.State = ID.State; MaintenanceThread.AddEvent(QIS, priority); return true; }