* Changed the misc. methods calling ThreadPool.UnsafeQueueUserWorkItem() to Util.FireAndForget()

* Changed Util.FireAndForget() to use any of five different methods set with async_call_method in the [Startup] section of OpenSim.ini. Look at the example config for possible values
prioritization
John Hurliman 2009-10-21 23:03:18 -07:00
parent 6492640e72
commit 32ccd5bb40
9 changed files with 79 additions and 36 deletions

View File

@ -403,7 +403,7 @@ namespace OpenSim.Framework.Communications
/// In case, we are invoked asynchroneously this object will keep track of the state
/// </summary>
AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
ThreadPool.UnsafeQueueUserWorkItem(RequestHelper, ar);
Util.FireAndForget(RequestHelper, ar);
return ar;
}

View File

@ -66,7 +66,7 @@ namespace OpenSim.Framework
for (int i = 0; i < threadCount; i++)
{
ThreadPool.UnsafeQueueUserWorkItem(
Util.FireAndForget(
delegate(object o)
{
int threadIndex = (int)o;
@ -122,7 +122,7 @@ namespace OpenSim.Framework
for (int i = 0; i < threadCount; i++)
{
ThreadPool.UnsafeQueueUserWorkItem(
Util.FireAndForget(
delegate(object o)
{
int threadIndex = (int)o;
@ -178,7 +178,7 @@ namespace OpenSim.Framework
for (int i = 0; i < threadCount; i++)
{
ThreadPool.UnsafeQueueUserWorkItem(
Util.FireAndForget(
delegate(object o)
{
int threadIndex = (int)o;

View File

@ -50,6 +50,18 @@ using OpenMetaverse.StructuredData;
namespace OpenSim.Framework
{
/// <summary>
/// The method used by Util.FireAndForget for asynchronously firing events
/// </summary>
public enum FireAndForgetMethod
{
UnsafeQueueUserWorkItem,
QueueUserWorkItem,
BeginInvoke,
SmartThreadPool,
Thread,
}
/// <summary>
/// Miscellaneous utility functions
/// </summary>
@ -70,7 +82,9 @@ namespace OpenSim.Framework
public static readonly Regex UUIDPattern
= new Regex("^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$");
public static FireAndForgetMethod FireAndForgetMethod = FireAndForgetMethod.UnsafeQueueUserWorkItem;
/// <summary>
/// Linear interpolates B<->C using percent A
/// </summary>
@ -1273,7 +1287,7 @@ namespace OpenSim.Framework
/// <summary>
/// Created to work around a limitation in Mono with nested delegates
/// </summary>
/*private class FireAndForgetWrapper
private class FireAndForgetWrapper
{
public void FireAndForget(System.Threading.WaitCallback callback)
{
@ -1284,32 +1298,50 @@ namespace OpenSim.Framework
{
callback.BeginInvoke(obj, EndFireAndForget, callback);
}
}*/
private static void EndFireAndForget(IAsyncResult ar)
{
System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
try { callback.EndInvoke(ar); }
catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
ar.AsyncWaitHandle.Close();
}
}
public static void FireAndForget(System.Threading.WaitCallback callback)
{
//FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
//wrapper.FireAndForget(callback);
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null);
FireAndForget(callback, null);
}
public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
{
//FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
//wrapper.FireAndForget(callback, obj);
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
switch (FireAndForgetMethod)
{
case FireAndForgetMethod.UnsafeQueueUserWorkItem:
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
break;
case FireAndForgetMethod.QueueUserWorkItem:
System.Threading.ThreadPool.QueueUserWorkItem(callback, obj);
break;
case FireAndForgetMethod.BeginInvoke:
FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
wrapper.FireAndForget(callback, obj);
break;
case FireAndForgetMethod.SmartThreadPool:
Amib.Threading.SmartThreadPool stp = Singleton.GetInstance<Amib.Threading.SmartThreadPool>();
stp.QueueWorkItem(delegate(object o) { callback(o); return null; }, obj);
break;
case FireAndForgetMethod.Thread:
System.Threading.Thread thread = new System.Threading.Thread(delegate(object o) { callback(o); });
thread.Start(obj);
break;
default:
throw new NotImplementedException();
}
}
/*private static void EndFireAndForget(IAsyncResult ar)
{
System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
try { callback.EndInvoke(ar); }
catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
ar.AsyncWaitHandle.Close();
}*/
#endregion FireAndForget Threading Pattern
}
}

View File

@ -148,8 +148,7 @@ namespace OpenSim.Grid.MessagingServer.Modules
friendlistupdater.presence2 = receiver;
friendlistupdater.OnGetRegionData += m_regionModule.GetRegionInfo;
friendlistupdater.OnDone += PresenceUpdateDone;
WaitCallback cb = new WaitCallback(friendlistupdater.go);
ThreadPool.UnsafeQueueUserWorkItem(cb, null);
Util.FireAndForget(friendlistupdater.go);
}
else
{

View File

@ -90,10 +90,17 @@ namespace OpenSim
appender.File = fileName;
appender.ActivateOptions();
}
m_log.InfoFormat("[LOGGING] Logging started to file {0}", appender.File);
m_log.InfoFormat("[LOGGING]: Logging started to file {0}", appender.File);
}
}
string asyncCallMethodStr = startupConfig.GetString("async_call_method", String.Empty);
FireAndForgetMethod asyncCallMethod;
if (!String.IsNullOrEmpty(asyncCallMethodStr) && Utils.EnumTryParse<FireAndForgetMethod>(asyncCallMethodStr, out asyncCallMethod))
Util.FireAndForgetMethod = asyncCallMethod;
}
m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod);
}
/// <summary>

View File

@ -791,7 +791,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="map">heightmap</param>
public virtual void SendLayerData(float[] map)
{
ThreadPool.UnsafeQueueUserWorkItem(DoSendLayerData, map);
Util.FireAndForget(DoSendLayerData, map);
}
/// <summary>
@ -931,7 +931,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="windSpeeds">16x16 array of wind speeds</param>
public virtual void SendWindData(Vector2[] windSpeeds)
{
ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(DoSendWindData), (object)windSpeeds);
Util.FireAndForget(DoSendWindData, windSpeeds);
}
/// <summary>
@ -940,7 +940,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
/// <param name="windSpeeds">16x16 array of cloud densities</param>
public virtual void SendCloudData(float[] cloudDensity)
{
ThreadPool.UnsafeQueueUserWorkItem(new WaitCallback(DoSendCloudData), (object)cloudDensity);
Util.FireAndForget(DoSendCloudData, cloudDensity);
}
/// <summary>

View File

@ -302,12 +302,8 @@ namespace Flotsam.RegionModules.AssetCache
}
ThreadPool.UnsafeQueueUserWorkItem(
delegate
{
WriteFileCache(filename, asset);
}, null
);
Util.FireAndForget(
delegate { WriteFileCache(filename, asset); });
}
}
catch (Exception e)

View File

@ -1095,7 +1095,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap
// The reason is so we don't cause the thread to freeze waiting
// for the 1 second it costs to start a thread manually.
if (!threadrunning)
ThreadPool.UnsafeQueueUserWorkItem(this.StartThread, null);
Util.FireAndForget(this.StartThread);
lock (m_rootAgents)
{

View File

@ -31,6 +31,15 @@
; To run a script every few minutes, set the script filename here
; timer_Script = "filename"
; ##
; ## SYSTEM
; ##
; Sets the method that OpenSim will use to fire asynchronous
; events. Valid values are UnsafeQueueUserWorkItem,
; QueueUserWorkItem, BeginInvoke, SmartThreadPool, and Thread
async_call_method = UnsafeQueueUserWorkItem
; ##
; ## CLIENTS