* Implements Microthreading for MRM scripting.
* This is achieved through two new keywords "microthreaded" and "relax". example: public microthreaded void MyFunc(...) { ... relax; ... }0.6.5-rc1
parent
7066e6e69f
commit
883f7dde38
|
@ -38,11 +38,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||
private readonly IGraphics m_graphics;
|
||||
private readonly IExtension m_extend;
|
||||
private readonly IMicrothreader m_threader;
|
||||
//private Scene m_scene;
|
||||
|
||||
public Host(IObject m_obj, Scene m_scene, IExtension m_extend)
|
||||
public Host(IObject m_obj, Scene m_scene, IExtension m_extend, IMicrothreader m_threader)
|
||||
{
|
||||
this.m_obj = m_obj;
|
||||
this.m_threader = m_threader;
|
||||
this.m_extend = m_extend;
|
||||
//this.m_scene = m_scene;
|
||||
|
||||
|
@ -68,5 +70,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
{
|
||||
get { return m_extend; }
|
||||
}
|
||||
|
||||
public IMicrothreader Microthreads
|
||||
{
|
||||
get { return m_threader; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,5 +39,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
ILog Console { get; }
|
||||
IGraphics Graphics { get; }
|
||||
IExtension Extensions { get; }
|
||||
IMicrothreader Microthreads { get; }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenSim.Region.OptionalModules.Scripting.Minimodule.Interfaces
|
||||
{
|
||||
public interface IMicrothreader
|
||||
{
|
||||
void Run(IEnumerable microthread);
|
||||
}
|
||||
}
|
|
@ -52,6 +52,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
|
||||
private static readonly CSharpCodeProvider CScodeProvider = new CSharpCodeProvider();
|
||||
|
||||
private readonly MicroScheduler m_microthreads = new MicroScheduler();
|
||||
|
||||
public void RegisterExtension<T>(T instance)
|
||||
{
|
||||
m_extensions[typeof (T)] = instance;
|
||||
|
@ -66,6 +68,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
m_log.Info("[MRM] Enabling MRM Module");
|
||||
m_scene = scene;
|
||||
scene.EventManager.OnRezScript += EventManager_OnRezScript;
|
||||
scene.EventManager.OnFrame += EventManager_OnFrame;
|
||||
|
||||
scene.RegisterModuleInterface<IMRMModule>(this);
|
||||
}
|
||||
|
@ -80,6 +83,19 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
}
|
||||
}
|
||||
|
||||
void EventManager_OnFrame()
|
||||
{
|
||||
m_microthreads.Tick(1000);
|
||||
}
|
||||
|
||||
static string ConvertMRMKeywords(string script)
|
||||
{
|
||||
script = script.Replace("microthreaded void ", "IEnumerable");
|
||||
script = script.Replace("relax;", "yield return null;");
|
||||
|
||||
return script;
|
||||
}
|
||||
|
||||
void EventManager_OnRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource)
|
||||
{
|
||||
if (script.StartsWith("//MRM:C#"))
|
||||
|
@ -87,11 +103,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
|||
if (m_scene.GetSceneObjectPart(localID).OwnerID != m_scene.RegionInfo.MasterAvatarAssignedUUID)
|
||||
return;
|
||||
|
||||
script = ConvertMRMKeywords(script);
|
||||
|
||||
try
|
||||
{
|
||||
m_log.Info("[MRM] Found C# MRM");
|
||||
IWorld m_world = new World(m_scene);
|
||||
IHost m_host = new Host(new SOPObject(m_scene, localID), m_scene, new ExtensionHandler(m_extensions));
|
||||
IHost m_host = new Host(new SOPObject(m_scene, localID), m_scene, new ExtensionHandler(m_extensions),
|
||||
m_microthreads);
|
||||
|
||||
MRMBase mmb = (MRMBase)AppDomain.CurrentDomain.CreateInstanceFromAndUnwrap(
|
||||
CompileFromDotNetText(script, itemID.ToString()),
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenSim.Region.OptionalModules.Scripting.Minimodule.Interfaces;
|
||||
|
||||
namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
|
||||
{
|
||||
public class MicroScheduler : IMicrothreader
|
||||
{
|
||||
private readonly List<IEnumerator> m_threads = new List<IEnumerator>();
|
||||
|
||||
public void Run(IEnumerable microthread)
|
||||
{
|
||||
lock (m_threads)
|
||||
m_threads.Add(microthread.GetEnumerator());
|
||||
}
|
||||
|
||||
public void Tick(int count)
|
||||
{
|
||||
lock (m_threads)
|
||||
{
|
||||
if(m_threads.Count == 0)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
while (m_threads.Count > 0 && i < count)
|
||||
{
|
||||
i++;
|
||||
bool running = m_threads[i%m_threads.Count].MoveNext();
|
||||
|
||||
if (!running)
|
||||
m_threads.Remove(m_threads[i%m_threads.Count]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
//MRM:C#
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Region.OptionalModules.Scripting.Minimodule;
|
||||
|
||||
namespace OpenSim
|
||||
{
|
||||
class MiniModule : MRMBase
|
||||
{
|
||||
public microthreaded void MicroThreadFunction(string testparam)
|
||||
{
|
||||
Host.Object.Say("Hello " + testparam);
|
||||
|
||||
relax; // the 'relax' keyword gives up processing time.
|
||||
// and should be inserted before, after or in
|
||||
// any computationally "heavy" zones.
|
||||
|
||||
int c = 500;
|
||||
while(c-- < 0) {
|
||||
Host.Object.Say("C=" + c);
|
||||
relax; // Putting 'relax' in microthreaded loops
|
||||
// is an easy way to lower the CPU tax
|
||||
// on your script.
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
Host.Microthreads.Run(
|
||||
MicroThreadFunction("World!")
|
||||
);
|
||||
}
|
||||
|
||||
public override void Stop()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,12 +25,55 @@
|
|||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using OpenSim.Region.OptionalModules.Scripting.Minimodule;
|
||||
|
||||
namespace OpenSim
|
||||
{
|
||||
class MiniModule : MRMBase
|
||||
{
|
||||
// private microthreaded Function(params...)
|
||||
private IEnumerable TestMicrothread(string param)
|
||||
{
|
||||
Host.Console.Info("Microthreaded " + param);
|
||||
// relax;
|
||||
yield return null;
|
||||
Host.Console.Info("Microthreaded 2" + param);
|
||||
yield return null;
|
||||
int c = 100;
|
||||
while(c-- < 0)
|
||||
{
|
||||
Host.Console.Info("Microthreaded Looped " + c + " " + param);
|
||||
yield return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void Microthread(IEnumerable thread)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void RunMicrothread()
|
||||
{
|
||||
List<IEnumerator> threads = new List<IEnumerator>();
|
||||
threads.Add(TestMicrothread("A").GetEnumerator());
|
||||
threads.Add(TestMicrothread("B").GetEnumerator());
|
||||
threads.Add(TestMicrothread("C").GetEnumerator());
|
||||
|
||||
Microthread(TestMicrothread("Ohai"));
|
||||
|
||||
int i = 0;
|
||||
while(threads.Count > 0)
|
||||
{
|
||||
i++;
|
||||
bool running = threads[i%threads.Count].MoveNext();
|
||||
|
||||
if (!running)
|
||||
threads.Remove(threads[i%threads.Count]);
|
||||
}
|
||||
}
|
||||
|
||||
public override void Start()
|
||||
{
|
||||
// Say Hello
|
||||
|
|
Loading…
Reference in New Issue