示例#1
0
        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++;
                    }
                }
            }
        }
示例#2
0
        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);
            }
        }
示例#3
0
        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);
        }
示例#4
0
        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);
            }
        }
示例#5
0
        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);
                }
            }
        }
示例#6
0
        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);
        }
示例#7
0
 /// <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);
     }
 }
示例#8
0
        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);
                }
            }
        }
示例#9
0
        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);
        }
示例#10
0
        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);
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
        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;
        }
示例#14
0
 public void AddEvent(QueueItemStruct QIS, EventPriority priority)
 {
     AddEventSchQIS(QIS);
 }
示例#15
0
        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;
        }
示例#16
0
        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);
            }
        }
示例#17
0
        /// <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;
        }
示例#18
0
        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);
        }
示例#19
0
        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;
        }
示例#21
0
 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);
            }
        }
示例#24
0
 public void AddEvent(QueueItemStruct QIS, EventPriority priority)
 {
     AddEventSchQIS(QIS);
 }
示例#25
0
        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);
        }
示例#26
0
        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;
        }
示例#27
0
        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);
                    }
                }
            }
示例#28
0
        /// <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;
                }
            }
        }
示例#29
0
        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);
        }
示例#30
0
 public void AddEvent(QueueItemStruct QIS, EventPriority priority)
 {
     if (RunInMainProcessingThread)
     {
         ProcessQIS(QIS);
     }
     else
     {
         EventProcessorQueue.Add(QIS, priority);
         if (!EventProcessorIsRunning)
             StartThread("Event");
     }
 }
示例#31
0
        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;
        }
示例#32
0
        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);
                }
            }
        }
示例#33
0
        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);
            }
        }
示例#34
0
 /// <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++;
                    }
                }
            }
        }
示例#39
0
 /// <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);
         }
     }
 }
示例#40
0
        /// <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;
        }