* This is Melanie's XEngine script engine. I've not tested this real well, however, it's confirmed to compile and OpenSimulator to run successfully without this script engine active.
parent
334d05db05
commit
1a47ff8094
|
@ -0,0 +1,270 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins;
|
||||||
|
using Timer=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Timer;
|
||||||
|
using Dataserver=OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins.Dataserver;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Handles LSL commands that takes long time and returns an event, for example timers, HTTP requests, etc.
|
||||||
|
/// </summary>
|
||||||
|
public class AsyncCommandManager
|
||||||
|
{
|
||||||
|
private static Thread cmdHandlerThread;
|
||||||
|
private static int cmdHandlerThreadCycleSleepms;
|
||||||
|
|
||||||
|
public XEngine m_ScriptEngine;
|
||||||
|
|
||||||
|
public Dataserver m_Dataserver;
|
||||||
|
public Timer m_Timer;
|
||||||
|
public HttpRequest m_HttpRequest;
|
||||||
|
public Listener m_Listener;
|
||||||
|
public SensorRepeat m_SensorRepeat;
|
||||||
|
public XmlRequest m_XmlRequest;
|
||||||
|
|
||||||
|
public AsyncCommandManager(XEngine _ScriptEngine)
|
||||||
|
{
|
||||||
|
m_ScriptEngine = _ScriptEngine;
|
||||||
|
ReadConfig();
|
||||||
|
|
||||||
|
// Create instances of all plugins
|
||||||
|
m_Dataserver = new Dataserver(this);
|
||||||
|
m_Timer = new Timer(this);
|
||||||
|
m_HttpRequest = new HttpRequest(this);
|
||||||
|
m_Listener = new Listener(this);
|
||||||
|
m_SensorRepeat = new SensorRepeat(this);
|
||||||
|
m_XmlRequest = new XmlRequest(this);
|
||||||
|
|
||||||
|
StartThread();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void StartThread()
|
||||||
|
{
|
||||||
|
if (cmdHandlerThread == null)
|
||||||
|
{
|
||||||
|
// Start the thread that will be doing the work
|
||||||
|
cmdHandlerThread = new Thread(CmdHandlerThreadLoop);
|
||||||
|
cmdHandlerThread.Name = "AsyncLSLCmdHandlerThread";
|
||||||
|
cmdHandlerThread.Priority = ThreadPriority.BelowNormal;
|
||||||
|
cmdHandlerThread.IsBackground = true;
|
||||||
|
cmdHandlerThread.Start();
|
||||||
|
ThreadTracker.Add(cmdHandlerThread);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ReadConfig()
|
||||||
|
{
|
||||||
|
cmdHandlerThreadCycleSleepms = m_ScriptEngine.ScriptConfigSource.GetInt("AsyncLLCommandLoopms", 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
~AsyncCommandManager()
|
||||||
|
{
|
||||||
|
// Shut down thread
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (cmdHandlerThread != null)
|
||||||
|
{
|
||||||
|
if (cmdHandlerThread.IsAlive == true)
|
||||||
|
{
|
||||||
|
cmdHandlerThread.Abort();
|
||||||
|
//cmdHandlerThread.Join();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CmdHandlerThreadLoop()
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Thread.Sleep(cmdHandlerThreadCycleSleepms);
|
||||||
|
|
||||||
|
foreach (XEngine xe in XEngine.ScriptEngines)
|
||||||
|
{
|
||||||
|
xe.m_ASYNCLSLCommandManager.DoOneCmdHandlerPass();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void DoOneCmdHandlerPass()
|
||||||
|
{
|
||||||
|
// Check timers
|
||||||
|
m_Timer.CheckTimerEvents();
|
||||||
|
// Check HttpRequests
|
||||||
|
m_HttpRequest.CheckHttpRequests();
|
||||||
|
// Check XMLRPCRequests
|
||||||
|
m_XmlRequest.CheckXMLRPCRequests();
|
||||||
|
// Check Listeners
|
||||||
|
m_Listener.CheckListeners();
|
||||||
|
// Check Sensors
|
||||||
|
m_SensorRepeat.CheckSenseRepeaterEvents();
|
||||||
|
// Check dataserver
|
||||||
|
m_Dataserver.ExpireRequests();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a specific script (and all its pending commands)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="localID"></param>
|
||||||
|
/// <param name="itemID"></param>
|
||||||
|
public void RemoveScript(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
// Remove a specific script
|
||||||
|
|
||||||
|
// Remove dataserver events
|
||||||
|
m_Dataserver.RemoveEvents(localID, itemID);
|
||||||
|
|
||||||
|
// Remove from: Timers
|
||||||
|
m_Timer.UnSetTimerEvents(localID, itemID);
|
||||||
|
|
||||||
|
// Remove from: HttpRequest
|
||||||
|
IHttpRequests iHttpReq =
|
||||||
|
m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
||||||
|
iHttpReq.StopHttpRequest(localID, itemID);
|
||||||
|
|
||||||
|
IWorldComm comms = m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
|
comms.DeleteListener(itemID);
|
||||||
|
|
||||||
|
IXMLRPC xmlrpc = m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
|
||||||
|
xmlrpc.DeleteChannels(itemID);
|
||||||
|
xmlrpc.CancelSRDRequests(itemID);
|
||||||
|
|
||||||
|
// Remove Sensors
|
||||||
|
m_SensorRepeat.UnSetSenseRepeaterEvents(localID, itemID);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] GetSerializationData(LLUUID itemID)
|
||||||
|
{
|
||||||
|
List<Object> data = new List<Object>();
|
||||||
|
|
||||||
|
Object[] listeners=m_Listener.GetSerializationData(itemID);
|
||||||
|
if(listeners.Length > 0)
|
||||||
|
{
|
||||||
|
data.Add("listener");
|
||||||
|
data.Add(listeners.Length);
|
||||||
|
data.AddRange(listeners);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] timers=m_Timer.GetSerializationData(itemID);
|
||||||
|
if(timers.Length > 0)
|
||||||
|
{
|
||||||
|
data.Add("timer");
|
||||||
|
data.Add(timers.Length);
|
||||||
|
data.AddRange(timers);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object[] sensors=m_SensorRepeat.GetSerializationData(itemID);
|
||||||
|
if(sensors.Length > 0)
|
||||||
|
{
|
||||||
|
data.Add("sensor");
|
||||||
|
data.Add(sensors.Length);
|
||||||
|
data.AddRange(sensors);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID,
|
||||||
|
Object[] data)
|
||||||
|
{
|
||||||
|
int idx=0;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
while(idx < data.Length)
|
||||||
|
{
|
||||||
|
string type = data[idx].ToString();
|
||||||
|
len = (int)data[idx+1];
|
||||||
|
idx+=2;
|
||||||
|
|
||||||
|
if(len > 0)
|
||||||
|
{
|
||||||
|
Object[] item = new Object[len];
|
||||||
|
Array.Copy(data, idx, item, 0, len);
|
||||||
|
|
||||||
|
idx+=len;
|
||||||
|
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case "listener":
|
||||||
|
m_Listener.CreateFromData(localID, itemID, hostID,
|
||||||
|
item);
|
||||||
|
break;
|
||||||
|
case "timer":
|
||||||
|
m_Timer.CreateFromData(localID, itemID, hostID, item);
|
||||||
|
break;
|
||||||
|
case "sensor":
|
||||||
|
m_SensorRepeat.CreateFromData(localID, itemID, hostID,
|
||||||
|
item);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Check llRemoteData channels
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Check llListeners
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If set to true then threads and stuff should try to make a graceful exit
|
||||||
|
/// </summary>
|
||||||
|
public bool PleaseShutdown
|
||||||
|
{
|
||||||
|
get { return _PleaseShutdown; }
|
||||||
|
set { _PleaseShutdown = value; }
|
||||||
|
}
|
||||||
|
private bool _PleaseShutdown = false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,127 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class Dataserver
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
private Dictionary<string, DataserverRequest> DataserverRequests =
|
||||||
|
new Dictionary<string, DataserverRequest>();
|
||||||
|
|
||||||
|
public Dataserver(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DataserverRequest
|
||||||
|
{
|
||||||
|
public uint localID;
|
||||||
|
public LLUUID itemID;
|
||||||
|
|
||||||
|
public LLUUID ID;
|
||||||
|
public string handle;
|
||||||
|
|
||||||
|
public DateTime startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LLUUID RegisterRequest(uint localID, LLUUID itemID,
|
||||||
|
string identifier)
|
||||||
|
{
|
||||||
|
lock(DataserverRequests)
|
||||||
|
{
|
||||||
|
if(DataserverRequests.ContainsKey(identifier))
|
||||||
|
return LLUUID.Zero;
|
||||||
|
|
||||||
|
DataserverRequest ds = new DataserverRequest();
|
||||||
|
|
||||||
|
ds.localID = localID;
|
||||||
|
ds.itemID = itemID;
|
||||||
|
|
||||||
|
ds.ID = LLUUID.Random();
|
||||||
|
ds.handle = identifier;
|
||||||
|
|
||||||
|
ds.startTime = DateTime.Now;
|
||||||
|
|
||||||
|
DataserverRequests[identifier]=ds;
|
||||||
|
|
||||||
|
return ds.ID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void DataserverReply(string identifier, string reply)
|
||||||
|
{
|
||||||
|
DataserverRequest ds;
|
||||||
|
|
||||||
|
lock(DataserverRequests)
|
||||||
|
{
|
||||||
|
if(!DataserverRequests.ContainsKey(identifier))
|
||||||
|
return;
|
||||||
|
|
||||||
|
ds=DataserverRequests[identifier];
|
||||||
|
DataserverRequests.Remove(identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CmdManager.m_ScriptEngine.PostObjectEvent(ds.localID,
|
||||||
|
new XEventParams( "dataserver", new Object[]
|
||||||
|
{ new LSL_Types.LSLString(ds.ID.ToString()),
|
||||||
|
new LSL_Types.LSLString(reply)},
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveEvents(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
lock(DataserverRequests)
|
||||||
|
{
|
||||||
|
foreach (DataserverRequest ds in new List<DataserverRequest>(DataserverRequests.Values))
|
||||||
|
{
|
||||||
|
if(ds.itemID == itemID)
|
||||||
|
DataserverRequests.Remove(ds.handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ExpireRequests()
|
||||||
|
{
|
||||||
|
lock(DataserverRequests)
|
||||||
|
{
|
||||||
|
foreach (DataserverRequest ds in new List<DataserverRequest>(DataserverRequests.Values))
|
||||||
|
{
|
||||||
|
if(ds.startTime > DateTime.Now.AddSeconds(30))
|
||||||
|
DataserverRequests.Remove(ds.handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,76 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class Eventstream
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
private class Event
|
||||||
|
{
|
||||||
|
public uint LocalID;
|
||||||
|
public string EventName;
|
||||||
|
public Dictionary<LLUUID, XDetectParams> DetectParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Dictionary<uint, Dictionary<string, Event> > m_Events =
|
||||||
|
new Dictionary<uint, Dictionary<string, Event> >();
|
||||||
|
|
||||||
|
public Eventstream(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddObjectEvent(uint localID, string eventName, XDetectParams det)
|
||||||
|
{
|
||||||
|
SceneObjectPart part = m_CmdManager.m_ScriptEngine.World.
|
||||||
|
GetSceneObjectPart(localID);
|
||||||
|
|
||||||
|
if(part == null) // Can't register events for non-prims
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!part.ContainsScripts())
|
||||||
|
return;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveObjectEvent(uint localID, string eventName, LLUUID id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveObjects(uint localID)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.Environment.Modules.Scripting.HttpRequest;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class HttpRequest
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
public HttpRequest(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckHttpRequests()
|
||||||
|
{
|
||||||
|
if (m_CmdManager.m_ScriptEngine.World == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IHttpRequests iHttpReq =
|
||||||
|
m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IHttpRequests>();
|
||||||
|
|
||||||
|
HttpRequestClass httpInfo = null;
|
||||||
|
|
||||||
|
if (iHttpReq != null)
|
||||||
|
httpInfo = iHttpReq.GetNextCompletedRequest();
|
||||||
|
|
||||||
|
while (httpInfo != null)
|
||||||
|
{
|
||||||
|
//m_ScriptEngine.Log.Info("[AsyncLSL]:" + httpInfo.response_body + httpInfo.status);
|
||||||
|
|
||||||
|
// Deliver data to prim's remote_data handler
|
||||||
|
//
|
||||||
|
// TODO: Returning null for metadata, since the lsl function
|
||||||
|
// only returns the byte for HTTP_BODY_TRUNCATED, which is not
|
||||||
|
// implemented here yet anyway. Should be fixed if/when maxsize
|
||||||
|
// is supported
|
||||||
|
|
||||||
|
iHttpReq.RemoveCompletedRequest(httpInfo.reqID);
|
||||||
|
|
||||||
|
object[] resobj = new object[]
|
||||||
|
{
|
||||||
|
new LSL_Types.LSLString(httpInfo.reqID.ToString()),
|
||||||
|
new LSL_Types.LSLInteger(httpInfo.status),
|
||||||
|
new LSL_Types.list(),
|
||||||
|
new LSL_Types.LSLString(httpInfo.response_body)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (XEngine xe in XEngine.ScriptEngines)
|
||||||
|
{
|
||||||
|
if(xe.PostObjectEvent(httpInfo.localID,
|
||||||
|
new XEventParams("http_response",
|
||||||
|
resobj, new XDetectParams[0])))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
httpInfo = iHttpReq.GetNextCompletedRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.Environment.Modules.Scripting.WorldComm;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class Listener
|
||||||
|
{
|
||||||
|
// private static readonly log4net.ILog m_log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
public Listener(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckListeners()
|
||||||
|
{
|
||||||
|
if (m_CmdManager.m_ScriptEngine.World == null)
|
||||||
|
return;
|
||||||
|
IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
|
|
||||||
|
if (comms != null)
|
||||||
|
{
|
||||||
|
while (comms.HasMessages())
|
||||||
|
{
|
||||||
|
ListenerInfo lInfo = comms.GetNextMessage();
|
||||||
|
|
||||||
|
//Deliver data to prim's listen handler
|
||||||
|
object[] resobj = new object[]
|
||||||
|
{
|
||||||
|
new LSL_Types.LSLInteger(lInfo.GetChannel()),
|
||||||
|
new LSL_Types.LSLString(lInfo.GetName()),
|
||||||
|
new LSL_Types.LSLString(lInfo.GetID().ToString()),
|
||||||
|
new LSL_Types.LSLString(lInfo.GetMessage())
|
||||||
|
};
|
||||||
|
|
||||||
|
m_CmdManager.m_ScriptEngine.PostScriptEvent(
|
||||||
|
lInfo.GetItemID(), new XEventParams(
|
||||||
|
"listen", resobj,
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] GetSerializationData(LLUUID itemID)
|
||||||
|
{
|
||||||
|
IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
|
|
||||||
|
return comms.GetSerializationData(itemID);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFromData(uint localID, LLUUID itemID, LLUUID hostID,
|
||||||
|
Object[] data)
|
||||||
|
{
|
||||||
|
IWorldComm comms = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IWorldComm>();
|
||||||
|
|
||||||
|
comms.CreateFromData(localID, itemID, hostID, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,391 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class SensorRepeat
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
public SensorRepeat(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>> SenseEvents =
|
||||||
|
new Dictionary<uint, Dictionary<LLUUID, LSL_Types.list>>();
|
||||||
|
private Object SenseLock = new Object();
|
||||||
|
|
||||||
|
//
|
||||||
|
// SenseRepeater and Sensors
|
||||||
|
//
|
||||||
|
private class SenseRepeatClass
|
||||||
|
{
|
||||||
|
public uint localID;
|
||||||
|
public LLUUID itemID;
|
||||||
|
public double interval;
|
||||||
|
public DateTime next;
|
||||||
|
|
||||||
|
public string name;
|
||||||
|
public LLUUID keyID;
|
||||||
|
public int type;
|
||||||
|
public double range;
|
||||||
|
public double arc;
|
||||||
|
public SceneObjectPart host;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<SenseRepeatClass> SenseRepeaters = new List<SenseRepeatClass>();
|
||||||
|
private object SenseRepeatListLock = new object();
|
||||||
|
|
||||||
|
public void SetSenseRepeatEvent(uint m_localID, LLUUID m_itemID,
|
||||||
|
string name, LLUUID keyID, int type, double range, double arc, double sec, SceneObjectPart host)
|
||||||
|
{
|
||||||
|
Console.WriteLine("SetSensorEvent");
|
||||||
|
|
||||||
|
// Always remove first, in case this is a re-set
|
||||||
|
UnSetSenseRepeaterEvents(m_localID, m_itemID);
|
||||||
|
if (sec == 0) // Disabling timer
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add to timer
|
||||||
|
SenseRepeatClass ts = new SenseRepeatClass();
|
||||||
|
ts.localID = m_localID;
|
||||||
|
ts.itemID = m_itemID;
|
||||||
|
ts.interval = sec;
|
||||||
|
ts.name = name;
|
||||||
|
ts.keyID = keyID;
|
||||||
|
ts.type = type;
|
||||||
|
ts.range = range;
|
||||||
|
ts.arc = arc;
|
||||||
|
ts.host = host;
|
||||||
|
|
||||||
|
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
|
lock (SenseRepeatListLock)
|
||||||
|
{
|
||||||
|
SenseRepeaters.Add(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnSetSenseRepeaterEvents(uint m_localID, LLUUID m_itemID)
|
||||||
|
{
|
||||||
|
// Remove from timer
|
||||||
|
lock (SenseRepeatListLock)
|
||||||
|
{
|
||||||
|
List<SenseRepeatClass> NewSensors = new List<SenseRepeatClass>();
|
||||||
|
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||||
|
{
|
||||||
|
if (ts.localID != m_localID && ts.itemID != m_itemID)
|
||||||
|
{
|
||||||
|
NewSensors.Add(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SenseRepeaters.Clear();
|
||||||
|
SenseRepeaters = NewSensors;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckSenseRepeaterEvents()
|
||||||
|
{
|
||||||
|
// Nothing to do here?
|
||||||
|
if (SenseRepeaters.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (SenseRepeatListLock)
|
||||||
|
{
|
||||||
|
// Go through all timers
|
||||||
|
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||||
|
{
|
||||||
|
// Time has passed?
|
||||||
|
if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime())
|
||||||
|
{
|
||||||
|
SensorSweep(ts);
|
||||||
|
// set next interval
|
||||||
|
ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // lock
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SenseOnce(uint m_localID, LLUUID m_itemID,
|
||||||
|
string name, LLUUID keyID, int type,
|
||||||
|
double range, double arc, SceneObjectPart host)
|
||||||
|
{
|
||||||
|
// Add to timer
|
||||||
|
SenseRepeatClass ts = new SenseRepeatClass();
|
||||||
|
ts.localID = m_localID;
|
||||||
|
ts.itemID = m_itemID;
|
||||||
|
ts.interval = 0;
|
||||||
|
ts.name = name;
|
||||||
|
ts.keyID = keyID;
|
||||||
|
ts.type = type;
|
||||||
|
ts.range = range;
|
||||||
|
ts.arc = arc;
|
||||||
|
ts.host = host;
|
||||||
|
SensorSweep(ts);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LSL_Types.list GetSensorList(uint m_localID, LLUUID m_itemID)
|
||||||
|
{
|
||||||
|
lock (SenseLock)
|
||||||
|
{
|
||||||
|
Dictionary<LLUUID, LSL_Types.list> Obj = null;
|
||||||
|
if (!SenseEvents.TryGetValue(m_localID, out Obj))
|
||||||
|
{
|
||||||
|
m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing localID: " + m_localID);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
lock (Obj)
|
||||||
|
{
|
||||||
|
// Get script
|
||||||
|
LSL_Types.list SenseList = null;
|
||||||
|
if (!Obj.TryGetValue(m_itemID, out SenseList))
|
||||||
|
{
|
||||||
|
m_CmdManager.m_ScriptEngine.Log.Info("[AsyncLSL]: GetSensorList missing itemID: " + m_itemID);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return SenseList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SensorSweep(SenseRepeatClass ts)
|
||||||
|
{
|
||||||
|
//m_ScriptEngine.Log.Info("[AsyncLSL]:Enter SensorSweep");
|
||||||
|
SceneObjectPart SensePoint = ts.host;
|
||||||
|
|
||||||
|
if (SensePoint == null)
|
||||||
|
{
|
||||||
|
//m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep (SensePoint == null) for "+ts.itemID.ToString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep Scan");
|
||||||
|
|
||||||
|
LLVector3 sensorPos = SensePoint.AbsolutePosition;
|
||||||
|
LLVector3 regionPos = new LLVector3(m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocX * Constants.RegionSize, m_CmdManager.m_ScriptEngine.World.RegionInfo.RegionLocY * Constants.RegionSize, 0);
|
||||||
|
LLVector3 fromRegionPos = sensorPos + regionPos;
|
||||||
|
|
||||||
|
LLQuaternion q = SensePoint.RotationOffset;
|
||||||
|
LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W);
|
||||||
|
LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r);
|
||||||
|
double mag_fwd = LSL_Types.Vector3.Mag(forward_dir);
|
||||||
|
|
||||||
|
// Here we should do some smart culling ...
|
||||||
|
// math seems quicker than strings so try that first
|
||||||
|
LSL_Types.list SensedObjects = new LSL_Types.list();
|
||||||
|
LSL_Types.Vector3 ZeroVector = new LSL_Types.Vector3(0, 0, 0);
|
||||||
|
|
||||||
|
foreach (EntityBase ent in m_CmdManager.m_ScriptEngine.World.Entities.Values)
|
||||||
|
{
|
||||||
|
LLVector3 toRegionPos = ent.AbsolutePosition + regionPos;
|
||||||
|
double dis = Math.Abs((double)Util.GetDistanceTo(toRegionPos, fromRegionPos));
|
||||||
|
if (dis <= ts.range)
|
||||||
|
{
|
||||||
|
// In Range, is it the right Type ?
|
||||||
|
int objtype = 0;
|
||||||
|
|
||||||
|
if (m_CmdManager.m_ScriptEngine.World.GetScenePresence(ent.UUID) != null) objtype |= 0x01; // actor
|
||||||
|
if (ent.Velocity.Equals(ZeroVector))
|
||||||
|
objtype |= 0x04; // passive non-moving
|
||||||
|
else
|
||||||
|
objtype |= 0x02; // active moving
|
||||||
|
if (ent is IScript) objtype |= 0x08; // Scripted. It COULD have one hidden ...
|
||||||
|
|
||||||
|
if (((ts.type & objtype) != 0) || ((ts.type & objtype) == ts.type))
|
||||||
|
{
|
||||||
|
// docs claim AGENT|ACTIVE should find agent objects OR active objects
|
||||||
|
// so the bitwise AND with object type should be non-zero
|
||||||
|
|
||||||
|
// Right type too, what about the other params , key and name ?
|
||||||
|
bool keep = true;
|
||||||
|
if (ts.arc < Math.PI)
|
||||||
|
{
|
||||||
|
// not omni-directional. Can you see it ?
|
||||||
|
// vec forward_dir = llRot2Fwd(llGetRot())
|
||||||
|
// vec obj_dir = toRegionPos-fromRegionPos
|
||||||
|
// dot=dot(forward_dir,obj_dir)
|
||||||
|
// mag_fwd = mag(forward_dir)
|
||||||
|
// mag_obj = mag(obj_dir)
|
||||||
|
// ang = acos(dot /(mag_fwd*mag_obj))
|
||||||
|
double ang_obj = 0;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
LLVector3 diff = toRegionPos - fromRegionPos;
|
||||||
|
LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z);
|
||||||
|
double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir);
|
||||||
|
double mag_obj = LSL_Types.Vector3.Mag(obj_dir);
|
||||||
|
ang_obj = Math.Acos(dot / (mag_fwd * mag_obj));
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ang_obj > ts.arc) keep = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keep && (ts.keyID != LLUUID.Zero) && (ts.keyID != ent.UUID))
|
||||||
|
{
|
||||||
|
keep = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keep && (ts.name.Length > 0))
|
||||||
|
{
|
||||||
|
string avatarname=null;
|
||||||
|
string objectname=null;
|
||||||
|
string entname =ent.Name;
|
||||||
|
|
||||||
|
// try avatar username surname
|
||||||
|
UserProfileData profile = m_CmdManager.m_ScriptEngine.World.CommsManager.UserService.GetUserProfile(ent.UUID);
|
||||||
|
if (profile != null)
|
||||||
|
{
|
||||||
|
avatarname = profile.FirstName + " " + profile.SurName;
|
||||||
|
}
|
||||||
|
// try an scene object
|
||||||
|
SceneObjectPart SOP = m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(ent.UUID);
|
||||||
|
if (SOP != null)
|
||||||
|
{
|
||||||
|
objectname = SOP.Name;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ts.name != entname) && (ts.name != avatarname) && (ts.name != objectname))
|
||||||
|
{
|
||||||
|
keep = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keep == true) SensedObjects.Add(ent.UUID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//m_ScriptEngine.Log.Info("[AsyncLSL]: Enter SensorSweep SenseLock");
|
||||||
|
|
||||||
|
lock (SenseLock)
|
||||||
|
{
|
||||||
|
// Create object if it doesn't exist
|
||||||
|
if (SenseEvents.ContainsKey(ts.localID) == false)
|
||||||
|
{
|
||||||
|
SenseEvents.Add(ts.localID, new Dictionary<LLUUID, LSL_Types.list>());
|
||||||
|
}
|
||||||
|
// clear if previous traces exist
|
||||||
|
Dictionary<LLUUID, LSL_Types.list> Obj;
|
||||||
|
SenseEvents.TryGetValue(ts.localID, out Obj);
|
||||||
|
if (Obj.ContainsKey(ts.itemID) == true)
|
||||||
|
Obj.Remove(ts.itemID);
|
||||||
|
|
||||||
|
// note list may be zero length
|
||||||
|
Obj.Add(ts.itemID, SensedObjects);
|
||||||
|
|
||||||
|
if (SensedObjects.Length == 0)
|
||||||
|
{
|
||||||
|
// send a "no_sensor"
|
||||||
|
// Add it to queue
|
||||||
|
m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
|
||||||
|
new XEventParams("no_sensor", new Object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
XDetectParams[] detect =
|
||||||
|
new XDetectParams[SensedObjects.Length];
|
||||||
|
|
||||||
|
int idx;
|
||||||
|
for(idx = 0 ; idx < SensedObjects.Length; idx++)
|
||||||
|
{
|
||||||
|
detect[idx].Key=(LLUUID)(SensedObjects.Data[idx]);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
|
||||||
|
new XEventParams("sensor",
|
||||||
|
new Object[] {
|
||||||
|
new LSL_Types.LSLInteger(SensedObjects.Length) },
|
||||||
|
detect));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] GetSerializationData(LLUUID itemID)
|
||||||
|
{
|
||||||
|
List<Object> data = new List<Object>();
|
||||||
|
|
||||||
|
foreach (SenseRepeatClass ts in SenseRepeaters)
|
||||||
|
{
|
||||||
|
if(ts.itemID == itemID)
|
||||||
|
{
|
||||||
|
data.Add(ts.interval);
|
||||||
|
data.Add(ts.name);
|
||||||
|
data.Add(ts.keyID);
|
||||||
|
data.Add(ts.type);
|
||||||
|
data.Add(ts.range);
|
||||||
|
data.Add(ts.arc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID,
|
||||||
|
Object[] data)
|
||||||
|
{
|
||||||
|
SceneObjectPart part =
|
||||||
|
m_CmdManager.m_ScriptEngine.World.GetSceneObjectPart(
|
||||||
|
objectID);
|
||||||
|
|
||||||
|
if(part == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
int idx=0;
|
||||||
|
|
||||||
|
while(idx < data.Length)
|
||||||
|
{
|
||||||
|
SenseRepeatClass ts = new SenseRepeatClass();
|
||||||
|
|
||||||
|
ts.localID = localID;
|
||||||
|
ts.itemID = itemID;
|
||||||
|
|
||||||
|
ts.interval = (double)data[idx];
|
||||||
|
ts.name = (string)data[idx+1];
|
||||||
|
ts.keyID = (LLUUID)data[idx+2];
|
||||||
|
ts.type = (int)data[idx+3];
|
||||||
|
ts.range = (double)data[idx+4];
|
||||||
|
ts.arc = (double)data[idx+5];
|
||||||
|
ts.host = part;
|
||||||
|
|
||||||
|
ts.next =
|
||||||
|
DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
|
|
||||||
|
SenseRepeaters.Add(ts);
|
||||||
|
idx += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,163 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using libsecondlife;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class Timer
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
public Timer(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// TIMER
|
||||||
|
//
|
||||||
|
private class TimerClass
|
||||||
|
{
|
||||||
|
public uint localID;
|
||||||
|
public LLUUID itemID;
|
||||||
|
//public double interval;
|
||||||
|
public long interval;
|
||||||
|
//public DateTime next;
|
||||||
|
public long next;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<TimerClass> Timers = new List<TimerClass>();
|
||||||
|
private object TimerListLock = new object();
|
||||||
|
|
||||||
|
public void SetTimerEvent(uint m_localID, LLUUID m_itemID, double sec)
|
||||||
|
{
|
||||||
|
Console.WriteLine("SetTimerEvent");
|
||||||
|
|
||||||
|
// Always remove first, in case this is a re-set
|
||||||
|
UnSetTimerEvents(m_localID, m_itemID);
|
||||||
|
if (sec == 0) // Disabling timer
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Add to timer
|
||||||
|
TimerClass ts = new TimerClass();
|
||||||
|
ts.localID = m_localID;
|
||||||
|
ts.itemID = m_itemID;
|
||||||
|
ts.interval = Convert.ToInt64(sec * 10000000); // How many 100 nanoseconds (ticks) should we wait
|
||||||
|
// 2193386136332921 ticks
|
||||||
|
// 219338613 seconds
|
||||||
|
|
||||||
|
//ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
|
ts.next = DateTime.Now.Ticks + ts.interval;
|
||||||
|
lock (TimerListLock)
|
||||||
|
{
|
||||||
|
Timers.Add(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UnSetTimerEvents(uint m_localID, LLUUID m_itemID)
|
||||||
|
{
|
||||||
|
// Remove from timer
|
||||||
|
lock (TimerListLock)
|
||||||
|
{
|
||||||
|
foreach (TimerClass ts in new ArrayList(Timers))
|
||||||
|
{
|
||||||
|
if (ts.localID == m_localID && ts.itemID == m_itemID)
|
||||||
|
Timers.Remove(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckTimerEvents()
|
||||||
|
{
|
||||||
|
// Nothing to do here?
|
||||||
|
if (Timers.Count == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
lock (TimerListLock)
|
||||||
|
{
|
||||||
|
// Go through all timers
|
||||||
|
foreach (TimerClass ts in Timers)
|
||||||
|
{
|
||||||
|
// Time has passed?
|
||||||
|
if (ts.next < DateTime.Now.Ticks)
|
||||||
|
{
|
||||||
|
// Console.WriteLine("Time has passed: Now: " + DateTime.Now.Ticks + ", Passed: " + ts.next);
|
||||||
|
// Add it to queue
|
||||||
|
m_CmdManager.m_ScriptEngine.PostScriptEvent(ts.itemID,
|
||||||
|
new XEventParams("timer", new Object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
// set next interval
|
||||||
|
|
||||||
|
//ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval);
|
||||||
|
ts.next = DateTime.Now.Ticks + ts.interval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object[] GetSerializationData(LLUUID itemID)
|
||||||
|
{
|
||||||
|
List<Object> data = new List<Object>();
|
||||||
|
|
||||||
|
lock (TimerListLock)
|
||||||
|
{
|
||||||
|
foreach (TimerClass ts in Timers)
|
||||||
|
{
|
||||||
|
if(ts.itemID == itemID)
|
||||||
|
{
|
||||||
|
data.Add(ts.interval);
|
||||||
|
data.Add(ts.next-DateTime.Now.Ticks);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return data.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CreateFromData(uint localID, LLUUID itemID, LLUUID objectID,
|
||||||
|
Object[] data)
|
||||||
|
{
|
||||||
|
int idx=0;
|
||||||
|
|
||||||
|
while(idx < data.Length)
|
||||||
|
{
|
||||||
|
TimerClass ts = new TimerClass();
|
||||||
|
|
||||||
|
ts.localID = localID;
|
||||||
|
ts.itemID = itemID;
|
||||||
|
ts.interval = (long)data[idx];
|
||||||
|
ts.next = DateTime.Now.Ticks + (long)data[idx+1];
|
||||||
|
idx += 2;
|
||||||
|
|
||||||
|
Timers.Add(ts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,115 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.Environment.Modules.Scripting.XMLRPC;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.AsyncCommandPlugins
|
||||||
|
{
|
||||||
|
public class XmlRequest
|
||||||
|
{
|
||||||
|
public AsyncCommandManager m_CmdManager;
|
||||||
|
|
||||||
|
public XmlRequest(AsyncCommandManager CmdManager)
|
||||||
|
{
|
||||||
|
m_CmdManager = CmdManager;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void CheckXMLRPCRequests()
|
||||||
|
{
|
||||||
|
if (m_CmdManager.m_ScriptEngine.World == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
IXMLRPC xmlrpc = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface<IXMLRPC>();
|
||||||
|
|
||||||
|
if (xmlrpc != null)
|
||||||
|
{
|
||||||
|
RPCRequestInfo rInfo = xmlrpc.GetNextCompletedRequest();
|
||||||
|
|
||||||
|
while (rInfo != null)
|
||||||
|
{
|
||||||
|
xmlrpc.RemoveCompletedRequest(rInfo.GetMessageID());
|
||||||
|
|
||||||
|
//Deliver data to prim's remote_data handler
|
||||||
|
object[] resobj = new object[]
|
||||||
|
{
|
||||||
|
new LSL_Types.LSLInteger(2),
|
||||||
|
new LSL_Types.LSLString(
|
||||||
|
rInfo.GetChannelKey().ToString()),
|
||||||
|
new LSL_Types.LSLString(
|
||||||
|
rInfo.GetMessageID().ToString()),
|
||||||
|
new LSL_Types.LSLString(String.Empty),
|
||||||
|
new LSL_Types.LSLInteger(rInfo.GetIntValue()),
|
||||||
|
new LSL_Types.LSLString(rInfo.GetStrVal())
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (XEngine xe in XEngine.ScriptEngines)
|
||||||
|
{
|
||||||
|
if(xe.PostScriptEvent(
|
||||||
|
rInfo.GetItemID(), new XEventParams(
|
||||||
|
"remote_data", resobj,
|
||||||
|
new XDetectParams[0])))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
rInfo = xmlrpc.GetNextCompletedRequest();
|
||||||
|
}
|
||||||
|
|
||||||
|
SendRemoteDataRequest srdInfo = xmlrpc.GetNextCompletedSRDRequest();
|
||||||
|
|
||||||
|
while (srdInfo != null)
|
||||||
|
{
|
||||||
|
xmlrpc.RemoveCompletedSRDRequest(srdInfo.GetReqID());
|
||||||
|
|
||||||
|
//Deliver data to prim's remote_data handler
|
||||||
|
object[] resobj = new object[]
|
||||||
|
{
|
||||||
|
new LSL_Types.LSLInteger(3),
|
||||||
|
new LSL_Types.LSLString(srdInfo.channel.ToString()),
|
||||||
|
new LSL_Types.LSLString(srdInfo.GetReqID().ToString()),
|
||||||
|
new LSL_Types.LSLString(String.Empty),
|
||||||
|
new LSL_Types.LSLInteger(srdInfo.idata),
|
||||||
|
new LSL_Types.LSLString(srdInfo.sdata)
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (XEngine xe in XEngine.ScriptEngines)
|
||||||
|
{
|
||||||
|
if(xe.PostScriptEvent(
|
||||||
|
srdInfo.m_itemID, new XEventParams(
|
||||||
|
"remote_data", resobj,
|
||||||
|
new XDetectParams[0])))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
srdInfo = xmlrpc.GetNextCompletedSRDRequest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,515 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.CodeDom.Compiler;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using Microsoft.CSharp;
|
||||||
|
using Microsoft.JScript;
|
||||||
|
using Microsoft.VisualBasic;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
public class Compiler
|
||||||
|
{
|
||||||
|
private static readonly log4net.ILog m_log
|
||||||
|
= log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
// * Uses "LSL2Converter" to convert LSL to C# if necessary.
|
||||||
|
// * Compiles C#-code into an assembly
|
||||||
|
// * Returns assembly name ready for AppDomain load.
|
||||||
|
//
|
||||||
|
// Assembly is compiled using LSL_BaseClass as base. Look at debug C# code file created when LSL script is compiled for full details.
|
||||||
|
//
|
||||||
|
|
||||||
|
internal enum enumCompileType
|
||||||
|
{
|
||||||
|
lsl = 0,
|
||||||
|
cs = 1,
|
||||||
|
vb = 2,
|
||||||
|
js = 3
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This contains number of lines WE use for header when compiling script. User will get error in line x-LinesToRemoveOnError when error occurs.
|
||||||
|
/// </summary>
|
||||||
|
public int LinesToRemoveOnError = 3;
|
||||||
|
private enumCompileType DefaultCompileLanguage;
|
||||||
|
private bool WriteScriptSourceToDebugFile;
|
||||||
|
private bool CompileWithDebugInformation;
|
||||||
|
private Dictionary<string, bool> AllowedCompilers = new Dictionary<string, bool>(StringComparer.CurrentCultureIgnoreCase);
|
||||||
|
private Dictionary<string, enumCompileType> LanguageMapping = new Dictionary<string, enumCompileType>(StringComparer.CurrentCultureIgnoreCase);
|
||||||
|
|
||||||
|
private string FilePrefix;
|
||||||
|
private string ScriptEnginesPath = "ScriptEngines";
|
||||||
|
|
||||||
|
private static LSL2CSConverter LSL_Converter = new LSL2CSConverter();
|
||||||
|
private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
|
||||||
|
private static VBCodeProvider VBcodeProvider = new VBCodeProvider();
|
||||||
|
private static JScriptCodeProvider JScodeProvider = new JScriptCodeProvider();
|
||||||
|
|
||||||
|
private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files
|
||||||
|
private static UInt64 scriptCompileCounter = 0; // And a counter
|
||||||
|
|
||||||
|
public XEngine m_scriptEngine;
|
||||||
|
public Compiler(XEngine scriptEngine)
|
||||||
|
{
|
||||||
|
m_scriptEngine = scriptEngine;
|
||||||
|
ReadConfig();
|
||||||
|
}
|
||||||
|
public bool in_startup = true;
|
||||||
|
public void ReadConfig()
|
||||||
|
{
|
||||||
|
|
||||||
|
// Get some config
|
||||||
|
WriteScriptSourceToDebugFile = m_scriptEngine.ScriptConfigSource.GetBoolean("WriteScriptSourceToDebugFile", true);
|
||||||
|
CompileWithDebugInformation = m_scriptEngine.ScriptConfigSource.GetBoolean("CompileWithDebugInformation", true);
|
||||||
|
|
||||||
|
// Get file prefix from scriptengine name and make it file system safe:
|
||||||
|
FilePrefix = m_scriptEngine.ScriptEngineName;
|
||||||
|
foreach (char c in Path.GetInvalidFileNameChars())
|
||||||
|
{
|
||||||
|
FilePrefix = FilePrefix.Replace(c, '_');
|
||||||
|
}
|
||||||
|
|
||||||
|
// First time we start? Delete old files
|
||||||
|
if (in_startup)
|
||||||
|
{
|
||||||
|
in_startup = false;
|
||||||
|
DeleteOldFiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Map name and enum type of our supported languages
|
||||||
|
LanguageMapping.Add(enumCompileType.cs.ToString(), enumCompileType.cs);
|
||||||
|
LanguageMapping.Add(enumCompileType.vb.ToString(), enumCompileType.vb);
|
||||||
|
LanguageMapping.Add(enumCompileType.lsl.ToString(), enumCompileType.lsl);
|
||||||
|
LanguageMapping.Add(enumCompileType.js.ToString(), enumCompileType.js);
|
||||||
|
|
||||||
|
// Allowed compilers
|
||||||
|
string allowComp = m_scriptEngine.ScriptConfigSource.GetString("AllowedCompilers", "lsl,cs,vb,js");
|
||||||
|
AllowedCompilers.Clear();
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Allowed languages: " + allowComp);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
foreach (string strl in allowComp.Split(','))
|
||||||
|
{
|
||||||
|
string strlan = strl.Trim(" \t".ToCharArray()).ToLower();
|
||||||
|
if (!LanguageMapping.ContainsKey(strlan))
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler is unable to recognize language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
//m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Config OK. Compiler recognized language type \"" + strlan + "\" specified in \"AllowedCompilers\".");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
AllowedCompilers.Add(strlan, true);
|
||||||
|
}
|
||||||
|
if (AllowedCompilers.Count == 0)
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Config error. Compiler could not recognize any language in \"AllowedCompilers\". Scripts will not be executed!");
|
||||||
|
|
||||||
|
// Default language
|
||||||
|
string defaultCompileLanguage = m_scriptEngine.ScriptConfigSource.GetString("DefaultCompileLanguage", "lsl").ToLower();
|
||||||
|
|
||||||
|
// Is this language recognized at all?
|
||||||
|
if (!LanguageMapping.ContainsKey(defaultCompileLanguage))
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
|
||||||
|
"Config error. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is not recognized as a valid language. Changing default to: \"lsl\".");
|
||||||
|
defaultCompileLanguage = "lsl";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is this language in allow-list?
|
||||||
|
if (!AllowedCompilers.ContainsKey(defaultCompileLanguage))
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: " +
|
||||||
|
"Config error. Default language \"" + defaultCompileLanguage + "\"specified in \"DefaultCompileLanguage\" is not in list of \"AllowedCompilers\". Scripts may not be executed!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#if DEBUG
|
||||||
|
// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: " +
|
||||||
|
// "Config OK. Default language \"" + defaultCompileLanguage + "\" specified in \"DefaultCompileLanguage\" is recognized as a valid language.");
|
||||||
|
#endif
|
||||||
|
// LANGUAGE IS IN ALLOW-LIST
|
||||||
|
DefaultCompileLanguage = LanguageMapping[defaultCompileLanguage];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We now have an allow-list, a mapping list, and a default language
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete old script files
|
||||||
|
/// </summary>
|
||||||
|
private void DeleteOldFiles()
|
||||||
|
{
|
||||||
|
|
||||||
|
// CREATE FOLDER IF IT DOESNT EXIST
|
||||||
|
if (!Directory.Exists(ScriptEnginesPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ScriptEnginesPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + ScriptEnginesPath + "\": " + ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString())))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.Combine(ScriptEnginesPath,
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString()));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying to create ScriptEngine directory \"" + Path.Combine(ScriptEnginesPath,
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString())+ "\": " + ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (string file in Directory.GetFiles(Path.Combine(ScriptEnginesPath,
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString())))
|
||||||
|
{
|
||||||
|
//m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: FILE FOUND: " + file);
|
||||||
|
|
||||||
|
if (file.ToLower().StartsWith(FilePrefix + "_compiled_") ||
|
||||||
|
file.ToLower().StartsWith(FilePrefix + "_source_"))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(file);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception trying delete old script file \"" + file + "\": " + ex.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
////private ICodeCompiler icc = codeProvider.CreateCompiler();
|
||||||
|
//public string CompileFromFile(string LSOFileName)
|
||||||
|
//{
|
||||||
|
// switch (Path.GetExtension(LSOFileName).ToLower())
|
||||||
|
// {
|
||||||
|
// case ".txt":
|
||||||
|
// case ".lsl":
|
||||||
|
// Common.ScriptEngineBase.Common.SendToDebug("Source code is LSL, converting to CS");
|
||||||
|
// return CompileFromLSLText(File.ReadAllText(LSOFileName));
|
||||||
|
// case ".cs":
|
||||||
|
// Common.ScriptEngineBase.Common.SendToDebug("Source code is CS");
|
||||||
|
// return CompileFromCSText(File.ReadAllText(LSOFileName));
|
||||||
|
// default:
|
||||||
|
// throw new Exception("Unknown script type.");
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts script from LSL to CS and calls CompileFromCSText
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Script">LSL script</param>
|
||||||
|
/// <returns>Filename to .dll assembly</returns>
|
||||||
|
public string PerformScriptCompile(string Script, string asset)
|
||||||
|
{
|
||||||
|
string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString(),
|
||||||
|
FilePrefix + "_compiled_" + asset + ".dll"));
|
||||||
|
// string OutFile = Path.Combine(ScriptEnginesPath,
|
||||||
|
// FilePrefix + "_compiled_" + asset + ".dll");
|
||||||
|
|
||||||
|
if(File.Exists(OutFile))
|
||||||
|
return OutFile;
|
||||||
|
|
||||||
|
if (!Directory.Exists(ScriptEnginesPath))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ScriptEnginesPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Directory.Exists(Path.Combine(ScriptEnginesPath,
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString())))
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(ScriptEnginesPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enumCompileType l = DefaultCompileLanguage;
|
||||||
|
|
||||||
|
|
||||||
|
if (Script.StartsWith("//c#", true, CultureInfo.InvariantCulture))
|
||||||
|
l = enumCompileType.cs;
|
||||||
|
if (Script.StartsWith("//vb", true, CultureInfo.InvariantCulture))
|
||||||
|
{
|
||||||
|
l = enumCompileType.vb;
|
||||||
|
// We need to remove //vb, it won't compile with that
|
||||||
|
|
||||||
|
Script = Script.Substring(4, Script.Length - 4);
|
||||||
|
}
|
||||||
|
if (Script.StartsWith("//lsl", true, CultureInfo.InvariantCulture))
|
||||||
|
l = enumCompileType.lsl;
|
||||||
|
|
||||||
|
if (Script.StartsWith("//js", true, CultureInfo.InvariantCulture))
|
||||||
|
l = enumCompileType.js;
|
||||||
|
|
||||||
|
if (!AllowedCompilers.ContainsKey(l.ToString()))
|
||||||
|
{
|
||||||
|
// Not allowed to compile to this language!
|
||||||
|
string errtext = String.Empty;
|
||||||
|
errtext += "The compiler for language \"" + l.ToString() + "\" is not in list of allowed compilers. Script will not be executed!";
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
|
||||||
|
string compileScript = Script;
|
||||||
|
|
||||||
|
if (l == enumCompileType.lsl)
|
||||||
|
{
|
||||||
|
// Its LSL, convert it to C#
|
||||||
|
compileScript = LSL_Converter.Convert(Script);
|
||||||
|
l = enumCompileType.cs;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Insert additional assemblies here
|
||||||
|
|
||||||
|
//ADAM: Disabled for the moment until it's working right.
|
||||||
|
bool enableCommanderLSL = false;
|
||||||
|
|
||||||
|
if (enableCommanderLSL == true && l == enumCompileType.cs)
|
||||||
|
{
|
||||||
|
foreach (KeyValuePair<string,
|
||||||
|
ICommander> com
|
||||||
|
in m_scriptEngine.World.GetCommanders())
|
||||||
|
{
|
||||||
|
compileScript = com.Value.GenerateRuntimeAPI() + compileScript;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// End of insert
|
||||||
|
|
||||||
|
|
||||||
|
switch (l)
|
||||||
|
{
|
||||||
|
case enumCompileType.cs:
|
||||||
|
compileScript = CreateCSCompilerScript(compileScript);
|
||||||
|
break;
|
||||||
|
case enumCompileType.vb:
|
||||||
|
compileScript = CreateVBCompilerScript(compileScript);
|
||||||
|
break;
|
||||||
|
case enumCompileType.js:
|
||||||
|
compileScript = CreateJSCompilerScript(compileScript);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// m_log.Debug("[ScriptEngine.DotNetEngine]: Preparing to compile the following LSL to C# translated code");
|
||||||
|
// m_log.Debug("");
|
||||||
|
// m_log.Debug(compileScript);
|
||||||
|
|
||||||
|
return CompileFromDotNetText(compileScript, l, asset);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateJSCompilerScript(string compileScript)
|
||||||
|
{
|
||||||
|
compileScript = String.Empty +
|
||||||
|
"import OpenSim.Region.ScriptEngine.XEngine.Script; import System.Collections.Generic;\r\n" +
|
||||||
|
"package SecondLife {\r\n" +
|
||||||
|
"class Script extends OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" +
|
||||||
|
compileScript +
|
||||||
|
"} }\r\n";
|
||||||
|
return compileScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateCSCompilerScript(string compileScript)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
compileScript = String.Empty +
|
||||||
|
"using OpenSim.Region.ScriptEngine.XEngine.Script; using System.Collections.Generic;\r\n" +
|
||||||
|
String.Empty + "namespace SecondLife { " +
|
||||||
|
String.Empty + "public class Script : OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass { \r\n" +
|
||||||
|
@"public Script() { } " +
|
||||||
|
compileScript +
|
||||||
|
"} }\r\n";
|
||||||
|
return compileScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string CreateVBCompilerScript(string compileScript)
|
||||||
|
{
|
||||||
|
compileScript = String.Empty +
|
||||||
|
"Imports OpenSim.Region.ScriptEngine.XEngine.Script: Imports System.Collections.Generic: " +
|
||||||
|
String.Empty + "NameSpace SecondLife:" +
|
||||||
|
String.Empty + "Public Class Script: Inherits OpenSim.Region.ScriptEngine.XEngine.Script.BuiltIn_Commands_BaseClass: " +
|
||||||
|
"\r\nPublic Sub New()\r\nEnd Sub: " +
|
||||||
|
compileScript +
|
||||||
|
":End Class :End Namespace\r\n";
|
||||||
|
return compileScript;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compile .NET script to .Net assembly (.dll)
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Script">CS script</param>
|
||||||
|
/// <returns>Filename to .dll assembly</returns>
|
||||||
|
internal string CompileFromDotNetText(string Script, enumCompileType lang, string asset)
|
||||||
|
{
|
||||||
|
string ext = "." + lang.ToString();
|
||||||
|
|
||||||
|
// Output assembly name
|
||||||
|
scriptCompileCounter++;
|
||||||
|
string OutFile = Path.Combine(ScriptEnginesPath, Path.Combine(
|
||||||
|
m_scriptEngine.World.RegionInfo.RegionID.ToString(),
|
||||||
|
FilePrefix + "_compiled_" + asset + ".dll"));
|
||||||
|
#if DEBUG
|
||||||
|
// m_scriptEngine.Log.Debug("[" + m_scriptEngine.ScriptEngineName + "]: Starting compile of \"" + OutFile + "\".");
|
||||||
|
#endif
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.Delete(OutFile);
|
||||||
|
}
|
||||||
|
catch (Exception e) // NOTLEGIT - Should be just catching FileIOException
|
||||||
|
{
|
||||||
|
//m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
|
||||||
|
throw new Exception("Unable to delete old existring script-file before writing new. Compile aborted: " + e.ToString());
|
||||||
|
}
|
||||||
|
//string OutFile = Path.Combine("ScriptEngines", "SecondLife.Script.dll");
|
||||||
|
|
||||||
|
// DEBUG - write source to disk
|
||||||
|
if (WriteScriptSourceToDebugFile)
|
||||||
|
{
|
||||||
|
string srcFileName = FilePrefix + "_source_" + Path.GetFileNameWithoutExtension(OutFile) + ext;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
File.WriteAllText(
|
||||||
|
Path.Combine("ScriptEngines", srcFileName),
|
||||||
|
Script);
|
||||||
|
}
|
||||||
|
catch (Exception ex) // NOTLEGIT - Should be just catching FileIOException
|
||||||
|
{
|
||||||
|
m_scriptEngine.Log.Error("[" + m_scriptEngine.ScriptEngineName + "]: Exception while trying to write script source to file \"" + srcFileName + "\": " + ex.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do actual compile
|
||||||
|
CompilerParameters parameters = new CompilerParameters();
|
||||||
|
|
||||||
|
parameters.IncludeDebugInformation = true;
|
||||||
|
|
||||||
|
// Add all available assemblies
|
||||||
|
// foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies())
|
||||||
|
// {
|
||||||
|
// Console.WriteLine("Adding assembly: " + asm.Location);
|
||||||
|
// parameters.ReferencedAssemblies.Add(asm.Location);
|
||||||
|
// }
|
||||||
|
|
||||||
|
string rootPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
|
||||||
|
string rootPathSE = Path.GetDirectoryName(GetType().Assembly.Location);
|
||||||
|
//Console.WriteLine("Assembly location: " + rootPath);
|
||||||
|
parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.XEngine.Script.dll"));
|
||||||
|
// parameters.ReferencedAssemblies.Add(Path.Combine(rootPathSE, "OpenSim.Region.ScriptEngine.XEngine.dll"));
|
||||||
|
|
||||||
|
//parameters.ReferencedAssemblies.Add("OpenSim.Region.Environment");
|
||||||
|
parameters.GenerateExecutable = false;
|
||||||
|
parameters.OutputAssembly = OutFile;
|
||||||
|
parameters.IncludeDebugInformation = CompileWithDebugInformation;
|
||||||
|
//parameters.WarningLevel = 1; // Should be 4?
|
||||||
|
parameters.TreatWarningsAsErrors = false;
|
||||||
|
|
||||||
|
//Console.WriteLine(Script);
|
||||||
|
CompilerResults results;
|
||||||
|
switch (lang)
|
||||||
|
{
|
||||||
|
case enumCompileType.vb:
|
||||||
|
results = VBcodeProvider.CompileAssemblyFromSource(parameters, Script);
|
||||||
|
break;
|
||||||
|
case enumCompileType.cs:
|
||||||
|
results = CScodeProvider.CompileAssemblyFromSource(parameters, Script);
|
||||||
|
break;
|
||||||
|
case enumCompileType.js:
|
||||||
|
results = JScodeProvider.CompileAssemblyFromSource(parameters, Script);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new Exception("Compiler is not able to recongnize language type \"" + lang.ToString() + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check result
|
||||||
|
// Go through errors
|
||||||
|
|
||||||
|
//
|
||||||
|
// WARNINGS AND ERRORS
|
||||||
|
//
|
||||||
|
if (results.Errors.Count > 0)
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
foreach (CompilerError CompErr in results.Errors)
|
||||||
|
{
|
||||||
|
errtext += "Line number " + (CompErr.Line - LinesToRemoveOnError) +
|
||||||
|
", Error Number: " + CompErr.ErrorNumber +
|
||||||
|
", '" + CompErr.ErrorText + "'\r\n";
|
||||||
|
}
|
||||||
|
if (!File.Exists(OutFile))
|
||||||
|
{
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// NO ERRORS, BUT NO COMPILED FILE
|
||||||
|
//
|
||||||
|
if (!File.Exists(OutFile))
|
||||||
|
{
|
||||||
|
string errtext = String.Empty;
|
||||||
|
errtext += "No compile error. But not able to locate compiled file.";
|
||||||
|
throw new Exception(errtext);
|
||||||
|
}
|
||||||
|
return OutFile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,293 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using libsecondlife;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Region.Environment.Modules.Avatar.Currency.SampleMoney;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
using Axiom.Math;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Prepares events so they can be directly executed upon a script by EventQueueManager, then queues it.
|
||||||
|
/// </summary>
|
||||||
|
public class EventManager
|
||||||
|
{
|
||||||
|
private XEngine myScriptEngine;
|
||||||
|
|
||||||
|
public EventManager(XEngine _ScriptEngine)
|
||||||
|
{
|
||||||
|
myScriptEngine = _ScriptEngine;
|
||||||
|
|
||||||
|
myScriptEngine.Log.Info("[XEngine] Hooking up to server events");
|
||||||
|
myScriptEngine.World.EventManager.OnObjectGrab += touch_start;
|
||||||
|
myScriptEngine.World.EventManager.OnObjectDeGrab += touch_end;
|
||||||
|
myScriptEngine.World.EventManager.OnScriptChangedEvent += changed;
|
||||||
|
myScriptEngine.World.EventManager.OnScriptAtTargetEvent += at_target;
|
||||||
|
myScriptEngine.World.EventManager.OnScriptNotAtTargetEvent += not_at_target;
|
||||||
|
myScriptEngine.World.EventManager.OnScriptControlEvent += control;
|
||||||
|
IMoneyModule money=myScriptEngine.World.RequestModuleInterface<IMoneyModule>();
|
||||||
|
if (money != null)
|
||||||
|
{
|
||||||
|
money.OnObjectPaid+=HandleObjectPaid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleObjectPaid(LLUUID objectID, LLUUID agentID,
|
||||||
|
int amount)
|
||||||
|
{
|
||||||
|
SceneObjectPart part =
|
||||||
|
myScriptEngine.World.GetSceneObjectPart(objectID);
|
||||||
|
|
||||||
|
if (part != null)
|
||||||
|
{
|
||||||
|
money(part.LocalId, agentID, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void touch_start(uint localID, LLVector3 offsetPos,
|
||||||
|
IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"touch_start", new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void touch(uint localID, LLVector3 offsetPos,
|
||||||
|
IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X,
|
||||||
|
offsetPos.Y,
|
||||||
|
offsetPos.Z);
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"touch", new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void touch_end(uint localID, IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"touch_end", new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changed(uint localID, uint change)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in localID, Object pass change.
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"changed",new object[] { new LSL_Types.LSLInteger(change) },
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// state_entry: not processed here
|
||||||
|
// state_exit: not processed here
|
||||||
|
|
||||||
|
public void money(uint localID, LLUUID agentID, int amount)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"money", new object[] {
|
||||||
|
new LSL_Types.LSLString(agentID.ToString()),
|
||||||
|
new LSL_Types.LSLInteger(amount) },
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collision_start(uint localID, LLUUID itemID,
|
||||||
|
IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"collision_start",
|
||||||
|
new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collision(uint localID, LLUUID itemID,
|
||||||
|
IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"collision", new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void collision_end(uint localID, LLUUID itemID,
|
||||||
|
IClientAPI remoteClient)
|
||||||
|
{
|
||||||
|
// Add to queue for all scripts in ObjectID object
|
||||||
|
XDetectParams[] det = new XDetectParams[1];
|
||||||
|
det[0].Key = remoteClient.AgentId;
|
||||||
|
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"collision_end",
|
||||||
|
new Object[] { new LSL_Types.LSLInteger(1) },
|
||||||
|
det));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void land_collision_start(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"land_collision_start",
|
||||||
|
new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void land_collision(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"land_collision",
|
||||||
|
new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void land_collision_end(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"land_collision_end",
|
||||||
|
new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// timer: not handled here
|
||||||
|
// listen: not handled here
|
||||||
|
|
||||||
|
public void on_rez(uint localID, LLUUID itemID, int startParam)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"on_rez",new object[] {
|
||||||
|
new LSL_Types.LSLInteger(startParam)},
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void control(uint localID, LLUUID itemID, LLUUID agentID, uint held, uint change)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"control",new object[] {
|
||||||
|
new LSL_Types.LSLString(agentID.ToString()),
|
||||||
|
new LSL_Types.LSLInteger(held),
|
||||||
|
new LSL_Types.LSLInteger(change)},
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void email(uint localID, LLUUID itemID, string timeSent,
|
||||||
|
string address, string subject, string message, int numLeft)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"email",new object[] {
|
||||||
|
new LSL_Types.LSLString(timeSent),
|
||||||
|
new LSL_Types.LSLString(address),
|
||||||
|
new LSL_Types.LSLString(subject),
|
||||||
|
new LSL_Types.LSLString(message),
|
||||||
|
new LSL_Types.LSLInteger(numLeft)},
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void at_target(uint localID, uint handle, LLVector3 targetpos,
|
||||||
|
LLVector3 atpos)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"at_target", new object[] {
|
||||||
|
new LSL_Types.LSLInteger(handle),
|
||||||
|
new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z),
|
||||||
|
new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) },
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void not_at_target(uint localID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"not_at_target",new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void at_rot_target(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"at_rot_target",new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void not_at_rot_target(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"not_at_rot_target",new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// run_time_permissions: not handled here
|
||||||
|
|
||||||
|
public void attach(uint localID, LLUUID itemID, LLUUID avatar)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"attach",new object[] {
|
||||||
|
new LSL_Types.LSLString(avatar.ToString()) },
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// dataserver: not handled here
|
||||||
|
// link_message: not handled here
|
||||||
|
|
||||||
|
public void moving_start(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"moving_start",new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void moving_end(uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
myScriptEngine.PostObjectEvent(localID, new XEventParams(
|
||||||
|
"moving_end",new object[0],
|
||||||
|
new XDetectParams[0]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// object_rez: not handled here
|
||||||
|
// remote_data: not handled here
|
||||||
|
// http_response: not handled here
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,136 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Reflection;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
public class Executor : ExecutorBase
|
||||||
|
{
|
||||||
|
// Cache functions by keeping a reference to them in a dictionary
|
||||||
|
private Dictionary<string, MethodInfo> Events = new Dictionary<string, MethodInfo>();
|
||||||
|
private Dictionary<string, scriptEvents> m_stateEvents = new Dictionary<string, scriptEvents>();
|
||||||
|
|
||||||
|
public Executor(IScript script) : base(script)
|
||||||
|
{
|
||||||
|
initEventFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected override scriptEvents DoGetStateEventFlags()
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Get event flags for " + m_Script.State);
|
||||||
|
|
||||||
|
// Check to see if we've already computed the flags for this state
|
||||||
|
scriptEvents eventFlags = scriptEvents.None;
|
||||||
|
if (m_stateEvents.ContainsKey(m_Script.State))
|
||||||
|
{
|
||||||
|
m_stateEvents.TryGetValue(m_Script.State, out eventFlags);
|
||||||
|
return eventFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type type=m_Script.GetType();
|
||||||
|
|
||||||
|
// Fill in the events for this state, cache the results in the map
|
||||||
|
foreach (KeyValuePair<string, scriptEvents> kvp in m_eventFlagsMap)
|
||||||
|
{
|
||||||
|
string evname = m_Script.State + "_event_" + kvp.Key;
|
||||||
|
//Console.WriteLine("Trying event "+evname);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MethodInfo mi = type.GetMethod(evname);
|
||||||
|
if (mi != null)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Found handler for " + kvp.Key);
|
||||||
|
eventFlags |= kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Exeption in GetMethod:\n"+e.ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the flags we just computed and return the result
|
||||||
|
if(eventFlags != 0)
|
||||||
|
m_stateEvents.Add(m_Script.State, eventFlags);
|
||||||
|
|
||||||
|
//Console.WriteLine("Returning {0:x}", eventFlags);
|
||||||
|
return (eventFlags);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void DoExecuteEvent(string FunctionName, object[] args)
|
||||||
|
{
|
||||||
|
// IMPORTANT: Types and MemberInfo-derived objects require a LOT of memory.
|
||||||
|
// Instead use RuntimeTypeHandle, RuntimeFieldHandle and RunTimeHandle (IntPtr) instead!
|
||||||
|
|
||||||
|
string EventName = m_Script.State + "_event_" + FunctionName;
|
||||||
|
|
||||||
|
//#if DEBUG
|
||||||
|
// Console.WriteLine("ScriptEngine: Script event function name: " + EventName);
|
||||||
|
//#endif
|
||||||
|
|
||||||
|
if (Events.ContainsKey(EventName) == false)
|
||||||
|
{
|
||||||
|
// Not found, create
|
||||||
|
Type type = m_Script.GetType();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
MethodInfo mi = type.GetMethod(EventName);
|
||||||
|
Events.Add(EventName, mi);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
Console.WriteLine("Event {0}not found", EventName);
|
||||||
|
// Event name not found, cache it as not found
|
||||||
|
Events.Add(EventName, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get event
|
||||||
|
MethodInfo ev = null;
|
||||||
|
Events.TryGetValue(EventName, out ev);
|
||||||
|
|
||||||
|
if (ev == null) // No event by that name!
|
||||||
|
{
|
||||||
|
//Console.WriteLine("ScriptEngine Can not find any event named: \String.Empty + EventName + "\String.Empty);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//cfk 2-7-08 dont need this right now and the default Linux build has DEBUG defined
|
||||||
|
#if DEBUG
|
||||||
|
//Console.WriteLine("ScriptEngine: Executing function name: " + EventName);
|
||||||
|
#endif
|
||||||
|
// Found
|
||||||
|
ev.Invoke(m_Script, args);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,181 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Remoting.Lifetime;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
public abstract class ExecutorBase : MarshalByRefObject
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the script to execute functions in.
|
||||||
|
/// </summary>
|
||||||
|
protected IScript m_Script;
|
||||||
|
|
||||||
|
protected Dictionary<string, scriptEvents> m_eventFlagsMap = new Dictionary<string, scriptEvents>();
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum scriptEvents : int
|
||||||
|
{
|
||||||
|
None = 0,
|
||||||
|
attach = 1,
|
||||||
|
collision = 15,
|
||||||
|
collision_end = 32,
|
||||||
|
collision_start = 64,
|
||||||
|
control = 128,
|
||||||
|
dataserver = 256,
|
||||||
|
email = 512,
|
||||||
|
http_response = 1024,
|
||||||
|
land_collision = 2048,
|
||||||
|
land_collision_end = 4096,
|
||||||
|
land_collision_start = 8192,
|
||||||
|
at_target = 16384,
|
||||||
|
listen = 32768,
|
||||||
|
money = 65536,
|
||||||
|
moving_end = 131072,
|
||||||
|
moving_start = 262144,
|
||||||
|
not_at_rot_target = 524288,
|
||||||
|
not_at_target = 1048576,
|
||||||
|
remote_data = 8388608,
|
||||||
|
run_time_permissions = 268435456,
|
||||||
|
state_entry = 1073741824,
|
||||||
|
state_exit = 2,
|
||||||
|
timer = 4,
|
||||||
|
touch = 8,
|
||||||
|
touch_end = 536870912,
|
||||||
|
touch_start = 2097152,
|
||||||
|
object_rez = 4194304
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new instance of ExecutorBase
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="Script"></param>
|
||||||
|
public ExecutorBase(IScript Script)
|
||||||
|
{
|
||||||
|
m_Script = Script;
|
||||||
|
initEventFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Make sure our object does not timeout when in AppDomain. (Called by ILease base class)
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public override Object InitializeLifetimeService()
|
||||||
|
{
|
||||||
|
//Console.WriteLine("Executor: InitializeLifetimeService()");
|
||||||
|
// return null;
|
||||||
|
ILease lease = (ILease)base.InitializeLifetimeService();
|
||||||
|
|
||||||
|
if (lease.CurrentState == LeaseState.Initial)
|
||||||
|
{
|
||||||
|
lease.InitialLeaseTime = TimeSpan.Zero; // TimeSpan.FromMinutes(1);
|
||||||
|
// lease.SponsorshipTimeout = TimeSpan.FromMinutes(2);
|
||||||
|
// lease.RenewOnCallTime = TimeSpan.FromSeconds(2);
|
||||||
|
}
|
||||||
|
return lease;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get current AppDomain
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Current AppDomain</returns>
|
||||||
|
public AppDomain GetAppDomain()
|
||||||
|
{
|
||||||
|
return AppDomain.CurrentDomain;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Execute a specific function/event in script.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="FunctionName">Name of function to execute</param>
|
||||||
|
/// <param name="args">Arguments to pass to function</param>
|
||||||
|
public void ExecuteEvent(string FunctionName, object[] args)
|
||||||
|
{
|
||||||
|
DoExecuteEvent(FunctionName, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract void DoExecuteEvent(string FunctionName, object[] args);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Compute the events handled by the current state of the script
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>state mask</returns>
|
||||||
|
public scriptEvents GetStateEventFlags()
|
||||||
|
{
|
||||||
|
return DoGetStateEventFlags();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract scriptEvents DoGetStateEventFlags();
|
||||||
|
|
||||||
|
protected void initEventFlags()
|
||||||
|
{
|
||||||
|
// Initialize the table if it hasn't already been done
|
||||||
|
if (m_eventFlagsMap.Count > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_eventFlagsMap.Add("attach", scriptEvents.attach);
|
||||||
|
// m_eventFlagsMap.Add("at_rot_target",(long)scriptEvents.at_rot_target);
|
||||||
|
m_eventFlagsMap.Add("at_target", scriptEvents.at_target);
|
||||||
|
// m_eventFlagsMap.Add("changed",(long)scriptEvents.changed);
|
||||||
|
m_eventFlagsMap.Add("collision", scriptEvents.collision);
|
||||||
|
m_eventFlagsMap.Add("collision_end", scriptEvents.collision_end);
|
||||||
|
m_eventFlagsMap.Add("collision_start", scriptEvents.collision_start);
|
||||||
|
m_eventFlagsMap.Add("control", scriptEvents.control);
|
||||||
|
m_eventFlagsMap.Add("dataserver", scriptEvents.dataserver);
|
||||||
|
m_eventFlagsMap.Add("email", scriptEvents.email);
|
||||||
|
m_eventFlagsMap.Add("http_response", scriptEvents.http_response);
|
||||||
|
m_eventFlagsMap.Add("land_collision", scriptEvents.land_collision);
|
||||||
|
m_eventFlagsMap.Add("land_collision_end", scriptEvents.land_collision_end);
|
||||||
|
m_eventFlagsMap.Add("land_collision_start", scriptEvents.land_collision_start);
|
||||||
|
// m_eventFlagsMap.Add("link_message",scriptEvents.link_message);
|
||||||
|
m_eventFlagsMap.Add("listen", scriptEvents.listen);
|
||||||
|
m_eventFlagsMap.Add("money", scriptEvents.money);
|
||||||
|
m_eventFlagsMap.Add("moving_end", scriptEvents.moving_end);
|
||||||
|
m_eventFlagsMap.Add("moving_start", scriptEvents.moving_start);
|
||||||
|
m_eventFlagsMap.Add("not_at_rot_target", scriptEvents.not_at_rot_target);
|
||||||
|
m_eventFlagsMap.Add("not_at_target", scriptEvents.not_at_target);
|
||||||
|
// m_eventFlagsMap.Add("no_sensor",(long)scriptEvents.no_sensor);
|
||||||
|
// m_eventFlagsMap.Add("on_rez",(long)scriptEvents.on_rez);
|
||||||
|
m_eventFlagsMap.Add("remote_data", scriptEvents.remote_data);
|
||||||
|
m_eventFlagsMap.Add("run_time_permissions", scriptEvents.run_time_permissions);
|
||||||
|
// m_eventFlagsMap.Add("sensor",(long)scriptEvents.sensor);
|
||||||
|
m_eventFlagsMap.Add("state_entry", scriptEvents.state_entry);
|
||||||
|
m_eventFlagsMap.Add("state_exit", scriptEvents.state_exit);
|
||||||
|
m_eventFlagsMap.Add("timer", scriptEvents.timer);
|
||||||
|
m_eventFlagsMap.Add("touch", scriptEvents.touch);
|
||||||
|
m_eventFlagsMap.Add("touch_end", scriptEvents.touch_end);
|
||||||
|
m_eventFlagsMap.Add("touch_start", scriptEvents.touch_start);
|
||||||
|
m_eventFlagsMap.Add("object_rez", scriptEvents.object_rez);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,363 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS AS IS AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
public class LSL2CSConverter
|
||||||
|
{
|
||||||
|
// Uses regex to convert LSL code to C# code.
|
||||||
|
|
||||||
|
//private Regex rnw = new Regex(@"[a-zA-Z0-9_\-]", RegexOptions.Compiled);
|
||||||
|
private Dictionary<string, string> dataTypes = new Dictionary<string, string>();
|
||||||
|
private Dictionary<string, string> quotes = new Dictionary<string, string>();
|
||||||
|
// c Style
|
||||||
|
private Regex cstylecomments = new Regex(@"/\*(.|[\r\n])*?\*/", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
// c# one liners
|
||||||
|
private Regex nonCommentFwsl = new Regex("\"[a-zA-Z0-9.,:/\\n ]+//[^\"+]+([\\\\\\\"+]+)?(\\s+)?[\"+](\\s+)?(;)?", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
private Regex conelinecomments = new Regex(@"[^:].?([\/]{2}[^\n]*)|([\n]{1,}[\/]{2}[^\n]*)", RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
// ([^\"])((?:[a-zA-Z])\.[a-zA-Z].?)([^\"])
|
||||||
|
|
||||||
|
// value we're looking for: (?:[a-zA-Z])\.[a-zA-Z]
|
||||||
|
public LSL2CSConverter()
|
||||||
|
{
|
||||||
|
// Only the types we need to convert
|
||||||
|
dataTypes.Add("void", "void");
|
||||||
|
dataTypes.Add("integer", "LSL_Types.LSLInteger");
|
||||||
|
dataTypes.Add("float", "double");
|
||||||
|
dataTypes.Add("string", "LSL_Types.LSLString");
|
||||||
|
dataTypes.Add("key", "LSL_Types.LSLString");
|
||||||
|
dataTypes.Add("vector", "LSL_Types.Vector3");
|
||||||
|
dataTypes.Add("rotation", "LSL_Types.Quaternion");
|
||||||
|
dataTypes.Add("list", "LSL_Types.list");
|
||||||
|
dataTypes.Add("null", "null");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Convert(string Script)
|
||||||
|
{
|
||||||
|
quotes.Clear();
|
||||||
|
string Return = String.Empty;
|
||||||
|
Script = " \r\n" + Script;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Prepare script for processing
|
||||||
|
//
|
||||||
|
|
||||||
|
// Clean up linebreaks
|
||||||
|
Script = Regex.Replace(Script, @"\r\n", "\n");
|
||||||
|
Script = Regex.Replace(Script, @"\n", "\r\n");
|
||||||
|
|
||||||
|
// QUOTE REPLACEMENT
|
||||||
|
// temporarily replace quotes so we can work our magic on the script without
|
||||||
|
// always considering if we are inside our outside quotes's
|
||||||
|
// TODO: Does this work on half-quotes in strings? ;)
|
||||||
|
string _Script = String.Empty;
|
||||||
|
string C;
|
||||||
|
bool in_quote = false;
|
||||||
|
bool quote_replaced = false;
|
||||||
|
string quote_replacement_string = "Q_U_O_T_E_REPLACEMENT_";
|
||||||
|
string quote = String.Empty;
|
||||||
|
bool last_was_escape = false;
|
||||||
|
int quote_replaced_count = 0;
|
||||||
|
|
||||||
|
string removefwnoncomments = nonCommentFwsl.Replace(Script, "\"\";");
|
||||||
|
|
||||||
|
string removecomments = conelinecomments.Replace(removefwnoncomments, "");
|
||||||
|
removecomments = cstylecomments.Replace(removecomments, "");
|
||||||
|
string[] localscript = removecomments.Split('"');
|
||||||
|
string checkscript = String.Empty;
|
||||||
|
bool flip = true;
|
||||||
|
|
||||||
|
for (int p = 0; p < localscript.Length; p++)
|
||||||
|
{
|
||||||
|
//if (localscript[p].Length >= 1)
|
||||||
|
//{
|
||||||
|
if (!localscript[p].EndsWith(@"\"))
|
||||||
|
{
|
||||||
|
flip = !flip;
|
||||||
|
//System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p] + " ! " + localscript[p].EndsWith(@"\").ToString());
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// flip = !flip;
|
||||||
|
// System.Console.WriteLine("Flip:" + flip.ToString() + " - " + localscript[p]);
|
||||||
|
//}
|
||||||
|
if (!flip)
|
||||||
|
checkscript += localscript[p];
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.Console.WriteLine("SCRIPT:" + checkscript);
|
||||||
|
|
||||||
|
// checks for alpha.alpha way of referring to objects in C#
|
||||||
|
// ignores alpha.x alpha.y, alpha.z for refering to vector components
|
||||||
|
Match SecurityM;
|
||||||
|
|
||||||
|
// BROKEN: this check is very wrong. It block's any url in strings.
|
||||||
|
SecurityM = Regex.Match(checkscript, @"(?:[a-zA-Z])\.(?:[a-wA-Z]|[a-zA-Z][a-zA-Z])", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
if (SecurityM.Success)
|
||||||
|
throw new Exception("CS0103: 'The . symbol cannot be used in LSL except in float values or vector components'. Detected around: " + SecurityM.Captures[0].Value);
|
||||||
|
|
||||||
|
SecurityM = Regex.Match(checkscript, @"typeof\s", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
if (SecurityM.Success)
|
||||||
|
throw new Exception("CS0103: 'The object.typeof method isn't allowed in LSL'");
|
||||||
|
|
||||||
|
SecurityM = Regex.Match(checkscript, @"GetType\(", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
if (SecurityM.Success)
|
||||||
|
throw new Exception("CS0103: 'The object.GetType method isn't allowed in LSL'");
|
||||||
|
|
||||||
|
for (int p = 0; p < Script.Length; p++)
|
||||||
|
{
|
||||||
|
C = Script.Substring(p, 1);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// found " and last was not \ so this is not an escaped \"
|
||||||
|
if (C == "\"" && last_was_escape == false)
|
||||||
|
{
|
||||||
|
// Toggle inside/outside quote
|
||||||
|
in_quote = !in_quote;
|
||||||
|
if (in_quote)
|
||||||
|
{
|
||||||
|
quote_replaced_count++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (quote == String.Empty)
|
||||||
|
{
|
||||||
|
// We didn't replace quote, probably because of empty string?
|
||||||
|
_Script += quote_replacement_string +
|
||||||
|
quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]);
|
||||||
|
}
|
||||||
|
// We just left a quote
|
||||||
|
quotes.Add(
|
||||||
|
quote_replacement_string +
|
||||||
|
quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]), quote);
|
||||||
|
quote = String.Empty;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!in_quote)
|
||||||
|
{
|
||||||
|
// We are not inside a quote
|
||||||
|
quote_replaced = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We are inside a quote
|
||||||
|
if (!quote_replaced)
|
||||||
|
{
|
||||||
|
// Replace quote
|
||||||
|
_Script += quote_replacement_string +
|
||||||
|
quote_replaced_count.ToString().PadLeft(5, "0".ToCharArray()[0]);
|
||||||
|
quote_replaced = true;
|
||||||
|
}
|
||||||
|
quote += C;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
_Script += C;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
last_was_escape = false;
|
||||||
|
if (C == @"\")
|
||||||
|
{
|
||||||
|
last_was_escape = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Script = _Script;
|
||||||
|
//
|
||||||
|
// END OF QUOTE REPLACEMENT
|
||||||
|
//
|
||||||
|
|
||||||
|
//
|
||||||
|
// PROCESS STATES
|
||||||
|
// Remove state definitions and add state names to start of each event within state
|
||||||
|
//
|
||||||
|
int ilevel = 0;
|
||||||
|
int lastlevel = 0;
|
||||||
|
string ret = String.Empty;
|
||||||
|
string cache = String.Empty;
|
||||||
|
bool in_state = false;
|
||||||
|
string current_statename = String.Empty;
|
||||||
|
for (int p = 0; p < Script.Length; p++)
|
||||||
|
{
|
||||||
|
C = Script.Substring(p, 1);
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// inc / dec level
|
||||||
|
if (C == @"{")
|
||||||
|
ilevel++;
|
||||||
|
if (C == @"}")
|
||||||
|
ilevel--;
|
||||||
|
if (ilevel < 0)
|
||||||
|
ilevel = 0;
|
||||||
|
cache += C;
|
||||||
|
|
||||||
|
// if level == 0, add to return
|
||||||
|
if (ilevel == 1 && lastlevel == 0)
|
||||||
|
{
|
||||||
|
// 0 => 1: Get last
|
||||||
|
Match m =
|
||||||
|
//Regex.Match(cache, @"(?![a-zA-Z_]+)\s*([a-zA-Z_]+)[^a-zA-Z_\(\)]*{",
|
||||||
|
Regex.Match(cache, @"(?![a-zA-Z_]+)\s*(state\s+)?(?<statename>[a-zA-Z_][a-zA-Z_0-9]*)[^a-zA-Z_0-9\(\)]*{",
|
||||||
|
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
in_state = false;
|
||||||
|
if (m.Success)
|
||||||
|
{
|
||||||
|
// Go back to level 0, this is not a state
|
||||||
|
in_state = true;
|
||||||
|
current_statename = m.Groups["statename"].Captures[0].Value;
|
||||||
|
//Console.WriteLine("Current statename: " + current_statename);
|
||||||
|
cache =
|
||||||
|
//@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"([a-zA-Z_]+)(?<s2>[^a-zA-Z_\(\)]*){",
|
||||||
|
Regex.Replace(cache,
|
||||||
|
@"(?<s1>(?![a-zA-Z_]+)\s*)" + @"(state\s+)?([a-zA-Z_][a-zA-Z_0-9]*)(?<s2>[^a-zA-Z_0-9\(\)]*){",
|
||||||
|
"${s1}${s2}",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||||
|
}
|
||||||
|
ret += cache;
|
||||||
|
cache = String.Empty;
|
||||||
|
}
|
||||||
|
if (ilevel == 0 && lastlevel == 1)
|
||||||
|
{
|
||||||
|
// 1 => 0: Remove last }
|
||||||
|
if (in_state == true)
|
||||||
|
{
|
||||||
|
cache = cache.Remove(cache.Length - 1, 1);
|
||||||
|
//cache = Regex.Replace(cache, "}$", String.Empty, RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
//Replace function names
|
||||||
|
// void dataserver(key query_id, string data) {
|
||||||
|
//cache = Regex.Replace(cache, @"([^a-zA-Z_]\s*)((?!if|switch|for)[a-zA-Z_]+\s*\([^\)]*\)[^{]*{)", "$1" + "<STATE>" + "$2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
//Console.WriteLine("Replacing using statename: " + current_statename);
|
||||||
|
cache =
|
||||||
|
Regex.Replace(cache,
|
||||||
|
@"^(\s*)((?!(if|switch|for|while)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)",
|
||||||
|
@"$1public " + current_statename + "_event_$2",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret += cache;
|
||||||
|
cache = String.Empty;
|
||||||
|
in_state = true;
|
||||||
|
current_statename = String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
lastlevel = ilevel;
|
||||||
|
}
|
||||||
|
ret += cache;
|
||||||
|
cache = String.Empty;
|
||||||
|
|
||||||
|
Script = ret;
|
||||||
|
ret = String.Empty;
|
||||||
|
|
||||||
|
foreach (string key in dataTypes.Keys)
|
||||||
|
{
|
||||||
|
string val;
|
||||||
|
dataTypes.TryGetValue(key, out val);
|
||||||
|
|
||||||
|
// Replace CAST - (integer) with (int)
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"\(" + key + @"\)", @"(" + val + ")",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
// Replace return types and function variables - integer a() and f(integer a, integer a)
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s+)", @"$1$2" + val + "$3",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"(^|;|}|[\(,])(\s*)" + key + @"(\s*)[,]", @"$1$2" + val + "$3,",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add "void" in front of functions that needs it
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script,
|
||||||
|
@"^(\s*public\s+)?((?!(if|switch|for)[^a-zA-Z0-9_])[a-zA-Z0-9_]*\s*\([^\)]*\)[^;]*\{)",
|
||||||
|
@"$1void $2", RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
// Replace <x,y,z> and <x,y,z,r>
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"<([^,>;]*,[^,>;]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Quaternion($1)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"<([^,>;)]*,[^,>;]*,[^,>;]*)>", @"new LSL_Types.Vector3($1)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
// Replace List []'s
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"\[([^\]]*)\]", @"new LSL_Types.list($1)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
// Replace (string) to .ToString() //
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"\(string\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.ToString()",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"\((float|int)\)\s*([a-zA-Z0-9_.]+(\s*\([^\)]*\))?)", @"$1.Parse($2)",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline);
|
||||||
|
|
||||||
|
// Replace "state STATENAME" with "state("statename")"
|
||||||
|
Script =
|
||||||
|
Regex.Replace(Script, @"(state)\s+([^;\n\r]+)(;[\r\n\s])", "$1(\"$2\")$3",
|
||||||
|
RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.IgnoreCase);
|
||||||
|
|
||||||
|
// REPLACE BACK QUOTES
|
||||||
|
foreach (string key in quotes.Keys)
|
||||||
|
{
|
||||||
|
string val;
|
||||||
|
quotes.TryGetValue(key, out val);
|
||||||
|
Script = Script.Replace(key, "\"" + val + "\"");
|
||||||
|
}
|
||||||
|
|
||||||
|
//System.Console.WriteLine(Script);
|
||||||
|
Return = String.Empty;// +
|
||||||
|
//"using OpenSim.Region.ScriptEngine.Common; using System.Collections.Generic;";
|
||||||
|
|
||||||
|
//Return += String.Empty +
|
||||||
|
// "namespace SecondLife { ";
|
||||||
|
//Return += String.Empty +
|
||||||
|
// //"[Serializable] " +
|
||||||
|
// "public class Script : OpenSim.Region.ScriptEngine.Common.LSL_BaseClass { ";
|
||||||
|
//Return += @"public Script() { } ";
|
||||||
|
Return += Script;
|
||||||
|
//Return += "} }\r\n";
|
||||||
|
|
||||||
|
quotes.Clear();
|
||||||
|
|
||||||
|
return Return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,553 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
using System;
|
||||||
|
using Axiom.Math;
|
||||||
|
using libsecondlife;
|
||||||
|
using Nini.Config;
|
||||||
|
using OpenSim.Framework.Console;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
using OpenSim.Region.Environment.Scenes;
|
||||||
|
using OpenSim.Region.ScriptEngine.XEngine.Script;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class OSSL_ScriptCommands : MarshalByRefObject, IOSSL_ScriptCommands
|
||||||
|
{
|
||||||
|
internal XEngine m_ScriptEngine;
|
||||||
|
internal XScriptInstance m_Instance;
|
||||||
|
internal SceneObjectPart m_host;
|
||||||
|
internal uint m_localID;
|
||||||
|
internal LLUUID m_itemID;
|
||||||
|
|
||||||
|
public OSSL_ScriptCommands(XEngine scriptEngine,
|
||||||
|
XScriptInstance instance, SceneObjectPart host,
|
||||||
|
uint localID, LLUUID itemID)
|
||||||
|
{
|
||||||
|
m_ScriptEngine = scriptEngine;
|
||||||
|
m_Instance = instance;
|
||||||
|
m_host = host;
|
||||||
|
m_localID = localID;
|
||||||
|
m_itemID = itemID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//
|
||||||
|
// OpenSim functions
|
||||||
|
//
|
||||||
|
|
||||||
|
public int osTerrainSetHeight(int x, int y, double val)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osTerrainSetHeight: permission denied");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (x > 255 || x < 0 || y > 255 || y < 0)
|
||||||
|
OSSLError("osTerrainSetHeight: Coordinate out of bounds");
|
||||||
|
|
||||||
|
if (World.ExternalChecks.ExternalChecksCanTerraformLand(m_host.OwnerID, new LLVector3(x, y, 0)))
|
||||||
|
{
|
||||||
|
World.Heightmap[x, y] = val;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double osTerrainGetHeight(int x, int y)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osTerrainGetHeight: permission denied");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (x > 255 || x < 0 || y > 255 || y < 0)
|
||||||
|
OSSLError("osTerrainGetHeight: Coordinate out of bounds");
|
||||||
|
|
||||||
|
return World.Heightmap[x, y];
|
||||||
|
}
|
||||||
|
|
||||||
|
public int osRegionRestart(double seconds)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osRegionRestart: permission denied");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (World.ExternalChecks.ExternalChecksCanIssueEstateCommand(m_host.OwnerID))
|
||||||
|
{
|
||||||
|
World.Restart((float)seconds);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osRegionNotice(string msg)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osRegionNotice: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
World.SendGeneralAlert(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osSetRot(LLUUID target, Quaternion rotation)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetRot: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (World.Entities.ContainsKey(target))
|
||||||
|
{
|
||||||
|
World.Entities[target].Rotation = rotation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
OSSLError("osSetRot: Invalid target");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams,
|
||||||
|
int timer)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetDynamicTextureURL: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (dynamicID == String.Empty)
|
||||||
|
{
|
||||||
|
IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
|
||||||
|
LLUUID createdTexture =
|
||||||
|
textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
|
||||||
|
extraParams, timer);
|
||||||
|
return createdTexture.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO update existing dynamic textures
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLUUID.Zero.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
|
||||||
|
int timer, int alpha)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetDynamicTextureURLBlend: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (dynamicID == String.Empty)
|
||||||
|
{
|
||||||
|
IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
|
||||||
|
LLUUID createdTexture =
|
||||||
|
textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url,
|
||||||
|
extraParams, timer, true, (byte) alpha);
|
||||||
|
return createdTexture.ToString();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO update existing dynamic textures
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLUUID.Zero.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams,
|
||||||
|
int timer)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetDynamicTextureData: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (dynamicID == String.Empty)
|
||||||
|
{
|
||||||
|
IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
|
||||||
|
if (textureManager != null)
|
||||||
|
{
|
||||||
|
LLUUID createdTexture =
|
||||||
|
textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
|
||||||
|
extraParams, timer);
|
||||||
|
return createdTexture.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO update existing dynamic textures
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLUUID.Zero.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
|
||||||
|
int timer, int alpha)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetDynamicTextureDataBlend: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (dynamicID == String.Empty)
|
||||||
|
{
|
||||||
|
IDynamicTextureManager textureManager = World.RequestModuleInterface<IDynamicTextureManager>();
|
||||||
|
if (textureManager != null)
|
||||||
|
{
|
||||||
|
LLUUID createdTexture =
|
||||||
|
textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data,
|
||||||
|
extraParams, timer, true, (byte) alpha);
|
||||||
|
return createdTexture.ToString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//TODO update existing dynamic textures
|
||||||
|
}
|
||||||
|
|
||||||
|
return LLUUID.Zero.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool osConsoleCommand(string command)
|
||||||
|
{
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowosConsoleCommand", false))
|
||||||
|
{
|
||||||
|
if (World.ExternalChecks.ExternalChecksCanRunConsoleCommand(m_host.OwnerID))
|
||||||
|
{
|
||||||
|
MainConsole.Instance.RunCommand(command);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
public void osSetPrimFloatOnWater(int floatYN)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetPrimFloatOnWater: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (m_host.ParentGroup != null)
|
||||||
|
{
|
||||||
|
if (m_host.ParentGroup.RootPart != null)
|
||||||
|
{
|
||||||
|
m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Adam's super super custom animation functions
|
||||||
|
public void osAvatarPlayAnimation(string avatar, string animation)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osAvatarPlayAnimation: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
|
||||||
|
{
|
||||||
|
ScenePresence target = (ScenePresence)World.Entities[avatar];
|
||||||
|
target.AddAnimation(avatar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osAvatarStopAnimation(string avatar, string animation)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osAvatarStopAnimation: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (World.Entities.ContainsKey(avatar) && World.Entities[avatar] is ScenePresence)
|
||||||
|
{
|
||||||
|
ScenePresence target = (ScenePresence)World.Entities[avatar];
|
||||||
|
target.RemoveAnimation(animation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Texture draw functions
|
||||||
|
public string osMovePen(string drawList, int x, int y)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osMovePen: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "MoveTo " + x + "," + y + ";";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawLine(string drawList, int startX, int startY, int endX, int endY)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawLine: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawLine(string drawList, int endX, int endY)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawLine: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "LineTo " + endX + "," + endY + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawText(string drawList, string text)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawText: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "Text " + text + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawEllipse(string drawList, int width, int height)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawEllipse: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "Ellipse " + width + "," + height + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawRectangle(string drawList, int width, int height)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawRectangle: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "Rectangle " + width + "," + height + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawFilledRectangle(string drawList, int width, int height)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawFilledRectangle: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "FillRectangle " + width + "," + height + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetFontSize(string drawList, int fontSize)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetFontSize: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "FontSize "+ fontSize +"; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetPenSize(string drawList, int penSize)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetPenSize: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "PenSize " + penSize + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osSetPenColour(string drawList, string colour)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetPenColour: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList += "PenColour " + colour + "; ";
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public string osDrawImage(string drawList, int width, int height, string imageUrl)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osDrawImage: permission denied");
|
||||||
|
return String.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ;
|
||||||
|
return drawList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osSetStateEvents(int events)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetStateEvents: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.SetScriptEvents(m_itemID, events);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osSetRegionWaterHeight(double height)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetRegionWaterHeight: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
//Check to make sure that the script's owner is the estate manager/master
|
||||||
|
//World.Permissions.GenericEstatePermission(
|
||||||
|
if (World.ExternalChecks.ExternalChecksCanBeGodLike(m_host.OwnerID))
|
||||||
|
{
|
||||||
|
World.EventManager.TriggerRequestChangeWaterHeight((float)height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public double osList2Double(LSL_Types.list src, int index)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osList2Double: permission denied");
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
if (index < 0)
|
||||||
|
{
|
||||||
|
index = src.Length + index;
|
||||||
|
}
|
||||||
|
if (index >= src.Length)
|
||||||
|
{
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
return Convert.ToDouble(src.Data[index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void osSetParcelMediaURL(string url)
|
||||||
|
{
|
||||||
|
if (!m_ScriptEngine.ScriptConfigSource.GetBoolean("AllowOSFunctions", false))
|
||||||
|
{
|
||||||
|
OSSLError("osSetParcelMediaURL: permission denied");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.AddScriptLPS(1);
|
||||||
|
LLUUID landowner = World.GetLandOwner(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
|
||||||
|
|
||||||
|
if (landowner == LLUUID.Zero)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (landowner != m_host.ObjectOwner)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
World.SetLandMediaURL(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y, url);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Scene World
|
||||||
|
{
|
||||||
|
get { return m_ScriptEngine.World; }
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void OSSLError(string msg)
|
||||||
|
{
|
||||||
|
throw new Exception("OSSL Runtime Error: " + msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.Script
|
||||||
|
{
|
||||||
|
[Serializable]
|
||||||
|
public class AssemblyResolver
|
||||||
|
{
|
||||||
|
public static Assembly OnAssemblyResolve(object sender,
|
||||||
|
ResolveEventArgs args)
|
||||||
|
{
|
||||||
|
if(!(sender is System.AppDomain))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
AppDomain myDomain = (AppDomain)sender;
|
||||||
|
string dirName = myDomain.FriendlyName;
|
||||||
|
|
||||||
|
string[] pathList=new string[] {"bin", "ScriptEngines",
|
||||||
|
Path.Combine("ScriptEngines", dirName)};
|
||||||
|
|
||||||
|
string assemblyName = args.Name;
|
||||||
|
if(assemblyName.IndexOf(",") != -1)
|
||||||
|
assemblyName=args.Name.Substring(0, args.Name.IndexOf(","));
|
||||||
|
|
||||||
|
foreach (string s in pathList)
|
||||||
|
{
|
||||||
|
string path=Path.Combine(Directory.GetCurrentDirectory(),
|
||||||
|
Path.Combine(s, assemblyName))+".dll";
|
||||||
|
|
||||||
|
if(File.Exists(path))
|
||||||
|
return Assembly.LoadFrom(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,653 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.Script
|
||||||
|
{
|
||||||
|
public interface ILSL_ScriptCommands
|
||||||
|
{
|
||||||
|
// Interface used for loading and executing scripts
|
||||||
|
|
||||||
|
string State { get; set ; }
|
||||||
|
|
||||||
|
void state(string newState);
|
||||||
|
|
||||||
|
ICommander GetCommander(string name);
|
||||||
|
|
||||||
|
void llSay(int channelID, string text);
|
||||||
|
double llSin(double f);
|
||||||
|
double llCos(double f);
|
||||||
|
double llTan(double f);
|
||||||
|
double llAtan2(double x, double y);
|
||||||
|
double llSqrt(double f);
|
||||||
|
double llPow(double fbase, double fexponent);
|
||||||
|
LSL_Types.LSLInteger llAbs(int i);
|
||||||
|
double llFabs(double f);
|
||||||
|
double llFrand(double mag);
|
||||||
|
LSL_Types.LSLInteger llFloor(double f);
|
||||||
|
LSL_Types.LSLInteger llCeil(double f);
|
||||||
|
LSL_Types.LSLInteger llRound(double f);
|
||||||
|
double llVecMag(LSL_Types.Vector3 v);
|
||||||
|
LSL_Types.Vector3 llVecNorm(LSL_Types.Vector3 v);
|
||||||
|
double llVecDist(LSL_Types.Vector3 a, LSL_Types.Vector3 b);
|
||||||
|
LSL_Types.Vector3 llRot2Euler(LSL_Types.Quaternion r);
|
||||||
|
LSL_Types.Quaternion llEuler2Rot(LSL_Types.Vector3 v);
|
||||||
|
LSL_Types.Quaternion llAxes2Rot(LSL_Types.Vector3 fwd, LSL_Types.Vector3 left, LSL_Types.Vector3 up);
|
||||||
|
LSL_Types.Vector3 llRot2Fwd(LSL_Types.Quaternion r);
|
||||||
|
LSL_Types.Vector3 llRot2Left(LSL_Types.Quaternion r);
|
||||||
|
LSL_Types.Vector3 llRot2Up(LSL_Types.Quaternion r);
|
||||||
|
LSL_Types.Quaternion llRotBetween(LSL_Types.Vector3 start, LSL_Types.Vector3 end);
|
||||||
|
void llWhisper(int channelID, string text);
|
||||||
|
//void llSay(int channelID, string text);
|
||||||
|
void llShout(int channelID, string text);
|
||||||
|
void llRegionSay(int channelID, string text);
|
||||||
|
LSL_Types.LSLInteger llListen(int channelID, string name, string ID, string msg);
|
||||||
|
void llListenControl(int number, int active);
|
||||||
|
void llListenRemove(int number);
|
||||||
|
void llSensor(string name, string id, int type, double range, double arc);
|
||||||
|
void llSensorRepeat(string name, string id, int type, double range, double arc, double rate);
|
||||||
|
void llSensorRemove();
|
||||||
|
string llDetectedName(int number);
|
||||||
|
string llDetectedKey(int number);
|
||||||
|
string llDetectedOwner(int number);
|
||||||
|
LSL_Types.LSLInteger llDetectedType(int number);
|
||||||
|
LSL_Types.Vector3 llDetectedPos(int number);
|
||||||
|
LSL_Types.Vector3 llDetectedVel(int number);
|
||||||
|
LSL_Types.Vector3 llDetectedGrab(int number);
|
||||||
|
LSL_Types.Quaternion llDetectedRot(int number);
|
||||||
|
LSL_Types.LSLInteger llDetectedGroup(int number);
|
||||||
|
LSL_Types.LSLInteger llDetectedLinkNumber(int number);
|
||||||
|
void llDie();
|
||||||
|
double llGround(LSL_Types.Vector3 offset);
|
||||||
|
double llCloud(LSL_Types.Vector3 offset);
|
||||||
|
LSL_Types.Vector3 llWind(LSL_Types.Vector3 offset);
|
||||||
|
void llSetStatus(int status, int value);
|
||||||
|
LSL_Types.LSLInteger llGetStatus(int status);
|
||||||
|
void llSetScale(LSL_Types.Vector3 scale);
|
||||||
|
LSL_Types.Vector3 llGetScale();
|
||||||
|
void llSetColor(LSL_Types.Vector3 color, int face);
|
||||||
|
double llGetAlpha(int face);
|
||||||
|
void llSetAlpha(double alpha, int face);
|
||||||
|
LSL_Types.Vector3 llGetColor(int face);
|
||||||
|
void llSetTexture(string texture, int face);
|
||||||
|
void llScaleTexture(double u, double v, int face);
|
||||||
|
void llOffsetTexture(double u, double v, int face);
|
||||||
|
void llRotateTexture(double rotation, int face);
|
||||||
|
string llGetTexture(int face);
|
||||||
|
void llSetPos(LSL_Types.Vector3 pos);
|
||||||
|
|
||||||
|
//wiki: vector llGetPos()
|
||||||
|
LSL_Types.Vector3 llGetPos();
|
||||||
|
//wiki: vector llGetLocalPos()
|
||||||
|
LSL_Types.Vector3 llGetLocalPos();
|
||||||
|
//wiki: llSetRot(rotation rot)
|
||||||
|
void llSetRot(LSL_Types.Quaternion rot);
|
||||||
|
//wiki: rotation llGetRot()
|
||||||
|
LSL_Types.Quaternion llGetRot();
|
||||||
|
//wiki: rotation llGetLocalRot()
|
||||||
|
LSL_Types.Quaternion llGetLocalRot();
|
||||||
|
//wiki: llSetForce(vector force, integer local)
|
||||||
|
void llSetForce(LSL_Types.Vector3 force, int local);
|
||||||
|
//wiki: vector llGetForce()
|
||||||
|
LSL_Types.Vector3 llGetForce();
|
||||||
|
//wiki: integer llTarget(vector position, double range)
|
||||||
|
LSL_Types.LSLInteger llTarget(LSL_Types.Vector3 position, double range);
|
||||||
|
//wiki: llTargetRemove(integer number)
|
||||||
|
void llTargetRemove(int number);
|
||||||
|
//wiki: integer llRotTarget(rotation rot, double error)
|
||||||
|
LSL_Types.LSLInteger llRotTarget(LSL_Types.Quaternion rot, double error);
|
||||||
|
//wiki: integer llRotTargetRemove(integer number)
|
||||||
|
void llRotTargetRemove(int number);
|
||||||
|
//wiki: llMoveToTarget(vector target, double tau)
|
||||||
|
void llMoveToTarget(LSL_Types.Vector3 target, double tau);
|
||||||
|
//wiki: llStopMoveToTarget()
|
||||||
|
void llStopMoveToTarget();
|
||||||
|
//wiki: llApplyImpulse(vector force, integer local)
|
||||||
|
void llApplyImpulse(LSL_Types.Vector3 force, int local);
|
||||||
|
//wiki: llapplyRotationalImpulse(vector force, integer local)
|
||||||
|
void llApplyRotationalImpulse(LSL_Types.Vector3 force, int local);
|
||||||
|
//wiki: llSetTorque(vector torque, integer local)
|
||||||
|
void llSetTorque(LSL_Types.Vector3 torque, int local);
|
||||||
|
//wiki: vector llGetTorque()
|
||||||
|
LSL_Types.Vector3 llGetTorque();
|
||||||
|
//wiki: llSeForceAndTorque(vector force, vector torque, integer local)
|
||||||
|
void llSetForceAndTorque(LSL_Types.Vector3 force, LSL_Types.Vector3 torque, int local);
|
||||||
|
//wiki: vector llGetVel()
|
||||||
|
LSL_Types.Vector3 llGetVel();
|
||||||
|
//wiki: vector llGetAccel()
|
||||||
|
LSL_Types.Vector3 llGetAccel();
|
||||||
|
//wiki: vector llGetOmega()
|
||||||
|
LSL_Types.Vector3 llGetOmega();
|
||||||
|
//wiki: double llGetTimeOfDay()
|
||||||
|
double llGetTimeOfDay();
|
||||||
|
//wiki: double llGetWallclock()
|
||||||
|
double llGetWallclock();
|
||||||
|
//wiki: double llGetTime()
|
||||||
|
double llGetTime();
|
||||||
|
//wiki: llResetTime()
|
||||||
|
void llResetTime();
|
||||||
|
//wiki: double llGetAndResetTime()
|
||||||
|
double llGetAndResetTime();
|
||||||
|
//wiki (deprecated) llSound(string sound, double volume, integer queue, integer loop)
|
||||||
|
void llSound();
|
||||||
|
//wiki: llPlaySound(string sound, double volume)
|
||||||
|
void llPlaySound(string sound, double volume);
|
||||||
|
//wiki: llLoopSound(string sound, double volume)
|
||||||
|
void llLoopSound(string sound, double volume);
|
||||||
|
//wiki: llLoopSoundMaster(string sound, double volume)
|
||||||
|
void llLoopSoundMaster(string sound, double volume);
|
||||||
|
//wiki: llLoopSoundSlave(string sound, double volume)
|
||||||
|
void llLoopSoundSlave(string sound, double volume);
|
||||||
|
//wiki llPlaySoundSlave(string sound, double volume)
|
||||||
|
void llPlaySoundSlave(string sound, double volume);
|
||||||
|
//wiki: llTriggerSound(string sound, double volume)
|
||||||
|
void llTriggerSound(string sound, double volume);
|
||||||
|
//wiki: llStopSound()
|
||||||
|
void llStopSound();
|
||||||
|
//wiki: llPreloadSound(string sound)
|
||||||
|
void llPreloadSound(string sound);
|
||||||
|
//wiki: string llGetSubString(string src, integer start, integer end)
|
||||||
|
string llGetSubString(string src, int start, int end);
|
||||||
|
//wiki: string llDeleteSubString(string src, integer start, integer end)
|
||||||
|
string llDeleteSubString(string src, int start, int end);
|
||||||
|
//wiki string llInsertString(string dst, integer position, string src)
|
||||||
|
string llInsertString(string dst, int position, string src);
|
||||||
|
//wiki: string llToUpper(string source)
|
||||||
|
string llToUpper(string source);
|
||||||
|
//wiki: string llToLower(string source)
|
||||||
|
string llToLower(string source);
|
||||||
|
//wiki: integer llGiveMoney(key destination, integer amount)
|
||||||
|
LSL_Types.LSLInteger llGiveMoney(string destination, int amount);
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llMakeExplosion();
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llMakeFountain();
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llMakeSmoke();
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llMakeFire();
|
||||||
|
//wiki: llRezObject(string inventory, vector pos, vector rel, rotation rot, integer param)
|
||||||
|
void llRezObject(string inventory, LSL_Types.Vector3 pos, LSL_Types.Vector3 vel, LSL_Types.Quaternion rot, int param);
|
||||||
|
//wiki: llLookAt(vector target, double strength, double damping)
|
||||||
|
void llLookAt(LSL_Types.Vector3 target, double strength, double damping);
|
||||||
|
//wiki: llStopLookAt()
|
||||||
|
void llStopLookAt();
|
||||||
|
//wiki: llSetTimerEvent(double sec)
|
||||||
|
void llSetTimerEvent(double sec);
|
||||||
|
//wiki: llSleep(double sec)
|
||||||
|
void llSleep(double sec);
|
||||||
|
//wiki: double llGetMass()
|
||||||
|
double llGetMass();
|
||||||
|
//wiki: llCollisionFilter(string name, key id, integer accept)
|
||||||
|
void llCollisionFilter(string name, string id, int accept);
|
||||||
|
//wiki: llTakeControls(integer controls, integer accept, integer pass_on)
|
||||||
|
void llTakeControls(int controls, int accept, int pass_on);
|
||||||
|
//wiki: llReleaseControls()
|
||||||
|
void llReleaseControls();
|
||||||
|
//wiki: llAttachToAvatar(integer attachment)
|
||||||
|
void llAttachToAvatar(int attachment);
|
||||||
|
//wiki: llDetachFromAvatar()
|
||||||
|
void llDetachFromAvatar();
|
||||||
|
//wiki: (deprecated) llTakeCamera()
|
||||||
|
void llTakeCamera();
|
||||||
|
//wiki: (deprecated) llReleaseCamera()
|
||||||
|
void llReleaseCamera();
|
||||||
|
//wiki: key llGetOwner()
|
||||||
|
string llGetOwner();
|
||||||
|
//wiki: llInstantMessage(key user, string message)
|
||||||
|
void llInstantMessage(string user, string message);
|
||||||
|
//wiki: llEmail(string address, string subject, string message)
|
||||||
|
void llEmail(string address, string subject, string message);
|
||||||
|
//wiki: llGetNextEmail(string address, string subject)
|
||||||
|
void llGetNextEmail(string address, string subject);
|
||||||
|
//wiki: key llGetKey()
|
||||||
|
string llGetKey();
|
||||||
|
//wiki: llSetBuoyancy(double buoyancy)
|
||||||
|
void llSetBuoyancy(double buoyancy);
|
||||||
|
//wiki: llSetHoverHeight(double height, integer water, double tau)
|
||||||
|
void llSetHoverHeight(double height, int water, double tau);
|
||||||
|
//wiki: llStopHover
|
||||||
|
void llStopHover();
|
||||||
|
//wiki: llMinEventDelay(double delay)
|
||||||
|
void llMinEventDelay(double delay);
|
||||||
|
//wiki: (deprecated) llSoundPreload()
|
||||||
|
void llSoundPreload();
|
||||||
|
//wiki: llRotLookAt(rotation target, double strength, double damping)
|
||||||
|
void llRotLookAt(LSL_Types.Quaternion target, double strength, double damping);
|
||||||
|
//wiki: integer llStringLength(string str)
|
||||||
|
LSL_Types.LSLInteger llStringLength(string str);
|
||||||
|
//wiki: llStartAnimation(string anim)
|
||||||
|
void llStartAnimation(string anim);
|
||||||
|
//wiki: llStopAnimation(string anim)
|
||||||
|
void llStopAnimation(string anim);
|
||||||
|
//wiki: (deprecated) llPointAt
|
||||||
|
void llPointAt();
|
||||||
|
//wiki: (deprecated) llStopPointAt
|
||||||
|
void llStopPointAt();
|
||||||
|
//wiki: llTargetOmega(vector axis, double spinrate, double gain)
|
||||||
|
void llTargetOmega(LSL_Types.Vector3 axis, double spinrate, double gain);
|
||||||
|
//wiki: integer llGetStartParameter()
|
||||||
|
LSL_Types.LSLInteger llGetStartParameter();
|
||||||
|
//wiki: llGodLikeRezObject(key inventory, vector pos)
|
||||||
|
void llGodLikeRezObject(string inventory, LSL_Types.Vector3 pos);
|
||||||
|
//wiki: llRequestPermissions(key agent, integer perm)
|
||||||
|
void llRequestPermissions(string agent, int perm);
|
||||||
|
//wiki: key llGetPermissionsKey()
|
||||||
|
string llGetPermissionsKey();
|
||||||
|
//wiki: integer llGetPermissions()
|
||||||
|
LSL_Types.LSLInteger llGetPermissions();
|
||||||
|
//wiki integer llGetLinkNumber()
|
||||||
|
LSL_Types.LSLInteger llGetLinkNumber();
|
||||||
|
//wiki: llSetLinkColor(integer linknumber, vector color, integer face)
|
||||||
|
void llSetLinkColor(int linknumber, LSL_Types.Vector3 color, int face);
|
||||||
|
//wiki: llCreateLink(key target, integer parent)
|
||||||
|
void llCreateLink(string target, int parent);
|
||||||
|
//wiki: llBreakLink(integer linknum)
|
||||||
|
void llBreakLink(int linknum);
|
||||||
|
//wiki: llBreakAllLinks()
|
||||||
|
void llBreakAllLinks();
|
||||||
|
//wiki: key llGetLinkKey(integer linknum)
|
||||||
|
string llGetLinkKey(int linknum);
|
||||||
|
//wiki: llGetLinkName(integer linknum)
|
||||||
|
string llGetLinkName(int linknum);
|
||||||
|
//wiki: integer llGetInventoryNumber(integer type)
|
||||||
|
LSL_Types.LSLInteger llGetInventoryNumber(int type);
|
||||||
|
//wiki: string llGetInventoryName(integer type, integer number)
|
||||||
|
string llGetInventoryName(int type, int number);
|
||||||
|
//wiki: llSetScriptState(string name, integer run)
|
||||||
|
void llSetScriptState(string name, int run);
|
||||||
|
//wiki: double llGetEnergy()
|
||||||
|
double llGetEnergy();
|
||||||
|
//wiki: llGiveInventory(key destination, string inventory)
|
||||||
|
void llGiveInventory(string destination, string inventory);
|
||||||
|
//wiki: llRemoveInventory(string item)
|
||||||
|
void llRemoveInventory(string item);
|
||||||
|
//wiki: llSetText(string text, vector color, double alpha)
|
||||||
|
void llSetText(string text, LSL_Types.Vector3 color, double alpha);
|
||||||
|
//wiki: double llWater(vector offset)
|
||||||
|
double llWater(LSL_Types.Vector3 offset);
|
||||||
|
//wiki: llPassTouches(integer pass)
|
||||||
|
void llPassTouches(int pass);
|
||||||
|
//wiki: key llRequestAgentData(key id, integer data)
|
||||||
|
string llRequestAgentData(string id, int data);
|
||||||
|
//wiki: key llRequestInventoryData(string name)
|
||||||
|
string llRequestInventoryData(string name);
|
||||||
|
//wiki: llSetDamage(double damage)
|
||||||
|
void llSetDamage(double damage);
|
||||||
|
//wiki: llTeleportAgentHome(key agent)
|
||||||
|
void llTeleportAgentHome(string agent);
|
||||||
|
//wiki: llModifyLand(integer action, integer brush)
|
||||||
|
void llModifyLand(int action, int brush);
|
||||||
|
//wiki: llCollisionSound(string impact_sound, double impact_volume)
|
||||||
|
void llCollisionSound(string impact_sound, double impact_volume);
|
||||||
|
//wiki: llCollisionSprite(string impact_sprite)
|
||||||
|
void llCollisionSprite(string impact_sprite);
|
||||||
|
//wiki: string llGetAnimation(key id)
|
||||||
|
string llGetAnimation(string id);
|
||||||
|
//wiki: llResetScript()
|
||||||
|
void llResetScript();
|
||||||
|
//wiki: llMessageLinked(integer linknum, integer num, string str, key id)
|
||||||
|
void llMessageLinked(int linknum, int num, string str, string id);
|
||||||
|
//wiki: llPushObject(key target, vector impulse, vector ang_impulse, integer local)
|
||||||
|
void llPushObject(string target, LSL_Types.Vector3 impulse, LSL_Types.Vector3 ang_impulse, int local);
|
||||||
|
//wiki: llPassCollisions(integer pass)
|
||||||
|
void llPassCollisions(int pass);
|
||||||
|
//wiki: string llGetScriptName()
|
||||||
|
string llGetScriptName();
|
||||||
|
//wiki: integer llGetNumberOfSides()
|
||||||
|
LSL_Types.LSLInteger llGetNumberOfSides();
|
||||||
|
//wiki: rotation llAxisAngle2Rot(vector axis, double angle)
|
||||||
|
LSL_Types.Quaternion llAxisAngle2Rot(LSL_Types.Vector3 axis, double angle);
|
||||||
|
//wiki: vector llRot2Axis(rotation rot)
|
||||||
|
LSL_Types.Vector3 llRot2Axis(LSL_Types.Quaternion rot);
|
||||||
|
//wiki: double llRot2Angle(rotation rot);
|
||||||
|
double llRot2Angle(LSL_Types.Quaternion rot);
|
||||||
|
//wiki: double llAcos(double val)
|
||||||
|
double llAcos(double val);
|
||||||
|
//wiki: double llAsin(double val)
|
||||||
|
double llAsin(double val);
|
||||||
|
//wiki: double llAngleBetween(rotation a, rotation b)
|
||||||
|
double llAngleBetween(LSL_Types.Quaternion a, LSL_Types.Quaternion b);
|
||||||
|
//wiki: string llGetInventoryKey(string name)
|
||||||
|
string llGetInventoryKey(string name);
|
||||||
|
//wiki: llAllowInventoryDrop(integer add)
|
||||||
|
void llAllowInventoryDrop(int add);
|
||||||
|
//wiki: vector llGetSunDirection()
|
||||||
|
LSL_Types.Vector3 llGetSunDirection();
|
||||||
|
//wiki: vector llGetTextureOffset(integer face)
|
||||||
|
LSL_Types.Vector3 llGetTextureOffset(int face);
|
||||||
|
//wiki: vector llGetTextureScale(integer side)
|
||||||
|
LSL_Types.Vector3 llGetTextureScale(int side);
|
||||||
|
//wiki: double llGetTextureRot(integer side)
|
||||||
|
double llGetTextureRot(int side);
|
||||||
|
//wiki: integer llSubStringIndex(string source, string pattern)
|
||||||
|
LSL_Types.LSLInteger llSubStringIndex(string source, string pattern);
|
||||||
|
//wiki: key llGetOwnerKey(key id)
|
||||||
|
string llGetOwnerKey(string id);
|
||||||
|
//wiki: vector llGetCenterOfMass()
|
||||||
|
LSL_Types.Vector3 llGetCenterOfMass();
|
||||||
|
//wiki: list llListSort(list src, integer stride, integer ascending)
|
||||||
|
LSL_Types.list llListSort(LSL_Types.list src, int stride, int ascending);
|
||||||
|
//integer llGetListLength(list src)
|
||||||
|
LSL_Types.LSLInteger llGetListLength(LSL_Types.list src);
|
||||||
|
//wiki: integer llList2Integer(list src, integer index)
|
||||||
|
LSL_Types.LSLInteger llList2Integer(LSL_Types.list src, int index);
|
||||||
|
//wiki: double llList2double(list src, integer index)
|
||||||
|
double llList2Float(LSL_Types.list src, int index);
|
||||||
|
//wiki: string llList2String(list src, integer index)
|
||||||
|
string llList2String(LSL_Types.list src, int index);
|
||||||
|
//wiki: key llList2Key(list src, integer index)
|
||||||
|
string llList2Key(LSL_Types.list src, int index);
|
||||||
|
//wiki: vector llList2Vector(list src, integer index)
|
||||||
|
LSL_Types.Vector3 llList2Vector(LSL_Types.list src, int index);
|
||||||
|
//wiki rotation llList2Rot(list src, integer index)
|
||||||
|
LSL_Types.Quaternion llList2Rot(LSL_Types.list src, int index);
|
||||||
|
//wiki: list llList2List(list src, integer start, integer end)
|
||||||
|
LSL_Types.list llList2List(LSL_Types.list src, int start, int end);
|
||||||
|
//wiki: llDeleteSubList(list src, integer start, integer end)
|
||||||
|
LSL_Types.list llDeleteSubList(LSL_Types.list src, int start, int end);
|
||||||
|
//wiki: integer llGetListEntryType(list src, integer index)
|
||||||
|
LSL_Types.LSLInteger llGetListEntryType(LSL_Types.list src, int index);
|
||||||
|
//wiki: string llList2CSV(list src)
|
||||||
|
string llList2CSV(LSL_Types.list src);
|
||||||
|
//wiki: list llCSV2List(string src)
|
||||||
|
LSL_Types.list llCSV2List(string src);
|
||||||
|
//wiki: list llListRandomize(list src, integer stride)
|
||||||
|
LSL_Types.list llListRandomize(LSL_Types.list src, int stride);
|
||||||
|
//wiki: list llList2ListStrided(list src, integer start, integer end, integer stride)
|
||||||
|
LSL_Types.list llList2ListStrided(LSL_Types.list src, int start, int end, int stride);
|
||||||
|
//wiki: vector llGetRegionCorner()
|
||||||
|
LSL_Types.Vector3 llGetRegionCorner();
|
||||||
|
//wiki: list llListInsertList(list dest, list src, integer start)
|
||||||
|
LSL_Types.list llListInsertList(LSL_Types.list dest, LSL_Types.list src, int start);
|
||||||
|
//wiki: integer llListFindList(list src, list test)
|
||||||
|
LSL_Types.LSLInteger llListFindList(LSL_Types.list src, LSL_Types.list test);
|
||||||
|
//wiki: string llGetObjectName()
|
||||||
|
string llGetObjectName();
|
||||||
|
//wiki: llSetObjectName(string name)
|
||||||
|
void llSetObjectName(string name);
|
||||||
|
//wiki: string llGetDate()
|
||||||
|
string llGetDate();
|
||||||
|
//wiki: integer llEdgeOfWorld(vector pos, vector dir)
|
||||||
|
LSL_Types.LSLInteger llEdgeOfWorld(LSL_Types.Vector3 pos, LSL_Types.Vector3 dir);
|
||||||
|
//wiki: integer llGetAgentInfo(key id)
|
||||||
|
LSL_Types.LSLInteger llGetAgentInfo(string id);
|
||||||
|
//wiki: llAdjustSoundVolume(double volume)
|
||||||
|
void llAdjustSoundVolume(double volume);
|
||||||
|
//wiki: llSetSoundQueueing(integer queue)
|
||||||
|
void llSetSoundQueueing(int queue);
|
||||||
|
//wiki: llSetSoundRadius(double radius)
|
||||||
|
void llSetSoundRadius(double radius);
|
||||||
|
//wiki: string llKey2Name(key id)
|
||||||
|
string llKey2Name(string id);
|
||||||
|
//wiki: llSetTextureAnim(integer mode, integer face, integer sizex, integer sizey, double start, double length, double rate)
|
||||||
|
void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate);
|
||||||
|
//wiki: llTriggerSoundLimited(string sound, double volume, vector top_north_east, vector bottom_south_west)
|
||||||
|
void llTriggerSoundLimited(string sound, double volume, LSL_Types.Vector3 top_north_east,
|
||||||
|
LSL_Types.Vector3 bottom_south_west);
|
||||||
|
|
||||||
|
//wiki: llEjectFromLand(key pest)
|
||||||
|
void llEjectFromLand(string pest);
|
||||||
|
LSL_Types.list llParseString2List(string str, LSL_Types.list separators, LSL_Types.list spacers);
|
||||||
|
//wiki: integer llOverMyLand(key id)
|
||||||
|
LSL_Types.LSLInteger llOverMyLand(string id);
|
||||||
|
//wiki: key llGetLandOwnerAt(vector pos)
|
||||||
|
string llGetLandOwnerAt(LSL_Types.Vector3 pos);
|
||||||
|
//wiki: key llGetNotecardLine(string name, integer line)
|
||||||
|
string llGetNotecardLine(string name, int line);
|
||||||
|
//wiki: vector llGetAgentSize(key id)
|
||||||
|
LSL_Types.Vector3 llGetAgentSize(string id);
|
||||||
|
//wiki: integer llSameGroup(key agent)
|
||||||
|
LSL_Types.LSLInteger llSameGroup(string agent);
|
||||||
|
//wiki: llUnSit(key id)
|
||||||
|
void llUnSit(string id);
|
||||||
|
//wiki: vector llGroundSlope(vector offset)
|
||||||
|
LSL_Types.Vector3 llGroundSlope(LSL_Types.Vector3 offset);
|
||||||
|
//wiki: vector llGroundNormal(vector offset)
|
||||||
|
LSL_Types.Vector3 llGroundNormal(LSL_Types.Vector3 offset);
|
||||||
|
//wiki: vector llGroundContour(vector offset)
|
||||||
|
LSL_Types.Vector3 llGroundContour(LSL_Types.Vector3 offset);
|
||||||
|
//wiki: integer llGetAttached()
|
||||||
|
LSL_Types.LSLInteger llGetAttached();
|
||||||
|
//wiki: integer llGetFreeMemory()
|
||||||
|
LSL_Types.LSLInteger llGetFreeMemory();
|
||||||
|
//wiki: string llGetRegionName()
|
||||||
|
string llGetRegionName();
|
||||||
|
//wiki: double llGetRegionTimeDilation()
|
||||||
|
double llGetRegionTimeDilation();
|
||||||
|
//wiki: double llGetRegionFPS()
|
||||||
|
double llGetRegionFPS();
|
||||||
|
//wiki: llParticleSystem(List<Object> rules
|
||||||
|
void llParticleSystem(LSL_Types.list rules);
|
||||||
|
//wiki: llGroundRepel(double height, integer water, double tau)
|
||||||
|
void llGroundRepel(double height, int water, double tau);
|
||||||
|
//wiki: llGiveInventoryList(string destination, string category, LSL_Types.list inventory)
|
||||||
|
void llGiveInventoryList(string destination, string category, LSL_Types.list inventory);
|
||||||
|
//wiki: llSetVehicleType(integer type)
|
||||||
|
void llSetVehicleType(int type);
|
||||||
|
//wiki: llSetVehicledoubleParam(integer param, double value)
|
||||||
|
void llSetVehicledoubleParam(int param, double value);
|
||||||
|
// wiki: llSetVehicleFloatParam(integer param, float value)
|
||||||
|
void llSetVehicleFloatParam(int param, float value);
|
||||||
|
//wiki: llSetVehicleVectorParam(integer param, vector vec)
|
||||||
|
void llSetVehicleVectorParam(int param, LSL_Types.Vector3 vec);
|
||||||
|
//wiki: llSetVehicleRotationParam(integer param, rotation rot)
|
||||||
|
void llSetVehicleRotationParam(int param, LSL_Types.Quaternion rot);
|
||||||
|
//wiki: llSetVehicleFlags(integer flags)
|
||||||
|
void llSetVehicleFlags(int flags);
|
||||||
|
//wiki: llRemoveVehicleFlags(integer flags)
|
||||||
|
void llRemoveVehicleFlags(int flags);
|
||||||
|
//wiki: llSitTarget(vector offset, rotation rot)
|
||||||
|
void llSitTarget(LSL_Types.Vector3 offset, LSL_Types.Quaternion rot);
|
||||||
|
//wiki key llAvatarOnSitTarget()
|
||||||
|
string llAvatarOnSitTarget();
|
||||||
|
//wiki: llAddToLandPassList(key avatar, double hours)
|
||||||
|
void llAddToLandPassList(string avatar, double hours);
|
||||||
|
//wiki: llSetTouchText(string text)
|
||||||
|
void llSetTouchText(string text);
|
||||||
|
//wiki: llSetSitText(string text)
|
||||||
|
void llSetSitText(string text);
|
||||||
|
//wiki: llSetCameraEyeOffset(vector offset)
|
||||||
|
void llSetCameraEyeOffset(LSL_Types.Vector3 offset);
|
||||||
|
//wiki: llSeteCameraAtOffset(vector offset)
|
||||||
|
void llSetCameraAtOffset(LSL_Types.Vector3 offset);
|
||||||
|
//
|
||||||
|
string llDumpList2String(LSL_Types.list src, string seperator);
|
||||||
|
//wiki: integer llScriptDanger(vector pos)
|
||||||
|
LSL_Types.LSLInteger llScriptDanger(LSL_Types.Vector3 pos);
|
||||||
|
//wiki: llDialog(key avatar, string message, list buttons, integer chat_channel)
|
||||||
|
void llDialog(string avatar, string message, LSL_Types.list buttons, int chat_channel);
|
||||||
|
//wiki: llVolumeDetect(integer detect)
|
||||||
|
void llVolumeDetect(int detect);
|
||||||
|
//wiki: llResetOtherScript(string name)
|
||||||
|
void llResetOtherScript(string name);
|
||||||
|
//wiki: integer llGetScriptState(string name)
|
||||||
|
LSL_Types.LSLInteger llGetScriptState(string name);
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llRemoteLoadScript();
|
||||||
|
//wiki: llSetRemoteScriptAccessPin(integer pin)
|
||||||
|
void llSetRemoteScriptAccessPin(int pin);
|
||||||
|
//wiki: llRemoteLoadScriptPin(key target, string name, integer pin, integer running, integer start_param)
|
||||||
|
void llRemoteLoadScriptPin(string target, string name, int pin, int running, int start_param);
|
||||||
|
//wiki: llOpenRemoteDataChannel()
|
||||||
|
void llOpenRemoteDataChannel();
|
||||||
|
//wiki: key llSendRemoteData(key channel, string dest, integer idata, string sdata)
|
||||||
|
string llSendRemoteData(string channel, string dest, int idata, string sdata);
|
||||||
|
//wiki: llRemoteDataReply(key channel, key message_id, string sdata, integer idata)
|
||||||
|
void llRemoteDataReply(string channel, string message_id, string sdata, int idata);
|
||||||
|
//wiki: llCloseRemoteDataChannel(key channel)
|
||||||
|
void llCloseRemoteDataChannel(string channel);
|
||||||
|
//wiki: string llMD5String(string src, integer nonce)
|
||||||
|
string llMD5String(string src, int nonce);
|
||||||
|
//wiki: llSetPrimitiveParams(list rules)
|
||||||
|
void llSetPrimitiveParams(LSL_Types.list rules);
|
||||||
|
//wiki: llSetLinkPrimitiveParams(integer linknumber, list rules)
|
||||||
|
void llSetLinkPrimitiveParams(int linknumber, LSL_Types.list rules);
|
||||||
|
//wiki: string llStringToBase64(string str)
|
||||||
|
string llStringToBase64(string str);
|
||||||
|
//wiki: string llBase64ToString(string str)
|
||||||
|
string llBase64ToString(string str);
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llXorBase64Strings();
|
||||||
|
//wiki: llRemoteDataSetRegion()
|
||||||
|
void llRemoteDataSetRegion();
|
||||||
|
//wiki: double llLog10(double val)
|
||||||
|
double llLog10(double val);
|
||||||
|
//wiki: double llLog(double val)
|
||||||
|
double llLog(double val);
|
||||||
|
//wiki: list llGetAnimationList(key id)
|
||||||
|
LSL_Types.list llGetAnimationList(string id);
|
||||||
|
//wiki: llSetParcelMusicURL(string url)
|
||||||
|
void llSetParcelMusicURL(string url);
|
||||||
|
//wiki: vector llGetRootPosition()
|
||||||
|
LSL_Types.Vector3 llGetRootPosition();
|
||||||
|
//wiki: rotation llGetRootRotation()
|
||||||
|
LSL_Types.Quaternion llGetRootRotation();
|
||||||
|
//wiki: string llGetObjectDesc()
|
||||||
|
string llGetObjectDesc();
|
||||||
|
//wiki: llSetObjectDesc(string desc)
|
||||||
|
void llSetObjectDesc(string desc);
|
||||||
|
//wiki: key llGetCreator()
|
||||||
|
string llGetCreator();
|
||||||
|
//wiki: string llGetTimestamp()
|
||||||
|
string llGetTimestamp();
|
||||||
|
//wiki: llSetLinkAlpha(integer linknumber, double alpha, integer face)
|
||||||
|
void llSetLinkAlpha(int linknumber, double alpha, int face);
|
||||||
|
//wiki: integer llGetNumberOfPrims()
|
||||||
|
LSL_Types.LSLInteger llGetNumberOfPrims();
|
||||||
|
//wiki: key llGetNumberOfNotecardLines(string name)
|
||||||
|
string llGetNumberOfNotecardLines(string name);
|
||||||
|
//wiki: list llGetBoundingBox(key object)
|
||||||
|
LSL_Types.list llGetBoundingBox(string obj);
|
||||||
|
//wiki: vector llGetGeometricCenter()
|
||||||
|
LSL_Types.Vector3 llGetGeometricCenter();
|
||||||
|
//wiki: list llGetPrimitiveParams(list rules)
|
||||||
|
LSL_Types.list llGetPrimitiveParams(LSL_Types.list rules);
|
||||||
|
//wiki: string llIntegerToBase64(integer number)
|
||||||
|
string llIntegerToBase64(int number);
|
||||||
|
//wiki integer llBase64ToInteger(string str)
|
||||||
|
LSL_Types.LSLInteger llBase64ToInteger(string str);
|
||||||
|
//wiki: double llGetGMTclock()
|
||||||
|
double llGetGMTclock();
|
||||||
|
//wiki: string llGetSimulatorHostname()
|
||||||
|
string llGetSimulatorHostname();
|
||||||
|
//llSetLocalRot(rotation rot)
|
||||||
|
void llSetLocalRot(LSL_Types.Quaternion rot);
|
||||||
|
//wiki: list llParseStringKeepNulls(string src, list separators, list spacers)
|
||||||
|
LSL_Types.list llParseStringKeepNulls(string src, LSL_Types.list seperators, LSL_Types.list spacers);
|
||||||
|
//wiki: llRezAtRoot(string inventory, vector position, vector velocity, rotation rot, integer param)
|
||||||
|
void llRezAtRoot(string inventory, LSL_Types.Vector3 position, LSL_Types.Vector3 velocity,
|
||||||
|
LSL_Types.Quaternion rot, int param);
|
||||||
|
|
||||||
|
//wiki: integer llGetObjectPermMask(integer mask)
|
||||||
|
LSL_Types.LSLInteger llGetObjectPermMask(int mask);
|
||||||
|
//wiki: llSetObjectPermMask(integer mask, integer value)
|
||||||
|
void llSetObjectPermMask(int mask, int value);
|
||||||
|
//wiki integer llGetInventoryPermMask(string item, integer mask)
|
||||||
|
LSL_Types.LSLInteger llGetInventoryPermMask(string item, int mask);
|
||||||
|
//wiki: llSetInventoryPermMask(string item, integer mask, integer value)
|
||||||
|
void llSetInventoryPermMask(string item, int mask, int value);
|
||||||
|
//wiki: key llGetInventoryCreator(string item)
|
||||||
|
string llGetInventoryCreator(string item);
|
||||||
|
//wiki: llOwnerSay(string msg)
|
||||||
|
void llOwnerSay(string msg);
|
||||||
|
//wiki: key llRequestSimulatorData(string simulator, integer data)
|
||||||
|
string llRequestSimulatorData(string simulator, int data);
|
||||||
|
//wiki: llForceMouselook(integer mouselook)
|
||||||
|
void llForceMouselook(int mouselook);
|
||||||
|
//wiki: double llGetObjectMass(key id)
|
||||||
|
double llGetObjectMass(string id);
|
||||||
|
LSL_Types.list llListReplaceList(LSL_Types.list dest, LSL_Types.list src, int start, int end);
|
||||||
|
//wiki: llLoadURL(key avatar_id, string message, string url)
|
||||||
|
void llLoadURL(string avatar_id, string message, string url);
|
||||||
|
//wiki: llParcelMediaCommandList(list commandList)
|
||||||
|
void llParcelMediaCommandList(LSL_Types.list commandList);
|
||||||
|
void llParcelMediaQuery();
|
||||||
|
//wiki integer llModPow(integer a, integer b, integer c)
|
||||||
|
LSL_Types.LSLInteger llModPow(int a, int b, int c);
|
||||||
|
//wiki: integer llGetInventoryType(string name)
|
||||||
|
LSL_Types.LSLInteger llGetInventoryType(string name);
|
||||||
|
//wiki: llSetPayPrice(integer price, list quick_pay_buttons)
|
||||||
|
void llSetPayPrice(int price, LSL_Types.list quick_pay_buttons);
|
||||||
|
//wiki: vector llGetCameraPos()
|
||||||
|
LSL_Types.Vector3 llGetCameraPos();
|
||||||
|
//wiki rotation llGetCameraRot()
|
||||||
|
LSL_Types.Quaternion llGetCameraRot();
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llSetPrimURL();
|
||||||
|
//wiki: (deprecated)
|
||||||
|
void llRefreshPrimURL();
|
||||||
|
//wiki: string llEscapeURL(string url)
|
||||||
|
string llEscapeURL(string url);
|
||||||
|
//wiki: string llUnescapeURL(string url)
|
||||||
|
string llUnescapeURL(string url);
|
||||||
|
//wiki: llMapDestination(string simname, vector pos, vector look_at)
|
||||||
|
void llMapDestination(string simname, LSL_Types.Vector3 pos, LSL_Types.Vector3 look_at);
|
||||||
|
//wiki: llAddToLandBanList(key avatar, double hours)
|
||||||
|
void llAddToLandBanList(string avatar, double hours);
|
||||||
|
//wiki: llRemoveFromLandPassList(key avatar)
|
||||||
|
void llRemoveFromLandPassList(string avatar);
|
||||||
|
//wiki: llRemoveFromLandBanList(key avatar)
|
||||||
|
void llRemoveFromLandBanList(string avatar);
|
||||||
|
//wiki: llSetCameraParams(list rules)
|
||||||
|
void llSetCameraParams(LSL_Types.list rules);
|
||||||
|
//wiki: llClearCameraParams()
|
||||||
|
void llClearCameraParams();
|
||||||
|
//wiki: double llListStatistics(integer operation, list src)
|
||||||
|
double llListStatistics(int operation, LSL_Types.list src);
|
||||||
|
//wiki: integer llGetUnixTime()
|
||||||
|
LSL_Types.LSLInteger llGetUnixTime();
|
||||||
|
//wiki: integer llGetParcelFlags(vector pos)
|
||||||
|
LSL_Types.LSLInteger llGetParcelFlags(LSL_Types.Vector3 pos);
|
||||||
|
//wiki: integer llGetRegionFlags()
|
||||||
|
LSL_Types.LSLInteger llGetRegionFlags();
|
||||||
|
//wiki: string llXorBase64StringsCorrect(string str1, string str2)
|
||||||
|
string llXorBase64StringsCorrect(string str1, string str2);
|
||||||
|
string llHTTPRequest(string url, LSL_Types.list parameters, string body);
|
||||||
|
//wiki: llResetLandBanList()
|
||||||
|
void llResetLandBanList();
|
||||||
|
//wiki: llResetLandPassList()
|
||||||
|
void llResetLandPassList();
|
||||||
|
//wiki: integer llGetParcelPrimCount(vector pos, integer category, integer sim_wide)
|
||||||
|
LSL_Types.LSLInteger llGetParcelPrimCount(LSL_Types.Vector3 pos, int category, int sim_wide);
|
||||||
|
//wiki: list llGetParcelPrimOwners(vector pos)
|
||||||
|
LSL_Types.list llGetParcelPrimOwners(LSL_Types.Vector3 pos);
|
||||||
|
//wiki: integer llGetObjectPrimCount(key object_id)
|
||||||
|
LSL_Types.LSLInteger llGetObjectPrimCount(string object_id);
|
||||||
|
//wiki: integer llGetParcelMaxPrims(vector pos, integer sim_wide)
|
||||||
|
LSL_Types.LSLInteger llGetParcelMaxPrims(LSL_Types.Vector3 pos, int sim_wide);
|
||||||
|
//wiki: llGetParcelDetails(vector pos, list params)
|
||||||
|
LSL_Types.list llGetParcelDetails(LSL_Types.Vector3 pos, LSL_Types.list param);
|
||||||
|
//wiki: llSetLinkTexture(integer linknumber, string texture, integer face)
|
||||||
|
void llSetLinkTexture(int linknumber, string texture, int face);
|
||||||
|
//wiki: string llStringTrim(string src, int type)
|
||||||
|
string llStringTrim(string src, int type);
|
||||||
|
//wiki: LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args)
|
||||||
|
LSL_Types.list llGetObjectDetails(string id, LSL_Types.list args);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,68 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.Script
|
||||||
|
{
|
||||||
|
public interface IOSSL_ScriptCommands
|
||||||
|
{
|
||||||
|
//OpenSim functions
|
||||||
|
string osSetDynamicTextureURL(string dynamicID, string contentType, string url, string extraParams, int timer);
|
||||||
|
string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams,
|
||||||
|
int timer, int alpha);
|
||||||
|
string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer);
|
||||||
|
string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams,
|
||||||
|
int timer, int alpha);
|
||||||
|
double osTerrainGetHeight(int x, int y);
|
||||||
|
int osTerrainSetHeight(int x, int y, double val);
|
||||||
|
int osRegionRestart(double seconds);
|
||||||
|
void osRegionNotice(string msg);
|
||||||
|
bool osConsoleCommand(string Command);
|
||||||
|
void osSetParcelMediaURL(string url);
|
||||||
|
void osSetPrimFloatOnWater(int floatYN);
|
||||||
|
|
||||||
|
// Animation commands
|
||||||
|
void osAvatarPlayAnimation(string avatar, string animation);
|
||||||
|
void osAvatarStopAnimation(string avatar, string animation);
|
||||||
|
|
||||||
|
//texture draw functions
|
||||||
|
string osMovePen(string drawList, int x, int y);
|
||||||
|
string osDrawLine(string drawList, int startX, int startY, int endX, int endY);
|
||||||
|
string osDrawLine(string drawList, int endX, int endY);
|
||||||
|
string osDrawText(string drawList, string text);
|
||||||
|
string osDrawEllipse(string drawList, int width, int height);
|
||||||
|
string osDrawRectangle(string drawList, int width, int height);
|
||||||
|
string osDrawFilledRectangle(string drawList, int width, int height);
|
||||||
|
string osSetFontSize(string drawList, int fontSize);
|
||||||
|
string osSetPenSize(string drawList, int penSize);
|
||||||
|
string osSetPenColour(string drawList, string colour);
|
||||||
|
string osDrawImage(string drawList, int width, int height, string imageUrl);
|
||||||
|
void osSetStateEvents(int events);
|
||||||
|
|
||||||
|
double osList2Double(LSL_Types.list src, int index);
|
||||||
|
void osSetRegionWaterHeight(double height);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSim Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System.Reflection;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using OpenSim.Region.Environment.Interfaces;
|
||||||
|
|
||||||
|
namespace OpenSim.Region.ScriptEngine.XEngine.Script
|
||||||
|
{
|
||||||
|
public interface IScript
|
||||||
|
{
|
||||||
|
Type Start(ILSL_ScriptCommands lsl, IOSSL_ScriptCommands ossl);
|
||||||
|
|
||||||
|
Dictionary<string, object> GetVars();
|
||||||
|
void SetVars(Dictionary<string, object> vars);
|
||||||
|
void ResetVars();
|
||||||
|
|
||||||
|
string State { get; set; }
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
|
//
|
||||||
|
// General Information about an assembly is controlled through the following
|
||||||
|
// set of attributes. Change these attribute values to modify the information
|
||||||
|
// associated with an assembly.
|
||||||
|
//
|
||||||
|
[assembly: AssemblyTitle("")]
|
||||||
|
[assembly: AssemblyDescription("")]
|
||||||
|
[assembly: AssemblyConfiguration("")]
|
||||||
|
[assembly: AssemblyCompany("")]
|
||||||
|
[assembly: AssemblyProduct("")]
|
||||||
|
[assembly: AssemblyCopyright("")]
|
||||||
|
[assembly: AssemblyTrademark("")]
|
||||||
|
[assembly: AssemblyCulture("")]
|
||||||
|
[assembly: ComVisible(false)]
|
||||||
|
[assembly: CLSCompliant(true)]
|
||||||
|
|
||||||
|
//
|
||||||
|
// Version information for an assembly consists of the following four values:
|
||||||
|
//
|
||||||
|
// Major Version
|
||||||
|
// Minor Version
|
||||||
|
// Build Number
|
||||||
|
// Revision
|
||||||
|
//
|
||||||
|
// You can specify all the values or you can default the Revision and Build Numbers
|
||||||
|
// by using the '*' as shown below:
|
||||||
|
|
||||||
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
|
|
||||||
|
//
|
||||||
|
// In order to sign your assembly you must specify a key to use. Refer to the
|
||||||
|
// Microsoft .NET Framework documentation for more information on assembly signing.
|
||||||
|
//
|
||||||
|
// Use the attributes below to control which key is used for signing.
|
||||||
|
//
|
||||||
|
// Notes:
|
||||||
|
// (*) If no key is specified, the assembly is not signed.
|
||||||
|
// (*) KeyName refers to a key that has been installed in the Crypto Service
|
||||||
|
// Provider (CSP) on your machine. KeyFile refers to a file which contains
|
||||||
|
// a key.
|
||||||
|
// (*) If the KeyFile and the KeyName values are both specified, the
|
||||||
|
// following processing occurs:
|
||||||
|
// (1) If the KeyName can be found in the CSP, that key is used.
|
||||||
|
// (2) If the KeyName does not exist and the KeyFile does exist, the key
|
||||||
|
// in the KeyFile is installed into the CSP and used.
|
||||||
|
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
|
||||||
|
// When specifying the KeyFile, the location of the KeyFile should be
|
||||||
|
// relative to the project output directory which is
|
||||||
|
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
|
||||||
|
// located in the project directory, you would specify the AssemblyKeyFile
|
||||||
|
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
|
||||||
|
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
|
||||||
|
// documentation for more information on this.
|
||||||
|
//
|
||||||
|
[assembly: AssemblyDelaySign(false)]
|
||||||
|
[assembly: AssemblyKeyFile("")]
|
||||||
|
[assembly: AssemblyKeyName("")]
|
|
@ -0,0 +1,223 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Web;
|
||||||
|
using System.Runtime.Remoting.Messaging;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
#region CallerThreadContext class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class stores the caller call context in order to restore
|
||||||
|
/// it when the work item is executed in the thread pool environment.
|
||||||
|
/// </summary>
|
||||||
|
internal class CallerThreadContext
|
||||||
|
{
|
||||||
|
#region Prepare reflection information
|
||||||
|
|
||||||
|
// Cached type information.
|
||||||
|
private static MethodInfo getLogicalCallContextMethodInfo =
|
||||||
|
typeof(Thread).GetMethod("GetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
private static MethodInfo setLogicalCallContextMethodInfo =
|
||||||
|
typeof(Thread).GetMethod("SetLogicalCallContext", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
private static string HttpContextSlotName = GetHttpContextSlotName();
|
||||||
|
|
||||||
|
private static string GetHttpContextSlotName()
|
||||||
|
{
|
||||||
|
FieldInfo fi = typeof(HttpContext).GetField("CallContextSlotName", BindingFlags.Static | BindingFlags.NonPublic);
|
||||||
|
|
||||||
|
if( fi != null )
|
||||||
|
return (string)fi.GetValue(null);
|
||||||
|
else // Use the default "HttpContext" slot name
|
||||||
|
return "HttpContext";
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private fields
|
||||||
|
|
||||||
|
private HttpContext _httpContext = null;
|
||||||
|
private LogicalCallContext _callContext = null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
private CallerThreadContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CapturedCallContext
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (null != _callContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool CapturedHttpContext
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return (null != _httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures the current thread context
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static CallerThreadContext Capture(
|
||||||
|
bool captureCallContext,
|
||||||
|
bool captureHttpContext)
|
||||||
|
{
|
||||||
|
Debug.Assert(captureCallContext || captureHttpContext);
|
||||||
|
|
||||||
|
CallerThreadContext callerThreadContext = new CallerThreadContext();
|
||||||
|
|
||||||
|
// TODO: In NET 2.0, redo using the new feature of ExecutionContext class - Capture()
|
||||||
|
// Capture Call Context
|
||||||
|
if(captureCallContext && (getLogicalCallContextMethodInfo != null))
|
||||||
|
{
|
||||||
|
callerThreadContext._callContext = (LogicalCallContext)getLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, null);
|
||||||
|
if (callerThreadContext._callContext != null)
|
||||||
|
{
|
||||||
|
callerThreadContext._callContext = (LogicalCallContext)callerThreadContext._callContext.Clone();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Capture httpContext
|
||||||
|
if (captureHttpContext && (null != HttpContext.Current))
|
||||||
|
{
|
||||||
|
callerThreadContext._httpContext = HttpContext.Current;
|
||||||
|
}
|
||||||
|
|
||||||
|
return callerThreadContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the thread context stored earlier
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callerThreadContext"></param>
|
||||||
|
public static void Apply(CallerThreadContext callerThreadContext)
|
||||||
|
{
|
||||||
|
if (null == callerThreadContext)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("callerThreadContext");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Todo: In NET 2.0, redo using the new feature of ExecutionContext class - Run()
|
||||||
|
// Restore call context
|
||||||
|
if ((callerThreadContext._callContext != null) && (setLogicalCallContextMethodInfo != null))
|
||||||
|
{
|
||||||
|
setLogicalCallContextMethodInfo.Invoke(Thread.CurrentThread, new object[] { callerThreadContext._callContext });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Restore HttpContext
|
||||||
|
if (callerThreadContext._httpContext != null)
|
||||||
|
{
|
||||||
|
CallContext.SetData(HttpContextSlotName, callerThreadContext._httpContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.Security.Principal;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Runtime.Remoting.Contexts;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region CallerThreadContext class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This class stores the caller thread context in order to restore
|
||||||
|
/// it when the work item is executed in the context of the thread
|
||||||
|
/// from the pool.
|
||||||
|
/// Note that we can't store the thread's CompressedStack, because
|
||||||
|
/// it throws a security exception
|
||||||
|
/// </summary>
|
||||||
|
public class CallerThreadContext
|
||||||
|
{
|
||||||
|
private CultureInfo _culture = null;
|
||||||
|
private CultureInfo _cultureUI = null;
|
||||||
|
private IPrincipal _principal;
|
||||||
|
private System.Runtime.Remoting.Contexts.Context _context;
|
||||||
|
|
||||||
|
private static FieldInfo _fieldInfo = GetFieldInfo();
|
||||||
|
|
||||||
|
private static FieldInfo GetFieldInfo()
|
||||||
|
{
|
||||||
|
Type threadType = typeof(Thread);
|
||||||
|
return threadType.GetField(
|
||||||
|
"m_Context",
|
||||||
|
BindingFlags.Instance | BindingFlags.NonPublic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Constructor
|
||||||
|
/// </summary>
|
||||||
|
private CallerThreadContext()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Captures the current thread context
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static CallerThreadContext Capture()
|
||||||
|
{
|
||||||
|
CallerThreadContext callerThreadContext = new CallerThreadContext();
|
||||||
|
|
||||||
|
Thread thread = Thread.CurrentThread;
|
||||||
|
callerThreadContext._culture = thread.CurrentCulture;
|
||||||
|
callerThreadContext._cultureUI = thread.CurrentUICulture;
|
||||||
|
callerThreadContext._principal = Thread.CurrentPrincipal;
|
||||||
|
callerThreadContext._context = Thread.CurrentContext;
|
||||||
|
return callerThreadContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Applies the thread context stored earlier
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callerThreadContext"></param>
|
||||||
|
public static void Apply(CallerThreadContext callerThreadContext)
|
||||||
|
{
|
||||||
|
Thread thread = Thread.CurrentThread;
|
||||||
|
thread.CurrentCulture = callerThreadContext._culture;
|
||||||
|
thread.CurrentUICulture = callerThreadContext._cultureUI;
|
||||||
|
Thread.CurrentPrincipal = callerThreadContext._principal;
|
||||||
|
|
||||||
|
// Uncomment the following block to enable the Thread.CurrentThread
|
||||||
|
/*
|
||||||
|
if (null != _fieldInfo)
|
||||||
|
{
|
||||||
|
_fieldInfo.SetValue(
|
||||||
|
Thread.CurrentThread,
|
||||||
|
callerThreadContext._context);
|
||||||
|
}
|
||||||
|
* /
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
#region Exceptions
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been canceled
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public sealed class WorkItemCancelException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemCancelException() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemCancelException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemCancelException(string message, Exception e) : base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemCancelException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public sealed class WorkItemTimeoutException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemTimeoutException() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemTimeoutException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemTimeoutException(string message, Exception e) : base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemTimeoutException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Represents an exception in case IWorkItemResult.GetResult has been timed out
|
||||||
|
/// </summary>
|
||||||
|
[Serializable]
|
||||||
|
public sealed class WorkItemResultException : ApplicationException
|
||||||
|
{
|
||||||
|
public WorkItemResultException() : base()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemResultException(string message) : base(message)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemResultException(string message, Exception e) : base(message, e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemResultException(SerializationInfo si, StreamingContext sc) : base(si, sc)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,271 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
#region Delegates
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate that represents the method to run as the work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="state">A state object for the method to run</param>
|
||||||
|
public delegate object WorkItemCallback(object state);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate to call after the WorkItemCallback completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wir">The work item result object</param>
|
||||||
|
public delegate void PostExecuteWorkItemCallback(IWorkItemResult wir);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A delegate to call when a WorkItemsGroup becomes idle
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItemsGroup">A reference to the WorkItemsGroup that became idle</param>
|
||||||
|
public delegate void WorkItemsGroupIdleHandler(IWorkItemsGroup workItemsGroup);
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region WorkItem Priority
|
||||||
|
|
||||||
|
public enum WorkItemPriority
|
||||||
|
{
|
||||||
|
Lowest,
|
||||||
|
BelowNormal,
|
||||||
|
Normal,
|
||||||
|
AboveNormal,
|
||||||
|
Highest,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IHasWorkItemPriority interface
|
||||||
|
|
||||||
|
public interface IHasWorkItemPriority
|
||||||
|
{
|
||||||
|
WorkItemPriority WorkItemPriority { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IWorkItemsGroup interface
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IWorkItemsGroup interface
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkItemsGroup
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the name of the WorkItemsGroup
|
||||||
|
/// </summary>
|
||||||
|
string Name { get; set; }
|
||||||
|
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, WorkItemPriority workItemPriority);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, PostExecuteWorkItemCallback postExecuteWorkItemCallback, CallToPostExecute callToPostExecute, WorkItemPriority workItemPriority);
|
||||||
|
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback);
|
||||||
|
IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state);
|
||||||
|
|
||||||
|
void WaitForIdle();
|
||||||
|
bool WaitForIdle(TimeSpan timeout);
|
||||||
|
bool WaitForIdle(int millisecondsTimeout);
|
||||||
|
|
||||||
|
int WaitingCallbacks { get; }
|
||||||
|
event WorkItemsGroupIdleHandler OnIdle;
|
||||||
|
|
||||||
|
void Cancel();
|
||||||
|
void Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region CallToPostExecute enumerator
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum CallToPostExecute
|
||||||
|
{
|
||||||
|
Never = 0x00,
|
||||||
|
WhenWorkItemCanceled = 0x01,
|
||||||
|
WhenWorkItemNotCanceled = 0x02,
|
||||||
|
Always = WhenWorkItemCanceled | WhenWorkItemNotCanceled,
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IWorkItemResult interface
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IWorkItemResult interface
|
||||||
|
/// </summary>
|
||||||
|
public interface IWorkItemResult
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
object GetResult();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
object GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
object GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext);
|
||||||
|
|
||||||
|
void Abort();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
||||||
|
/// <param name="exitContext">
|
||||||
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
object GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
object GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
object GetResult(out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
object GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
object GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">Timeout in milliseconds, or -1 for infinite</param>
|
||||||
|
/// <param name="exitContext">
|
||||||
|
/// true to exit the synchronization domain for the context before the wait (if in a synchronized context), and reacquire it; otherwise, false.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="cancelWaitHandle">A cancel wait handle to interrupt the blocking if needed</param>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
object GetResult(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the result of the work item.
|
||||||
|
/// If the work item didn't run yet then the caller waits until timeout or until the cancelWaitHandle is signaled.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The result of the work item</returns>
|
||||||
|
/// <param name="e">Filled with the exception if one was thrown</param>
|
||||||
|
/// On timeout throws WorkItemTimeoutException
|
||||||
|
/// On cancel throws WorkItemCancelException
|
||||||
|
object GetResult(
|
||||||
|
TimeSpan timeout,
|
||||||
|
bool exitContext,
|
||||||
|
WaitHandle cancelWaitHandle,
|
||||||
|
out Exception e);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an indication whether the asynchronous operation has completed.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCompleted { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets an indication whether the asynchronous operation has been canceled.
|
||||||
|
/// </summary>
|
||||||
|
bool IsCanceled { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a user-defined object that qualifies or contains information about an asynchronous operation.
|
||||||
|
/// </summary>
|
||||||
|
object State { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cancel the work item if it didn't start running yet.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns true on success or false if the work item is in progress or already completed</returns>
|
||||||
|
bool Cancel();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the work item's priority
|
||||||
|
/// </summary>
|
||||||
|
WorkItemPriority WorkItemPriority { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Return the result, same as GetResult()
|
||||||
|
/// </summary>
|
||||||
|
object Result { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the exception if occured otherwise returns null.
|
||||||
|
/// </summary>
|
||||||
|
object Exception { get; }
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,240 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region PriorityQueue class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PriorityQueue class
|
||||||
|
/// This class is not thread safe because we use external lock
|
||||||
|
/// </summary>
|
||||||
|
public sealed class PriorityQueue : IEnumerable
|
||||||
|
{
|
||||||
|
#region Private members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of queues, there is one for each type of priority
|
||||||
|
/// </summary>
|
||||||
|
private const int _queuesCount = WorkItemPriority.Highest-WorkItemPriority.Lowest+1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Work items queues. There is one for each type of priority
|
||||||
|
/// </summary>
|
||||||
|
private Queue [] _queues = new Queue[_queuesCount];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The total number of work items within the queues
|
||||||
|
/// </summary>
|
||||||
|
private int _workItemsCount = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use with IEnumerable interface
|
||||||
|
/// </summary>
|
||||||
|
private int _version = 0;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Contructor
|
||||||
|
|
||||||
|
public PriorityQueue()
|
||||||
|
{
|
||||||
|
for(int i = 0; i < _queues.Length; ++i)
|
||||||
|
{
|
||||||
|
_queues[i] = new Queue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enqueue a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItem">A work item</param>
|
||||||
|
public void Enqueue(IHasWorkItemPriority workItem)
|
||||||
|
{
|
||||||
|
Debug.Assert(null != workItem);
|
||||||
|
|
||||||
|
int queueIndex = _queuesCount-(int)workItem.WorkItemPriority-1;
|
||||||
|
Debug.Assert(queueIndex >= 0);
|
||||||
|
Debug.Assert(queueIndex < _queuesCount);
|
||||||
|
|
||||||
|
_queues[queueIndex].Enqueue(workItem);
|
||||||
|
++_workItemsCount;
|
||||||
|
++_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dequeque a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the next work item</returns>
|
||||||
|
public IHasWorkItemPriority Dequeue()
|
||||||
|
{
|
||||||
|
IHasWorkItemPriority workItem = null;
|
||||||
|
|
||||||
|
if(_workItemsCount > 0)
|
||||||
|
{
|
||||||
|
int queueIndex = GetNextNonEmptyQueue(-1);
|
||||||
|
Debug.Assert(queueIndex >= 0);
|
||||||
|
workItem = _queues[queueIndex].Dequeue() as IHasWorkItemPriority;
|
||||||
|
Debug.Assert(null != workItem);
|
||||||
|
--_workItemsCount;
|
||||||
|
++_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find the next non empty queue starting at queue queueIndex+1
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="queueIndex">The index-1 to start from</param>
|
||||||
|
/// <returns>
|
||||||
|
/// The index of the next non empty queue or -1 if all the queues are empty
|
||||||
|
/// </returns>
|
||||||
|
private int GetNextNonEmptyQueue(int queueIndex)
|
||||||
|
{
|
||||||
|
for(int i = queueIndex+1; i < _queuesCount; ++i)
|
||||||
|
{
|
||||||
|
if(_queues[i].Count > 0)
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The number of work items
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _workItemsCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Clear all the work items
|
||||||
|
/// </summary>
|
||||||
|
public void Clear()
|
||||||
|
{
|
||||||
|
if (_workItemsCount > 0)
|
||||||
|
{
|
||||||
|
foreach(Queue queue in _queues)
|
||||||
|
{
|
||||||
|
queue.Clear();
|
||||||
|
}
|
||||||
|
_workItemsCount = 0;
|
||||||
|
++_version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IEnumerable Members
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an enumerator to iterate over the work items
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns an enumerator</returns>
|
||||||
|
public IEnumerator GetEnumerator()
|
||||||
|
{
|
||||||
|
return new PriorityQueueEnumerator(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region PriorityQueueEnumerator
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The class the implements the enumerator
|
||||||
|
/// </summary>
|
||||||
|
private class PriorityQueueEnumerator : IEnumerator
|
||||||
|
{
|
||||||
|
private PriorityQueue _priorityQueue;
|
||||||
|
private int _version;
|
||||||
|
private int _queueIndex;
|
||||||
|
private IEnumerator _enumerator;
|
||||||
|
|
||||||
|
public PriorityQueueEnumerator(PriorityQueue priorityQueue)
|
||||||
|
{
|
||||||
|
_priorityQueue = priorityQueue;
|
||||||
|
_version = _priorityQueue._version;
|
||||||
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
||||||
|
if (_queueIndex >= 0)
|
||||||
|
{
|
||||||
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_enumerator = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region IEnumerator Members
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_version = _priorityQueue._version;
|
||||||
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(-1);
|
||||||
|
if (_queueIndex >= 0)
|
||||||
|
{
|
||||||
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_enumerator = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Current
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
Debug.Assert(null != _enumerator);
|
||||||
|
return _enumerator.Current;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext()
|
||||||
|
{
|
||||||
|
if (null == _enumerator)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(_version != _priorityQueue._version)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The collection has been modified");
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!_enumerator.MoveNext())
|
||||||
|
{
|
||||||
|
_queueIndex = _priorityQueue.GetNextNonEmptyQueue(_queueIndex);
|
||||||
|
if(-1 == _queueIndex)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
_enumerator = _priorityQueue._queues[_queueIndex].GetEnumerator();
|
||||||
|
_enumerator.MoveNext();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,352 @@
|
||||||
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
internal enum STPPerformanceCounterType
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
ActiveThreads = 0,
|
||||||
|
InUseThreads = 1,
|
||||||
|
OverheadThreads = 2,
|
||||||
|
OverheadThreadsPercent = 3,
|
||||||
|
OverheadThreadsPercentBase = 4,
|
||||||
|
|
||||||
|
WorkItems = 5,
|
||||||
|
WorkItemsInQueue = 6,
|
||||||
|
WorkItemsProcessed = 7,
|
||||||
|
|
||||||
|
WorkItemsQueuedPerSecond = 8,
|
||||||
|
WorkItemsProcessedPerSecond = 9,
|
||||||
|
|
||||||
|
AvgWorkItemWaitTime = 10,
|
||||||
|
AvgWorkItemWaitTimeBase = 11,
|
||||||
|
|
||||||
|
AvgWorkItemProcessTime = 12,
|
||||||
|
AvgWorkItemProcessTimeBase = 13,
|
||||||
|
|
||||||
|
WorkItemsGroups = 14,
|
||||||
|
|
||||||
|
LastCounter = 14,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for STPPerformanceCounter.
|
||||||
|
/// </summary>
|
||||||
|
internal class STPPerformanceCounter
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private PerformanceCounterType _pcType;
|
||||||
|
protected string _counterHelp;
|
||||||
|
protected string _counterName;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
public STPPerformanceCounter(
|
||||||
|
string counterName,
|
||||||
|
string counterHelp,
|
||||||
|
PerformanceCounterType pcType)
|
||||||
|
{
|
||||||
|
this._counterName = counterName;
|
||||||
|
this._counterHelp = counterHelp;
|
||||||
|
this._pcType = pcType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCounterToCollection(CounterCreationDataCollection counterData)
|
||||||
|
{
|
||||||
|
CounterCreationData counterCreationData = new CounterCreationData(
|
||||||
|
_counterName,
|
||||||
|
_counterHelp,
|
||||||
|
_pcType);
|
||||||
|
|
||||||
|
counterData.Add(counterCreationData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _counterName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class STPPerformanceCounters
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
internal STPPerformanceCounter[] _stpPerformanceCounters;
|
||||||
|
private static STPPerformanceCounters _instance;
|
||||||
|
internal const string _stpCategoryHelp = "SmartThreadPool performance counters";
|
||||||
|
internal const string _stpCategoryName = "SmartThreadPool";
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
static STPPerformanceCounters()
|
||||||
|
{
|
||||||
|
_instance = new STPPerformanceCounters();
|
||||||
|
}
|
||||||
|
|
||||||
|
private STPPerformanceCounters()
|
||||||
|
{
|
||||||
|
STPPerformanceCounter[] stpPerformanceCounters = new STPPerformanceCounter[]
|
||||||
|
{
|
||||||
|
new STPPerformanceCounter("Active threads", "The current number of available in the thread pool.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("In use threads", "The current number of threads that execute a work item.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("Overhead threads", "The current number of threads that are active, but are not in use.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("% overhead threads", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawFraction),
|
||||||
|
new STPPerformanceCounter("% overhead threads base", "The current number of threads that are active, but are not in use in percents.", PerformanceCounterType.RawBase),
|
||||||
|
|
||||||
|
new STPPerformanceCounter("Work Items", "The number of work items in the Smart Thread Pool. Both queued and processed.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("Work Items in queue", "The current number of work items in the queue", PerformanceCounterType.NumberOfItems32),
|
||||||
|
new STPPerformanceCounter("Work Items processed", "The number of work items already processed", PerformanceCounterType.NumberOfItems32),
|
||||||
|
|
||||||
|
new STPPerformanceCounter("Work Items queued/sec", "The number of work items queued per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
||||||
|
new STPPerformanceCounter("Work Items processed/sec", "The number of work items processed per second", PerformanceCounterType.RateOfCountsPerSecond32),
|
||||||
|
|
||||||
|
new STPPerformanceCounter("Avg. Work Item wait time/sec", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageCount64),
|
||||||
|
new STPPerformanceCounter("Avg. Work Item wait time base", "The average time a work item supends in the queue waiting for its turn to execute.", PerformanceCounterType.AverageBase),
|
||||||
|
|
||||||
|
new STPPerformanceCounter("Avg. Work Item process time/sec", "The average time it takes to process a work item.", PerformanceCounterType.AverageCount64),
|
||||||
|
new STPPerformanceCounter("Avg. Work Item process time base", "The average time it takes to process a work item.", PerformanceCounterType.AverageBase),
|
||||||
|
|
||||||
|
new STPPerformanceCounter("Work Items Groups", "The current number of work item groups associated with the Smart Thread Pool.", PerformanceCounterType.NumberOfItems32),
|
||||||
|
};
|
||||||
|
|
||||||
|
_stpPerformanceCounters = stpPerformanceCounters;
|
||||||
|
SetupCategory();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SetupCategory()
|
||||||
|
{
|
||||||
|
if (!PerformanceCounterCategory.Exists(_stpCategoryName))
|
||||||
|
{
|
||||||
|
CounterCreationDataCollection counters = new CounterCreationDataCollection();
|
||||||
|
|
||||||
|
for (int i = 0; i < _stpPerformanceCounters.Length; i++)
|
||||||
|
{
|
||||||
|
_stpPerformanceCounters[i].AddCounterToCollection(counters);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// *********** Remark for .NET 2.0 ***********
|
||||||
|
// If you are here, it means you got the warning that this overload
|
||||||
|
// of the method is deprecated in .NET 2.0. To use the correct
|
||||||
|
// method overload, uncomment the third argument of the method.
|
||||||
|
PerformanceCounterCategory.Create(
|
||||||
|
_stpCategoryName,
|
||||||
|
_stpCategoryHelp,
|
||||||
|
//PerformanceCounterCategoryType.MultiInstance,
|
||||||
|
counters);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Properties
|
||||||
|
public static STPPerformanceCounters Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class STPInstancePerformanceCounter : IDisposable
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private PerformanceCounter _pcs;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
protected STPInstancePerformanceCounter()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public STPInstancePerformanceCounter(
|
||||||
|
string instance,
|
||||||
|
STPPerformanceCounterType spcType)
|
||||||
|
{
|
||||||
|
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
||||||
|
_pcs = new PerformanceCounter(
|
||||||
|
STPPerformanceCounters._stpCategoryName,
|
||||||
|
counters._stpPerformanceCounters[(int) spcType].Name,
|
||||||
|
instance,
|
||||||
|
false);
|
||||||
|
_pcs.RawValue = _pcs.RawValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
~STPInstancePerformanceCounter()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (_pcs != null)
|
||||||
|
{
|
||||||
|
_pcs.RemoveInstance();
|
||||||
|
_pcs.Close();
|
||||||
|
_pcs = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Increment()
|
||||||
|
{
|
||||||
|
_pcs.Increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void IncrementBy(long val)
|
||||||
|
{
|
||||||
|
_pcs.IncrementBy(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
public virtual void Set(long val)
|
||||||
|
{
|
||||||
|
_pcs.RawValue = val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class STPInstanceNullPerformanceCounter : STPInstancePerformanceCounter
|
||||||
|
{
|
||||||
|
// Methods
|
||||||
|
public STPInstanceNullPerformanceCounter() {}
|
||||||
|
public override void Increment() {}
|
||||||
|
public override void IncrementBy(long value) {}
|
||||||
|
public override void Set(long val) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal interface ISTPInstancePerformanceCounters : IDisposable
|
||||||
|
{
|
||||||
|
void Close();
|
||||||
|
void SampleThreads(long activeThreads, long inUseThreads);
|
||||||
|
void SampleWorkItems(long workItemsQueued, long workItemsProcessed);
|
||||||
|
void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime);
|
||||||
|
void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
internal class STPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
||||||
|
{
|
||||||
|
// Fields
|
||||||
|
private STPInstancePerformanceCounter[] _pcs;
|
||||||
|
private static STPInstancePerformanceCounter _stpInstanceNullPerformanceCounter;
|
||||||
|
|
||||||
|
// Methods
|
||||||
|
static STPInstancePerformanceCounters()
|
||||||
|
{
|
||||||
|
_stpInstanceNullPerformanceCounter = new STPInstanceNullPerformanceCounter();
|
||||||
|
}
|
||||||
|
|
||||||
|
public STPInstancePerformanceCounters(string instance)
|
||||||
|
{
|
||||||
|
_pcs = new STPInstancePerformanceCounter[(int)STPPerformanceCounterType.LastCounter];
|
||||||
|
STPPerformanceCounters counters = STPPerformanceCounters.Instance;
|
||||||
|
for (int i = 0; i < _pcs.Length; i++)
|
||||||
|
{
|
||||||
|
if (instance != null)
|
||||||
|
{
|
||||||
|
_pcs[i] = new STPInstancePerformanceCounter(
|
||||||
|
instance,
|
||||||
|
(STPPerformanceCounterType) i);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_pcs[i] = _stpInstanceNullPerformanceCounter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (null != _pcs)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < _pcs.Length; i++)
|
||||||
|
{
|
||||||
|
if (null != _pcs[i])
|
||||||
|
{
|
||||||
|
_pcs[i].Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_pcs = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~STPInstancePerformanceCounters()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private STPInstancePerformanceCounter GetCounter(STPPerformanceCounterType spcType)
|
||||||
|
{
|
||||||
|
return _pcs[(int) spcType];
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleThreads(long activeThreads, long inUseThreads)
|
||||||
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.ActiveThreads).Set(activeThreads);
|
||||||
|
GetCounter(STPPerformanceCounterType.InUseThreads).Set(inUseThreads);
|
||||||
|
GetCounter(STPPerformanceCounterType.OverheadThreads).Set(activeThreads-inUseThreads);
|
||||||
|
|
||||||
|
GetCounter(STPPerformanceCounterType.OverheadThreadsPercentBase).Set(activeThreads-inUseThreads);
|
||||||
|
GetCounter(STPPerformanceCounterType.OverheadThreadsPercent).Set(inUseThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed)
|
||||||
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItems).Set(workItemsQueued+workItemsProcessed);
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItemsInQueue).Set(workItemsQueued);
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItemsProcessed).Set(workItemsProcessed);
|
||||||
|
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItemsQueuedPerSecond).Set(workItemsQueued);
|
||||||
|
GetCounter(STPPerformanceCounterType.WorkItemsProcessedPerSecond).Set(workItemsProcessed);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime)
|
||||||
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTime).IncrementBy((long)workItemWaitTime.TotalMilliseconds);
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemWaitTimeBase).Increment();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime)
|
||||||
|
{
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTime).IncrementBy((long)workItemProcessTime.TotalMilliseconds);
|
||||||
|
GetCounter(STPPerformanceCounterType.AvgWorkItemProcessTimeBase).Increment();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class NullSTPInstancePerformanceCounters : ISTPInstancePerformanceCounters, IDisposable
|
||||||
|
{
|
||||||
|
static NullSTPInstancePerformanceCounters()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static NullSTPInstancePerformanceCounters _instance = new NullSTPInstancePerformanceCounters(null);
|
||||||
|
|
||||||
|
public static NullSTPInstancePerformanceCounters Instance
|
||||||
|
{
|
||||||
|
get { return _instance; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public NullSTPInstancePerformanceCounters(string instance) {}
|
||||||
|
public void Close() {}
|
||||||
|
public void Dispose() {}
|
||||||
|
|
||||||
|
public void SampleThreads(long activeThreads, long inUseThreads) {}
|
||||||
|
public void SampleWorkItems(long workItemsQueued, long workItemsProcessed) {}
|
||||||
|
public void SampleWorkItemsWaitTime(TimeSpan workItemWaitTime) {}
|
||||||
|
public void SampleWorkItemsProcessTime(TimeSpan workItemProcessTime) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for STPStartInfo.
|
||||||
|
/// </summary>
|
||||||
|
public class STPStartInfo : WIGStartInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Idle timeout in milliseconds.
|
||||||
|
/// If a thread is idle for _idleTimeout milliseconds then
|
||||||
|
/// it may quit.
|
||||||
|
/// </summary>
|
||||||
|
private int _idleTimeout;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The lower limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
private int _minWorkerThreads;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The upper limit of threads in the pool.
|
||||||
|
/// </summary>
|
||||||
|
private int _maxWorkerThreads;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The priority of the threads in the pool
|
||||||
|
/// </summary>
|
||||||
|
private ThreadPriority _threadPriority;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// If this field is not null then the performance counters are enabled
|
||||||
|
/// and use the string as the name of the instance.
|
||||||
|
/// </summary>
|
||||||
|
private string _pcInstanceName;
|
||||||
|
|
||||||
|
private int _stackSize;
|
||||||
|
|
||||||
|
public STPStartInfo() : base()
|
||||||
|
{
|
||||||
|
_idleTimeout = SmartThreadPool.DefaultIdleTimeout;
|
||||||
|
_minWorkerThreads = SmartThreadPool.DefaultMinWorkerThreads;
|
||||||
|
_maxWorkerThreads = SmartThreadPool.DefaultMaxWorkerThreads;
|
||||||
|
_threadPriority = SmartThreadPool.DefaultThreadPriority;
|
||||||
|
_pcInstanceName = SmartThreadPool.DefaultPerformanceCounterInstanceName;
|
||||||
|
_stackSize = SmartThreadPool.DefaultStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public STPStartInfo(STPStartInfo stpStartInfo) : base(stpStartInfo)
|
||||||
|
{
|
||||||
|
_idleTimeout = stpStartInfo._idleTimeout;
|
||||||
|
_minWorkerThreads = stpStartInfo._minWorkerThreads;
|
||||||
|
_maxWorkerThreads = stpStartInfo._maxWorkerThreads;
|
||||||
|
_threadPriority = stpStartInfo._threadPriority;
|
||||||
|
_pcInstanceName = stpStartInfo._pcInstanceName;
|
||||||
|
_stackSize = stpStartInfo._stackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int IdleTimeout
|
||||||
|
{
|
||||||
|
get { return _idleTimeout; }
|
||||||
|
set { _idleTimeout = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MinWorkerThreads
|
||||||
|
{
|
||||||
|
get { return _minWorkerThreads; }
|
||||||
|
set { _minWorkerThreads = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int MaxWorkerThreads
|
||||||
|
{
|
||||||
|
get { return _maxWorkerThreads; }
|
||||||
|
set { _maxWorkerThreads = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public ThreadPriority ThreadPriority
|
||||||
|
{
|
||||||
|
get { return _threadPriority; }
|
||||||
|
set { _threadPriority = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public string PerformanceCounterInstanceName
|
||||||
|
{
|
||||||
|
get { return _pcInstanceName; }
|
||||||
|
set { _pcInstanceName = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public int StackSize
|
||||||
|
{
|
||||||
|
get { return _stackSize; }
|
||||||
|
set { _stackSize = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for WIGStartInfo.
|
||||||
|
/// </summary>
|
||||||
|
public class WIGStartInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
private bool _useCallerCallContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the caller's HTTP context
|
||||||
|
/// </summary>
|
||||||
|
private bool _useCallerHttpContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
|
private bool _disposeOfStateObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The option to run the post execute
|
||||||
|
/// </summary>
|
||||||
|
private CallToPostExecute _callToPostExecute;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A post execute callback to call when none is provided in
|
||||||
|
/// the QueueWorkItem method.
|
||||||
|
/// </summary>
|
||||||
|
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate the WorkItemsGroup to suspend the handling of the work items
|
||||||
|
/// until the Start() method is called.
|
||||||
|
/// </summary>
|
||||||
|
private bool _startSuspended;
|
||||||
|
|
||||||
|
public WIGStartInfo()
|
||||||
|
{
|
||||||
|
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
||||||
|
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
||||||
|
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
||||||
|
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
||||||
|
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
||||||
|
_startSuspended = SmartThreadPool.DefaultStartSuspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WIGStartInfo(WIGStartInfo wigStartInfo)
|
||||||
|
{
|
||||||
|
_useCallerCallContext = wigStartInfo._useCallerCallContext;
|
||||||
|
_useCallerHttpContext = wigStartInfo._useCallerHttpContext;
|
||||||
|
_disposeOfStateObjects = wigStartInfo._disposeOfStateObjects;
|
||||||
|
_callToPostExecute = wigStartInfo._callToPostExecute;
|
||||||
|
_postExecuteWorkItemCallback = wigStartInfo._postExecuteWorkItemCallback;
|
||||||
|
_startSuspended = wigStartInfo._startSuspended;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseCallerCallContext
|
||||||
|
{
|
||||||
|
get { return _useCallerCallContext; }
|
||||||
|
set { _useCallerCallContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseCallerHttpContext
|
||||||
|
{
|
||||||
|
get { return _useCallerHttpContext; }
|
||||||
|
set { _useCallerHttpContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DisposeOfStateObjects
|
||||||
|
{
|
||||||
|
get { return _disposeOfStateObjects; }
|
||||||
|
set { _disposeOfStateObjects = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallToPostExecute CallToPostExecute
|
||||||
|
{
|
||||||
|
get { return _callToPostExecute; }
|
||||||
|
set { _callToPostExecute = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
|
{
|
||||||
|
get { return _postExecuteWorkItemCallback; }
|
||||||
|
set { _postExecuteWorkItemCallback = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool StartSuspended
|
||||||
|
{
|
||||||
|
get { return _startSuspended; }
|
||||||
|
set { _startSuspended = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,333 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region WorkItemFactory class
|
||||||
|
|
||||||
|
public class WorkItemFactory
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="workItemPriority">The priority of the work item</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
return CreateWorkItem(workItemsGroup, wigStartInfo, callback, null, workItemPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemInfo workItemInfo,
|
||||||
|
WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
return CreateWorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
wigStartInfo,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = wigStartInfo.PostExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemInfo workItemInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(workItemInfo.PostExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
new WorkItemInfo(workItemInfo),
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = wigStartInfo.CallToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute)
|
||||||
|
{
|
||||||
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = callToPostExecute;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wigStartInfo">Work item group start information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item</returns>
|
||||||
|
public static WorkItem CreateWorkItem(
|
||||||
|
IWorkItemsGroup workItemsGroup,
|
||||||
|
WIGStartInfo wigStartInfo,
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
|
||||||
|
ValidateCallback(callback);
|
||||||
|
ValidateCallback(postExecuteWorkItemCallback);
|
||||||
|
|
||||||
|
WorkItemInfo workItemInfo = new WorkItemInfo();
|
||||||
|
workItemInfo.UseCallerCallContext = wigStartInfo.UseCallerCallContext;
|
||||||
|
workItemInfo.UseCallerHttpContext = wigStartInfo.UseCallerHttpContext;
|
||||||
|
workItemInfo.PostExecuteWorkItemCallback = postExecuteWorkItemCallback;
|
||||||
|
workItemInfo.CallToPostExecute = callToPostExecute;
|
||||||
|
workItemInfo.WorkItemPriority = workItemPriority;
|
||||||
|
workItemInfo.DisposeOfStateObjects = wigStartInfo.DisposeOfStateObjects;
|
||||||
|
|
||||||
|
WorkItem workItem = new WorkItem(
|
||||||
|
workItemsGroup,
|
||||||
|
workItemInfo,
|
||||||
|
callback,
|
||||||
|
state);
|
||||||
|
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void ValidateCallback(Delegate callback)
|
||||||
|
{
|
||||||
|
if(callback.GetInvocationList().Length > 1)
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("SmartThreadPool doesn't support delegates chains");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
namespace Amib.Threading
|
||||||
|
{
|
||||||
|
#region WorkItemInfo class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for WorkItemInfo.
|
||||||
|
/// </summary>
|
||||||
|
public class WorkItemInfo
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
private bool _useCallerCallContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the caller's security context
|
||||||
|
/// </summary>
|
||||||
|
private bool _useCallerHttpContext;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Dispose of the state object of a work item
|
||||||
|
/// </summary>
|
||||||
|
private bool _disposeOfStateObjects;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The option to run the post execute
|
||||||
|
/// </summary>
|
||||||
|
private CallToPostExecute _callToPostExecute;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A post execute callback to call when none is provided in
|
||||||
|
/// the QueueWorkItem method.
|
||||||
|
/// </summary>
|
||||||
|
private PostExecuteWorkItemCallback _postExecuteWorkItemCallback;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The priority of the work item
|
||||||
|
/// </summary>
|
||||||
|
private WorkItemPriority _workItemPriority;
|
||||||
|
|
||||||
|
public WorkItemInfo()
|
||||||
|
{
|
||||||
|
_useCallerCallContext = SmartThreadPool.DefaultUseCallerCallContext;
|
||||||
|
_useCallerHttpContext = SmartThreadPool.DefaultUseCallerHttpContext;
|
||||||
|
_disposeOfStateObjects = SmartThreadPool.DefaultDisposeOfStateObjects;
|
||||||
|
_callToPostExecute = SmartThreadPool.DefaultCallToPostExecute;
|
||||||
|
_postExecuteWorkItemCallback = SmartThreadPool.DefaultPostExecuteWorkItemCallback;
|
||||||
|
_workItemPriority = SmartThreadPool.DefaultWorkItemPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemInfo(WorkItemInfo workItemInfo)
|
||||||
|
{
|
||||||
|
_useCallerCallContext = workItemInfo._useCallerCallContext;
|
||||||
|
_useCallerHttpContext = workItemInfo._useCallerHttpContext;
|
||||||
|
_disposeOfStateObjects = workItemInfo._disposeOfStateObjects;
|
||||||
|
_callToPostExecute = workItemInfo._callToPostExecute;
|
||||||
|
_postExecuteWorkItemCallback = workItemInfo._postExecuteWorkItemCallback;
|
||||||
|
_workItemPriority = workItemInfo._workItemPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseCallerCallContext
|
||||||
|
{
|
||||||
|
get { return _useCallerCallContext; }
|
||||||
|
set { _useCallerCallContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool UseCallerHttpContext
|
||||||
|
{
|
||||||
|
get { return _useCallerHttpContext; }
|
||||||
|
set { _useCallerHttpContext = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool DisposeOfStateObjects
|
||||||
|
{
|
||||||
|
get { return _disposeOfStateObjects; }
|
||||||
|
set { _disposeOfStateObjects = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public CallToPostExecute CallToPostExecute
|
||||||
|
{
|
||||||
|
get { return _callToPostExecute; }
|
||||||
|
set { _callToPostExecute = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public PostExecuteWorkItemCallback PostExecuteWorkItemCallback
|
||||||
|
{
|
||||||
|
get { return _postExecuteWorkItemCallback; }
|
||||||
|
set { _postExecuteWorkItemCallback = value; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItemPriority WorkItemPriority
|
||||||
|
{
|
||||||
|
get { return _workItemPriority; }
|
||||||
|
set { _workItemPriority = value; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,512 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region WorkItemsGroup class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Summary description for WorkItemsGroup.
|
||||||
|
/// </summary>
|
||||||
|
public class WorkItemsGroup : IWorkItemsGroup
|
||||||
|
{
|
||||||
|
#region Private members
|
||||||
|
|
||||||
|
private object _lock = new object();
|
||||||
|
/// <summary>
|
||||||
|
/// Contains the name of this instance of SmartThreadPool.
|
||||||
|
/// Can be changed by the user.
|
||||||
|
/// </summary>
|
||||||
|
private string _name = "WorkItemsGroup";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A reference to the SmartThreadPool instance that created this
|
||||||
|
/// WorkItemsGroup.
|
||||||
|
/// </summary>
|
||||||
|
private SmartThreadPool _stp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The OnIdle event
|
||||||
|
/// </summary>
|
||||||
|
private event WorkItemsGroupIdleHandler _onIdle;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines how many work items of this WorkItemsGroup can run at once.
|
||||||
|
/// </summary>
|
||||||
|
private int _concurrency;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Priority queue to hold work items before they are passed
|
||||||
|
/// to the SmartThreadPool.
|
||||||
|
/// </summary>
|
||||||
|
private PriorityQueue _workItemsQueue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate how many work items are waiting in the SmartThreadPool
|
||||||
|
/// queue.
|
||||||
|
/// This value is used to apply the concurrency.
|
||||||
|
/// </summary>
|
||||||
|
private int _workItemsInStpQueue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate how many work items are currently running in the SmartThreadPool.
|
||||||
|
/// This value is used with the Cancel, to calculate if we can send new
|
||||||
|
/// work items to the STP.
|
||||||
|
/// </summary>
|
||||||
|
private int _workItemsExecutingInStp = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WorkItemsGroup start information
|
||||||
|
/// </summary>
|
||||||
|
private WIGStartInfo _workItemsGroupStartInfo;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signaled when all of the WorkItemsGroup's work item completed.
|
||||||
|
/// </summary>
|
||||||
|
private ManualResetEvent _isIdleWaitHandle = new ManualResetEvent(true);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A common object for all the work items that this work items group
|
||||||
|
/// generate so we can mark them to cancel in O(1)
|
||||||
|
/// </summary>
|
||||||
|
private CanceledWorkItemsGroup _canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Construction
|
||||||
|
|
||||||
|
public WorkItemsGroup(
|
||||||
|
SmartThreadPool stp,
|
||||||
|
int concurrency,
|
||||||
|
WIGStartInfo wigStartInfo)
|
||||||
|
{
|
||||||
|
if (concurrency <= 0)
|
||||||
|
{
|
||||||
|
throw new ArgumentOutOfRangeException("concurrency", concurrency, "concurrency must be greater than zero");
|
||||||
|
}
|
||||||
|
_stp = stp;
|
||||||
|
_concurrency = concurrency;
|
||||||
|
_workItemsGroupStartInfo = new WIGStartInfo(wigStartInfo);
|
||||||
|
_workItemsQueue = new PriorityQueue();
|
||||||
|
|
||||||
|
// The _workItemsInStpQueue gets the number of currently executing work items,
|
||||||
|
// because once a work item is executing, it cannot be cancelled.
|
||||||
|
_workItemsInStpQueue = _workItemsExecutingInStp;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IWorkItemsGroup implementation
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get/Set the name of the SmartThreadPool instance
|
||||||
|
/// </summary>
|
||||||
|
public string Name
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _name;
|
||||||
|
}
|
||||||
|
|
||||||
|
set
|
||||||
|
{
|
||||||
|
_name = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="workItemPriority">The priority of the work item</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, workItemPriority);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItemInfo">Work item info</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemCallback callback, object state, WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, workItemPriority);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="workItemInfo">Work item information</param>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(WorkItemInfo workItemInfo, WorkItemCallback callback, object state)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, workItemInfo, callback, state);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, workItemPriority);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queue a work item
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="callback">A callback to execute</param>
|
||||||
|
/// <param name="state">
|
||||||
|
/// The context object of the work item. Used for passing arguments to the work item.
|
||||||
|
/// </param>
|
||||||
|
/// <param name="postExecuteWorkItemCallback">
|
||||||
|
/// A delegate to call after the callback completion
|
||||||
|
/// </param>
|
||||||
|
/// <param name="callToPostExecute">Indicates on which cases to call to the post execute callback</param>
|
||||||
|
/// <param name="workItemPriority">The work item priority</param>
|
||||||
|
/// <returns>Returns a work item result</returns>
|
||||||
|
public IWorkItemResult QueueWorkItem(
|
||||||
|
WorkItemCallback callback,
|
||||||
|
object state,
|
||||||
|
PostExecuteWorkItemCallback postExecuteWorkItemCallback,
|
||||||
|
CallToPostExecute callToPostExecute,
|
||||||
|
WorkItemPriority workItemPriority)
|
||||||
|
{
|
||||||
|
WorkItem workItem = WorkItemFactory.CreateWorkItem(this, _workItemsGroupStartInfo, callback, state, postExecuteWorkItemCallback, callToPostExecute, workItemPriority);
|
||||||
|
EnqueueToSTPNextWorkItem(workItem);
|
||||||
|
return workItem.GetWorkItemResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for the thread pool to be idle
|
||||||
|
/// </summary>
|
||||||
|
public void WaitForIdle()
|
||||||
|
{
|
||||||
|
WaitForIdle(Timeout.Infinite);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for the thread pool to be idle
|
||||||
|
/// </summary>
|
||||||
|
public bool WaitForIdle(TimeSpan timeout)
|
||||||
|
{
|
||||||
|
return WaitForIdle((int)timeout.TotalMilliseconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Wait for the thread pool to be idle
|
||||||
|
/// </summary>
|
||||||
|
public bool WaitForIdle(int millisecondsTimeout)
|
||||||
|
{
|
||||||
|
_stp.ValidateWorkItemsGroupWaitForIdle(this);
|
||||||
|
return _isIdleWaitHandle.WaitOne(millisecondsTimeout, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int WaitingCallbacks
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return _workItemsQueue.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event WorkItemsGroupIdleHandler OnIdle
|
||||||
|
{
|
||||||
|
add
|
||||||
|
{
|
||||||
|
_onIdle += value;
|
||||||
|
}
|
||||||
|
remove
|
||||||
|
{
|
||||||
|
_onIdle -= value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Cancel()
|
||||||
|
{
|
||||||
|
lock(_lock)
|
||||||
|
{
|
||||||
|
_canceledWorkItemsGroup.IsCanceled = true;
|
||||||
|
_workItemsQueue.Clear();
|
||||||
|
_workItemsInStpQueue = 0;
|
||||||
|
_canceledWorkItemsGroup = new CanceledWorkItemsGroup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Start()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (!_workItemsGroupStartInfo.StartSuspended)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_workItemsGroupStartInfo.StartSuspended = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < _concurrency; ++i)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextWorkItem(null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private methods
|
||||||
|
|
||||||
|
private void RegisterToWorkItemCompletion(IWorkItemResult wir)
|
||||||
|
{
|
||||||
|
IInternalWorkItemResult iwir = wir as IInternalWorkItemResult;
|
||||||
|
iwir.OnWorkItemStarted += new WorkItemStateCallback(OnWorkItemStartedCallback);
|
||||||
|
iwir.OnWorkItemCompleted += new WorkItemStateCallback(OnWorkItemCompletedCallback);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnSTPIsStarting()
|
||||||
|
{
|
||||||
|
lock (this)
|
||||||
|
{
|
||||||
|
if (_workItemsGroupStartInfo.StartSuspended)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int i = 0; i < _concurrency; ++i)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextWorkItem(null, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private object FireOnIdle(object state)
|
||||||
|
{
|
||||||
|
FireOnIdleImpl(_onIdle);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.NoInlining)]
|
||||||
|
private void FireOnIdleImpl(WorkItemsGroupIdleHandler onIdle)
|
||||||
|
{
|
||||||
|
if(null == onIdle)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Delegate[] delegates = onIdle.GetInvocationList();
|
||||||
|
foreach(WorkItemsGroupIdleHandler eh in delegates)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
eh(this);
|
||||||
|
}
|
||||||
|
// Ignore exceptions
|
||||||
|
catch{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWorkItemStartedCallback(WorkItem workItem)
|
||||||
|
{
|
||||||
|
lock(_lock)
|
||||||
|
{
|
||||||
|
++_workItemsExecutingInStp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnWorkItemCompletedCallback(WorkItem workItem)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextWorkItem(null, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnqueueToSTPNextWorkItem(WorkItem workItem)
|
||||||
|
{
|
||||||
|
EnqueueToSTPNextWorkItem(workItem, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnqueueToSTPNextWorkItem(WorkItem workItem, bool decrementWorkItemsInStpQueue)
|
||||||
|
{
|
||||||
|
lock(_lock)
|
||||||
|
{
|
||||||
|
// Got here from OnWorkItemCompletedCallback()
|
||||||
|
if (decrementWorkItemsInStpQueue)
|
||||||
|
{
|
||||||
|
--_workItemsInStpQueue;
|
||||||
|
|
||||||
|
if(_workItemsInStpQueue < 0)
|
||||||
|
{
|
||||||
|
_workItemsInStpQueue = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
--_workItemsExecutingInStp;
|
||||||
|
|
||||||
|
if(_workItemsExecutingInStp < 0)
|
||||||
|
{
|
||||||
|
_workItemsExecutingInStp = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the work item is not null then enqueue it
|
||||||
|
if (null != workItem)
|
||||||
|
{
|
||||||
|
workItem.CanceledWorkItemsGroup = _canceledWorkItemsGroup;
|
||||||
|
|
||||||
|
RegisterToWorkItemCompletion(workItem.GetWorkItemResult());
|
||||||
|
_workItemsQueue.Enqueue(workItem);
|
||||||
|
//_stp.IncrementWorkItemsCount();
|
||||||
|
|
||||||
|
if ((1 == _workItemsQueue.Count) &&
|
||||||
|
(0 == _workItemsInStpQueue))
|
||||||
|
{
|
||||||
|
_stp.RegisterWorkItemsGroup(this);
|
||||||
|
Trace.WriteLine("WorkItemsGroup " + Name + " is NOT idle");
|
||||||
|
_isIdleWaitHandle.Reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the work items queue of the group is empty than quit
|
||||||
|
if (0 == _workItemsQueue.Count)
|
||||||
|
{
|
||||||
|
if (0 == _workItemsInStpQueue)
|
||||||
|
{
|
||||||
|
_stp.UnregisterWorkItemsGroup(this);
|
||||||
|
Trace.WriteLine("WorkItemsGroup " + Name + " is idle");
|
||||||
|
_isIdleWaitHandle.Set();
|
||||||
|
_stp.QueueWorkItem(new WorkItemCallback(this.FireOnIdle));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_workItemsGroupStartInfo.StartSuspended)
|
||||||
|
{
|
||||||
|
if (_workItemsInStpQueue < _concurrency)
|
||||||
|
{
|
||||||
|
WorkItem nextWorkItem = _workItemsQueue.Dequeue() as WorkItem;
|
||||||
|
_stp.Enqueue(nextWorkItem, true);
|
||||||
|
++_workItemsInStpQueue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
|
@ -0,0 +1,600 @@
|
||||||
|
// Ami Bar
|
||||||
|
// amibar@gmail.com
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Amib.Threading.Internal
|
||||||
|
{
|
||||||
|
#region WorkItemsQueue class
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WorkItemsQueue class.
|
||||||
|
/// </summary>
|
||||||
|
public class WorkItemsQueue : IDisposable
|
||||||
|
{
|
||||||
|
#region Member variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Waiters queue (implemented as stack).
|
||||||
|
/// </summary>
|
||||||
|
private WaiterEntry _headWaiterEntry = new WaiterEntry();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Waiters count
|
||||||
|
/// </summary>
|
||||||
|
private int _waitersCount = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Work items queue
|
||||||
|
/// </summary>
|
||||||
|
private PriorityQueue _workItems = new PriorityQueue();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicate that work items are allowed to be queued
|
||||||
|
/// </summary>
|
||||||
|
private bool _isWorkItemsQueueActive = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Each thread in the thread pool keeps its own waiter entry.
|
||||||
|
/// </summary>
|
||||||
|
[ThreadStatic]
|
||||||
|
private static WaiterEntry _waiterEntry;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A flag that indicates if the WorkItemsQueue has been disposed.
|
||||||
|
/// </summary>
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public properties
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current number of work items in the queue
|
||||||
|
/// </summary>
|
||||||
|
public int Count
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
ValidateNotDisposed();
|
||||||
|
return _workItems.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the current number of waiters
|
||||||
|
/// </summary>
|
||||||
|
public int WaitersCount
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
ValidateNotDisposed();
|
||||||
|
return _waitersCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enqueue a work item to the queue.
|
||||||
|
/// </summary>
|
||||||
|
public bool EnqueueWorkItem(WorkItem workItem)
|
||||||
|
{
|
||||||
|
// A work item cannot be null, since null is used in the
|
||||||
|
// WaitForWorkItem() method to indicate timeout or cancel
|
||||||
|
if (null == workItem)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException("workItem" , "workItem cannot be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enqueue = true;
|
||||||
|
|
||||||
|
// First check if there is a waiter waiting for work item. During
|
||||||
|
// the check, timed out waiters are ignored. If there is no
|
||||||
|
// waiter then the work item is queued.
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
ValidateNotDisposed();
|
||||||
|
|
||||||
|
if (!_isWorkItemsQueueActive)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while(_waitersCount > 0)
|
||||||
|
{
|
||||||
|
// Dequeue a waiter.
|
||||||
|
WaiterEntry waiterEntry = PopWaiter();
|
||||||
|
|
||||||
|
// Signal the waiter. On success break the loop
|
||||||
|
if (waiterEntry.Signal(workItem))
|
||||||
|
{
|
||||||
|
enqueue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enqueue)
|
||||||
|
{
|
||||||
|
// Enqueue the work item
|
||||||
|
_workItems.Enqueue(workItem);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Waits for a work item or exits on timeout or cancel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="millisecondsTimeout">Timeout in milliseconds</param>
|
||||||
|
/// <param name="cancelEvent">Cancel wait handle</param>
|
||||||
|
/// <returns>Returns true if the resource was granted</returns>
|
||||||
|
public WorkItem DequeueWorkItem(
|
||||||
|
int millisecondsTimeout,
|
||||||
|
WaitHandle cancelEvent)
|
||||||
|
{
|
||||||
|
/// This method cause the caller to wait for a work item.
|
||||||
|
/// If there is at least one waiting work item then the
|
||||||
|
/// method returns immidiately with true.
|
||||||
|
///
|
||||||
|
/// If there are no waiting work items then the caller
|
||||||
|
/// is queued between other waiters for a work item to arrive.
|
||||||
|
///
|
||||||
|
/// If a work item didn't come within millisecondsTimeout or
|
||||||
|
/// the user canceled the wait by signaling the cancelEvent
|
||||||
|
/// then the method returns false to indicate that the caller
|
||||||
|
/// didn't get a work item.
|
||||||
|
|
||||||
|
WaiterEntry waiterEntry = null;
|
||||||
|
WorkItem workItem = null;
|
||||||
|
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
ValidateNotDisposed();
|
||||||
|
|
||||||
|
// If there are waiting work items then take one and return.
|
||||||
|
if (_workItems.Count > 0)
|
||||||
|
{
|
||||||
|
workItem = _workItems.Dequeue() as WorkItem;
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
// No waiting work items ...
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Get the wait entry for the waiters queue
|
||||||
|
waiterEntry = GetThreadWaiterEntry();
|
||||||
|
|
||||||
|
// Put the waiter with the other waiters
|
||||||
|
PushWaiter(waiterEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare array of wait handle for the WaitHandle.WaitAny()
|
||||||
|
WaitHandle [] waitHandles = new WaitHandle [] {
|
||||||
|
waiterEntry.WaitHandle,
|
||||||
|
cancelEvent };
|
||||||
|
|
||||||
|
// Wait for an available resource, cancel event, or timeout.
|
||||||
|
|
||||||
|
// During the wait we are supposes to exit the synchronization
|
||||||
|
// domain. (Placing true as the third argument of the WaitAny())
|
||||||
|
// It just doesn't work, I don't know why, so I have lock(this)
|
||||||
|
// statments insted of one.
|
||||||
|
|
||||||
|
int index = WaitHandle.WaitAny(
|
||||||
|
waitHandles,
|
||||||
|
millisecondsTimeout,
|
||||||
|
true);
|
||||||
|
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// success is true if it got a work item.
|
||||||
|
bool success = (0 == index);
|
||||||
|
|
||||||
|
// The timeout variable is used only for readability.
|
||||||
|
// (We treat cancel as timeout)
|
||||||
|
bool timeout = !success;
|
||||||
|
|
||||||
|
// On timeout update the waiterEntry that it is timed out
|
||||||
|
if (timeout)
|
||||||
|
{
|
||||||
|
// The Timeout() fails if the waiter has already been signaled
|
||||||
|
timeout = waiterEntry.Timeout();
|
||||||
|
|
||||||
|
// On timeout remove the waiter from the queue.
|
||||||
|
// Note that the complexity is O(1).
|
||||||
|
if(timeout)
|
||||||
|
{
|
||||||
|
RemoveWaiter(waiterEntry, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Again readability
|
||||||
|
success = !timeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On success return the work item
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
workItem = waiterEntry.WorkItem;
|
||||||
|
|
||||||
|
if (null == workItem)
|
||||||
|
{
|
||||||
|
workItem = _workItems.Dequeue() as WorkItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// On failure return null.
|
||||||
|
return workItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cleanup the work items queue, hence no more work
|
||||||
|
/// items are allowed to be queue
|
||||||
|
/// </summary>
|
||||||
|
protected virtual void Cleanup()
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// Deactivate only once
|
||||||
|
if (!_isWorkItemsQueueActive)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't queue more work items
|
||||||
|
_isWorkItemsQueueActive = false;
|
||||||
|
|
||||||
|
foreach(WorkItem workItem in _workItems)
|
||||||
|
{
|
||||||
|
workItem.DisposeOfState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear the work items that are already queued
|
||||||
|
_workItems.Clear();
|
||||||
|
|
||||||
|
// Note:
|
||||||
|
// I don't iterate over the queue and dispose of work items's states,
|
||||||
|
// since if a work item has a state object that is still in use in the
|
||||||
|
// application then I must not dispose it.
|
||||||
|
|
||||||
|
// Tell the waiters that they were timed out.
|
||||||
|
// It won't signal them to exit, but to ignore their
|
||||||
|
// next work item.
|
||||||
|
while(_waitersCount > 0)
|
||||||
|
{
|
||||||
|
WaiterEntry waiterEntry = PopWaiter();
|
||||||
|
waiterEntry.Timeout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Private methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the WaiterEntry of the current thread
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// In order to avoid creation and destuction of WaiterEntry
|
||||||
|
/// objects each thread has its own WaiterEntry object.
|
||||||
|
private WaiterEntry GetThreadWaiterEntry()
|
||||||
|
{
|
||||||
|
if (null == _waiterEntry)
|
||||||
|
{
|
||||||
|
_waiterEntry = new WaiterEntry();
|
||||||
|
}
|
||||||
|
_waiterEntry.Reset();
|
||||||
|
return _waiterEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Waiters stack methods
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Push a new waiter into the waiter's stack
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="newWaiterEntry">A waiter to put in the stack</param>
|
||||||
|
public void PushWaiter(WaiterEntry newWaiterEntry)
|
||||||
|
{
|
||||||
|
// Remove the waiter if it is already in the stack and
|
||||||
|
// update waiter's count as needed
|
||||||
|
RemoveWaiter(newWaiterEntry, false);
|
||||||
|
|
||||||
|
// If the stack is empty then newWaiterEntry is the new head of the stack
|
||||||
|
if (null == _headWaiterEntry._nextWaiterEntry)
|
||||||
|
{
|
||||||
|
_headWaiterEntry._nextWaiterEntry = newWaiterEntry;
|
||||||
|
newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
||||||
|
|
||||||
|
}
|
||||||
|
// If the stack is not empty then put newWaiterEntry as the new head
|
||||||
|
// of the stack.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Save the old first waiter entry
|
||||||
|
WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
|
||||||
|
|
||||||
|
// Update the links
|
||||||
|
_headWaiterEntry._nextWaiterEntry = newWaiterEntry;
|
||||||
|
newWaiterEntry._nextWaiterEntry = oldFirstWaiterEntry;
|
||||||
|
newWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
||||||
|
oldFirstWaiterEntry._prevWaiterEntry = newWaiterEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment the number of waiters
|
||||||
|
++_waitersCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pop a waiter from the waiter's stack
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Returns the first waiter in the stack</returns>
|
||||||
|
private WaiterEntry PopWaiter()
|
||||||
|
{
|
||||||
|
// Store the current stack head
|
||||||
|
WaiterEntry oldFirstWaiterEntry = _headWaiterEntry._nextWaiterEntry;
|
||||||
|
|
||||||
|
// Store the new stack head
|
||||||
|
WaiterEntry newHeadWaiterEntry = oldFirstWaiterEntry._nextWaiterEntry;
|
||||||
|
|
||||||
|
// Update the old stack head list links and decrement the number
|
||||||
|
// waiters.
|
||||||
|
RemoveWaiter(oldFirstWaiterEntry, true);
|
||||||
|
|
||||||
|
// Update the new stack head
|
||||||
|
_headWaiterEntry._nextWaiterEntry = newHeadWaiterEntry;
|
||||||
|
if (null != newHeadWaiterEntry)
|
||||||
|
{
|
||||||
|
newHeadWaiterEntry._prevWaiterEntry = _headWaiterEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the old stack head
|
||||||
|
return oldFirstWaiterEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove a waiter from the stack
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="waiterEntry">A waiter entry to remove</param>
|
||||||
|
/// <param name="popDecrement">If true the waiter count is always decremented</param>
|
||||||
|
private void RemoveWaiter(WaiterEntry waiterEntry, bool popDecrement)
|
||||||
|
{
|
||||||
|
// Store the prev entry in the list
|
||||||
|
WaiterEntry prevWaiterEntry = waiterEntry._prevWaiterEntry;
|
||||||
|
|
||||||
|
// Store the next entry in the list
|
||||||
|
WaiterEntry nextWaiterEntry = waiterEntry._nextWaiterEntry;
|
||||||
|
|
||||||
|
// A flag to indicate if we need to decrement the waiters count.
|
||||||
|
// If we got here from PopWaiter then we must decrement.
|
||||||
|
// If we got here from PushWaiter then we decrement only if
|
||||||
|
// the waiter was already in the stack.
|
||||||
|
bool decrementCounter = popDecrement;
|
||||||
|
|
||||||
|
// Null the waiter's entry links
|
||||||
|
waiterEntry._prevWaiterEntry = null;
|
||||||
|
waiterEntry._nextWaiterEntry = null;
|
||||||
|
|
||||||
|
// If the waiter entry had a prev link then update it.
|
||||||
|
// It also means that the waiter is already in the list and we
|
||||||
|
// need to decrement the waiters count.
|
||||||
|
if (null != prevWaiterEntry)
|
||||||
|
{
|
||||||
|
prevWaiterEntry._nextWaiterEntry = nextWaiterEntry;
|
||||||
|
decrementCounter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the waiter entry had a next link then update it.
|
||||||
|
// It also means that the waiter is already in the list and we
|
||||||
|
// need to decrement the waiters count.
|
||||||
|
if (null != nextWaiterEntry)
|
||||||
|
{
|
||||||
|
nextWaiterEntry._prevWaiterEntry = prevWaiterEntry;
|
||||||
|
decrementCounter = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decrement the waiters count if needed
|
||||||
|
if (decrementCounter)
|
||||||
|
{
|
||||||
|
--_waitersCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region WaiterEntry class
|
||||||
|
|
||||||
|
// A waiter entry in the _waiters queue.
|
||||||
|
public class WaiterEntry : IDisposable
|
||||||
|
{
|
||||||
|
#region Member variables
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Event to signal the waiter that it got the work item.
|
||||||
|
/// </summary>
|
||||||
|
private AutoResetEvent _waitHandle = new AutoResetEvent(false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flag to know if this waiter already quited from the queue
|
||||||
|
/// because of a timeout.
|
||||||
|
/// </summary>
|
||||||
|
private bool _isTimedout = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Flag to know if the waiter was signaled and got a work item.
|
||||||
|
/// </summary>
|
||||||
|
private bool _isSignaled = false;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A work item that passed directly to the waiter withou going
|
||||||
|
/// through the queue
|
||||||
|
/// </summary>
|
||||||
|
private WorkItem _workItem = null;
|
||||||
|
|
||||||
|
private bool _isDisposed = false;
|
||||||
|
|
||||||
|
// Linked list members
|
||||||
|
internal WaiterEntry _nextWaiterEntry = null;
|
||||||
|
internal WaiterEntry _prevWaiterEntry = null;
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Construction
|
||||||
|
|
||||||
|
public WaiterEntry()
|
||||||
|
{
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Public methods
|
||||||
|
|
||||||
|
public WaitHandle WaitHandle
|
||||||
|
{
|
||||||
|
get { return _waitHandle; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public WorkItem WorkItem
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
return _workItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Signal the waiter that it got a work item.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Return true on success</returns>
|
||||||
|
/// The method fails if Timeout() preceded its call
|
||||||
|
public bool Signal(WorkItem workItem)
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
if (!_isTimedout)
|
||||||
|
{
|
||||||
|
_workItem = workItem;
|
||||||
|
_isSignaled = true;
|
||||||
|
_waitHandle.Set();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Mark the wait entry that it has been timed out
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Return true on success</returns>
|
||||||
|
/// The method fails if Signal() preceded its call
|
||||||
|
public bool Timeout()
|
||||||
|
{
|
||||||
|
lock(this)
|
||||||
|
{
|
||||||
|
// Time out can happen only if the waiter wasn't marked as
|
||||||
|
// signaled
|
||||||
|
if (!_isSignaled)
|
||||||
|
{
|
||||||
|
// We don't remove the waiter from the queue, the DequeueWorkItem
|
||||||
|
// method skips _waiters that were timed out.
|
||||||
|
_isTimedout = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset the wait entry so it can be used again
|
||||||
|
/// </summary>
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
_workItem = null;
|
||||||
|
_isTimedout = false;
|
||||||
|
_isSignaled = false;
|
||||||
|
_waitHandle.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Free resources
|
||||||
|
/// </summary>
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (null != _waitHandle)
|
||||||
|
{
|
||||||
|
_waitHandle.Close();
|
||||||
|
_waitHandle = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
Close();
|
||||||
|
_isDisposed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~WaiterEntry()
|
||||||
|
{
|
||||||
|
Dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region IDisposable Members
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (!_isDisposed)
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
_isDisposed = true;
|
||||||
|
GC.SuppressFinalize(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
~WorkItemsQueue()
|
||||||
|
{
|
||||||
|
Cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ValidateNotDisposed()
|
||||||
|
{
|
||||||
|
if(_isDisposed)
|
||||||
|
{
|
||||||
|
throw new ObjectDisposedException(GetType().ToString(), "The SmartThreadPool has been shutdown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
Microsoft Public License (Ms-PL)
|
||||||
|
|
||||||
|
This license governs use of the accompanying software. If you use the software, you
|
||||||
|
accept this license. If you do not accept the license, do not use the software.
|
||||||
|
|
||||||
|
1. Definitions
|
||||||
|
The terms "reproduce," "reproduction," "derivative works," and "distribution" have the
|
||||||
|
same meaning here as under U.S. copyright law.
|
||||||
|
A "contribution" is the original software, or any additions or changes to the software.
|
||||||
|
A "contributor" is any person that distributes its contribution under this license.
|
||||||
|
"Licensed patents" are a contributor's patent claims that read directly on its contribution.
|
||||||
|
|
||||||
|
2. Grant of Rights
|
||||||
|
(A) Copyright Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free copyright license to reproduce its contribution, prepare derivative works of its contribution, and distribute its contribution or any derivative works that you create.
|
||||||
|
(B) Patent Grant- Subject to the terms of this license, including the license conditions and limitations in section 3, each contributor grants you a non-exclusive, worldwide, royalty-free license under its licensed patents to make, have made, use, sell, offer for sale, import, and/or otherwise dispose of its contribution in the software or derivative works of the contribution in the software.
|
||||||
|
|
||||||
|
3. Conditions and Limitations
|
||||||
|
(A) No Trademark License- This license does not grant you rights to use any contributors' name, logo, or trademarks.
|
||||||
|
(B) If you bring a patent claim against any contributor over patents that you claim are infringed by the software, your patent license from such contributor to the software ends automatically.
|
||||||
|
(C) If you distribute any portion of the software, you must retain all copyright, patent, trademark, and attribution notices that are present in the software.
|
||||||
|
(D) If you distribute any portion of the software in source code form, you may do so only under this license by including a complete copy of this license with your distribution. If you distribute any portion of the software in compiled or object code form, you may only do so under a license that complies with this license.
|
||||||
|
(E) The software is licensed "as-is." You bear the risk of using it. The contributors give no express warranties, guarantees or conditions. You may have additional consumer rights under your local laws which this license cannot change. To the extent permitted under your local laws, the contributors exclude the implied warranties of merchantability, fitness for a particular purpose and non-infringement.
|
|
@ -535,3 +535,40 @@ Password = "password"
|
||||||
ImportOnStartup = false
|
ImportOnStartup = false
|
||||||
Autosave = false
|
Autosave = false
|
||||||
AutoSavePeriod = 15 ; Number of minutes between autosave backups
|
AutoSavePeriod = 15 ; Number of minutes between autosave backups
|
||||||
|
|
||||||
|
|
||||||
|
[XEngine]
|
||||||
|
; How many threads to keep alive even if nothing is happening
|
||||||
|
MinThreads = 2
|
||||||
|
; How many threads to start at maximum load
|
||||||
|
MaxThreads = 100
|
||||||
|
; Time a thread must be idle (in seconds) before it dies
|
||||||
|
IdleTimeout = 60
|
||||||
|
; Thread priority ("Lowest", "BelowNormal", "Normal", "AboveNormal", "Highest")
|
||||||
|
Priority = "BelowNormal"
|
||||||
|
; Maximum number of events to queue for a script (excluding timers)
|
||||||
|
MaxScriptEventQueue = 300
|
||||||
|
; Stack size per thread created
|
||||||
|
ThreadStackSize = 262144
|
||||||
|
; Rate to poll for asynchronous command replies (ms)
|
||||||
|
AsyncLLCommandLoopms = 50
|
||||||
|
; Save the source of all compiled scripts
|
||||||
|
WriteScriptSourceToDebugFile = false
|
||||||
|
; Default language for scripts
|
||||||
|
DefaultCompileLanguage = lsl
|
||||||
|
; List of allowed languages (lsl,vb,js,cs)
|
||||||
|
AllowedCompilers = lsl
|
||||||
|
; Compile debug info (line numbers) into the script assemblies
|
||||||
|
CompileWithDebugInformation = true
|
||||||
|
; Allow the use of os* functions (some are dangerous)
|
||||||
|
AllowOSFunctions = false
|
||||||
|
; Interval (s) between background save of script states
|
||||||
|
SaveInterval = 120
|
||||||
|
; Interval (s) between maintenance runs (0 = disable)
|
||||||
|
MaintenanceInterval = 10
|
||||||
|
; Time a script can spend in an event handler before it is interrupted
|
||||||
|
EventLimit = 30
|
||||||
|
; If a script overruns it's event limit, kill the script?
|
||||||
|
KillTimedOutScripts = false
|
||||||
|
; Allow OS console command functionality (VERY DANGEROUS!!)
|
||||||
|
AllowosConsoleCommand = false
|
94
prebuild.xml
94
prebuild.xml
|
@ -1345,6 +1345,63 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project name="OpenSim.Region.ScriptEngine.XEngine.Script" path="OpenSim/Region/ScriptEngine/XEngine/Script" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System" localCopy="false"/>
|
||||||
|
<Reference name="System.Data" localCopy="false"/>
|
||||||
|
<Reference name="System.Web" localCopy="false"/>
|
||||||
|
<Reference name="System.Xml" localCopy="false"/>
|
||||||
|
<Reference name="libsecondlife.dll"/>
|
||||||
|
<Reference name="OpenSim" />
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Framework.Communications"/>
|
||||||
|
<Reference name="OpenSim.Region.Environment" />
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="Axiom.MathLib.dll" localCopy="false"/>
|
||||||
|
<Reference name="Nini.dll" />
|
||||||
|
<Reference name="RAIL.dll"/>
|
||||||
|
<Reference name="Nini.dll" />
|
||||||
|
<Reference name="log4net"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="true"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
<Project name="SmartThreadPool" path="ThirdParty/SmartThreadPool" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../bin/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../bin/</ReferencePath>
|
||||||
|
<Reference name="System" localCopy="false"/>
|
||||||
|
<Reference name="System.Xml"/>
|
||||||
|
<Reference name="System.Data"/>
|
||||||
|
<Reference name="System.Web"/>
|
||||||
|
<Files>
|
||||||
|
<Match pattern="*.cs" recurse="false"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<!-- OGS projects -->
|
<!-- OGS projects -->
|
||||||
|
|
||||||
|
@ -1571,6 +1628,43 @@
|
||||||
</Files>
|
</Files>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
<Project name="OpenSim.Region.ScriptEngine.XEngine" path="OpenSim/Region/ScriptEngine/XEngine" type="Library">
|
||||||
|
<Configuration name="Debug">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../bin/ScriptEngines/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
<Configuration name="Release">
|
||||||
|
<Options>
|
||||||
|
<OutputPath>../../../../bin/ScriptEngines/</OutputPath>
|
||||||
|
</Options>
|
||||||
|
</Configuration>
|
||||||
|
|
||||||
|
<ReferencePath>../../../../bin/</ReferencePath>
|
||||||
|
<Reference name="System" localCopy="false"/>
|
||||||
|
<Reference name="System.Data" localCopy="false"/>
|
||||||
|
<Reference name="System.Xml" localCopy="false"/>
|
||||||
|
<Reference name="System.Runtime.Remoting" localCopy="false"/>
|
||||||
|
<Reference name="libsecondlife.dll"/>
|
||||||
|
<Reference name="RAIL.dll"/>
|
||||||
|
<Reference name="OpenSim.Framework"/>
|
||||||
|
<Reference name="OpenSim.Framework.Console"/>
|
||||||
|
<Reference name="OpenSim.Framework.Communications"/>
|
||||||
|
<Reference name="OpenSim.Region.Environment" />
|
||||||
|
<Reference name="OpenSim.Region.ScriptEngine.XEngine.Script" />
|
||||||
|
<Reference name="Microsoft.JScript"/>
|
||||||
|
<Reference name="Axiom.MathLib.dll" localCopy="false"/>
|
||||||
|
<Reference name="Nini.dll" />
|
||||||
|
<Reference name="SmartThreadPool" />
|
||||||
|
<Reference name="log4net"/>
|
||||||
|
|
||||||
|
<Files>
|
||||||
|
<Match path="AsyncCommandPlugins" pattern="*.cs" recurse="false"/>
|
||||||
|
<Match pattern="*.cs" recurse="false"/>
|
||||||
|
</Files>
|
||||||
|
</Project>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<Project name="OpenSim.Grid.ScriptServer" path="OpenSim/Grid/ScriptServer" type="Exe">
|
<Project name="OpenSim.Grid.ScriptServer" path="OpenSim/Grid/ScriptServer" type="Exe">
|
||||||
<Configuration name="Debug">
|
<Configuration name="Debug">
|
||||||
|
|
Loading…
Reference in New Issue