* 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 /// In case, we are invoked asynchroneously this object will keep track of the state
/// </summary> /// </summary>
AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
ThreadPool.UnsafeQueueUserWorkItem(RequestHelper, ar); Util.FireAndForget(RequestHelper, ar);
return ar; return ar;
} }

View File

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

View File

@ -50,6 +50,18 @@ using OpenMetaverse.StructuredData;
namespace OpenSim.Framework namespace OpenSim.Framework
{ {
/// <summary>
/// The method used by Util.FireAndForget for asynchronously firing events
/// </summary>
public enum FireAndForgetMethod
{
UnsafeQueueUserWorkItem,
QueueUserWorkItem,
BeginInvoke,
SmartThreadPool,
Thread,
}
/// <summary> /// <summary>
/// Miscellaneous utility functions /// Miscellaneous utility functions
/// </summary> /// </summary>
@ -70,7 +82,9 @@ namespace OpenSim.Framework
public static readonly Regex UUIDPattern 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}$"); = 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> /// <summary>
/// Linear interpolates B<->C using percent A /// Linear interpolates B<->C using percent A
/// </summary> /// </summary>
@ -1273,7 +1287,7 @@ namespace OpenSim.Framework
/// <summary> /// <summary>
/// Created to work around a limitation in Mono with nested delegates /// Created to work around a limitation in Mono with nested delegates
/// </summary> /// </summary>
/*private class FireAndForgetWrapper private class FireAndForgetWrapper
{ {
public void FireAndForget(System.Threading.WaitCallback callback) public void FireAndForget(System.Threading.WaitCallback callback)
{ {
@ -1284,32 +1298,50 @@ namespace OpenSim.Framework
{ {
callback.BeginInvoke(obj, EndFireAndForget, callback); 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) public static void FireAndForget(System.Threading.WaitCallback callback)
{ {
//FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); FireAndForget(callback, null);
//wrapper.FireAndForget(callback);
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null);
} }
public static void FireAndForget(System.Threading.WaitCallback callback, object obj) public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
{ {
//FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>(); switch (FireAndForgetMethod)
//wrapper.FireAndForget(callback, obj); {
System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj); 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 #endregion FireAndForget Threading Pattern
} }
} }

View File

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

View File

@ -90,10 +90,17 @@ namespace OpenSim
appender.File = fileName; appender.File = fileName;
appender.ActivateOptions(); 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> /// <summary>

View File

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

View File

@ -302,12 +302,8 @@ namespace Flotsam.RegionModules.AssetCache
} }
ThreadPool.UnsafeQueueUserWorkItem( Util.FireAndForget(
delegate delegate { WriteFileCache(filename, asset); });
{
WriteFileCache(filename, asset);
}, null
);
} }
} }
catch (Exception e) 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 // The reason is so we don't cause the thread to freeze waiting
// for the 1 second it costs to start a thread manually. // for the 1 second it costs to start a thread manually.
if (!threadrunning) if (!threadrunning)
ThreadPool.UnsafeQueueUserWorkItem(this.StartThread, null); Util.FireAndForget(this.StartThread);
lock (m_rootAgents) lock (m_rootAgents)
{ {

View File

@ -31,6 +31,15 @@
; To run a script every few minutes, set the script filename here ; To run a script every few minutes, set the script filename here
; timer_Script = "filename" ; 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 ; ## CLIENTS