2021-07-11 22:59:29 -05:00
// Decompiled with JetBrains decompiler
// Type: Microsoft.Iris.Render.Protocol.MessagingSession
// Assembly: UIX.RenderApi, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217
// MVID: D47658B8-A8EA-43D6-8837-ECE823BFFFC1
// Assembly location: C:\Program Files\Zune\UIX.RenderApi.dll
using Microsoft.Iris.Render.Common ;
using Microsoft.Iris.Render.Internal ;
using System ;
using System.Threading ;
namespace Microsoft.Iris.Render.Protocol
{
2021-07-11 23:04:40 -05:00
internal sealed class MessagingSession : RenderObject
2021-07-11 22:59:29 -05:00
{
2021-07-11 23:04:40 -05:00
private static Map < Thread , MessagingSession > s_sessions = new Map < Thread , MessagingSession >();
private readonly ContextID m_localContextId ;
private bool m_isConnected ;
private int m_pingRequestCount ;
private IRenderHost m_renderHost ;
private Thread m_owningThread ;
private Vector m_ports ;
private Vector m_activeTrackers ;
private RenderPort m_portRendering ;
private RenderPort m_portWindowing ;
private bool m_isBatchingMessages ;
private BatchCallback m_batchFillCallback ;
private BatchCallback m_batchBeginCallbacks ;
private BatchCallback m_batchEndCallbacks ;
private BatchCallback m_batchDeliveryCallbacks ;
private bool m_fBatchFlushRequested ;
private DeferredInvokeItem m_batchFlushInvokeItem ;
private EngineApi . MessageBufferEventHandler m_messageBufferHandler ;
private TimeoutHandler m_externalTimeoutHandler ;
private EngineApi . TimeoutEventHandler m_internalTimeoutHandler ;
2021-07-11 22:59:29 -05:00
2021-07-11 23:04:40 -05:00
internal MessagingSession ( IRenderHost renderHost , RenderToken token )
2021-07-11 23:07:04 -05:00
: this ( renderHost , token , null , 0 U )
2021-07-11 22:59:29 -05:00
{
}
2021-07-11 23:04:40 -05:00
internal MessagingSession (
IRenderHost renderHost ,
RenderToken token ,
TimeoutHandler handlerTimeout ,
uint nTimeoutSec )
2021-07-11 22:59:29 -05:00
{
2021-07-11 23:04:40 -05:00
Debug2 . Validate ( renderHost != null , typeof ( ArgumentNullException ), nameof ( renderHost ));
Debug2 . Validate ( token != null , typeof ( ArgumentNullException ), nameof ( token ));
Debug2 . Validate ( token . LocalContextId != ContextID . NULL , typeof ( ArgumentNullException ), "token.LocalContextId" );
Debug2 . Validate ( token . EngineInfo is IrisEngineInfo , typeof ( ArgumentException ), "token.EngineInfo" );
this . m_pingRequestCount = 0 ;
this . m_renderHost = renderHost ;
this . m_ports = new Vector ( 2 );
this . m_localContextId = token . LocalContextId ;
2021-07-11 23:07:04 -05:00
this . m_batchFlushInvokeItem = new DeferredInvokeItem ( null , new DeferredHandler ( this . ProcessDeferredFlushBatch ), null );
2021-07-11 23:04:40 -05:00
this . m_batchFillCallback = new BatchCallback ( this . OnBatchFirstMessage );
this . InitializeLocalMessaging ( this . m_localContextId , new EngineApi . MessageBufferEventHandler ( this . OnIncomingMessageBuffer ), nTimeoutSec , handlerTimeout );
this . m_portRendering = this . CreatePort (( token . EngineInfo as IrisEngineInfo ). ConnectionInfo , token . DestinationContextId , token . RenderGroupId );
2021-07-11 23:07:04 -05:00
this . m_portWindowing = null ;
2021-07-11 23:04:40 -05:00
this . m_activeTrackers = new Vector ();
}
protected override void Dispose ( bool fInDispose )
{
try
{
if ( fInDispose )
{
if ( this . IsConnected )
this . Disconnect ();
this . DisposeRemainingDataBufferTrackers ();
foreach ( RenderPort port in this . m_ports )
port . Dispose ();
this . m_ports . Clear ();
this . ShutdownLocalMessaging ();
}
2021-07-11 23:07:04 -05:00
this . m_activeTrackers = null ;
this . m_portWindowing = null ;
this . m_portRendering = null ;
this . m_ports = null ;
this . m_renderHost = null ;
2021-07-11 23:04:40 -05:00
}
finally
{
base . Dispose ( fInDispose );
}
}
internal static MessagingSession Current
{
get
{
2021-07-11 23:07:04 -05:00
lock ( s_sessions )
return s_sessions . ContainsKey ( Thread . CurrentThread ) ? s_sessions [ Thread . CurrentThread ] : null ;
2021-07-11 23:04:40 -05:00
}
}
internal Thread OwningThread => this . m_owningThread ;
internal bool IsConnected => this . m_isConnected ;
internal ContextID LocalContext => this . m_localContextId ;
internal RenderPort RenderingPort => this . m_portRendering ;
internal RenderPort WindowingPort => this . m_portWindowing == null ? this . m_portRendering : this . m_portWindowing ;
private void InitializeLocalMessaging (
ContextID localContextId ,
EngineApi . MessageBufferEventHandler messageHandler ,
uint timeoutInSeconds ,
TimeoutHandler timeoutHandler )
{
this . m_messageBufferHandler = messageHandler ;
this . m_externalTimeoutHandler = timeoutHandler ;
this . m_internalTimeoutHandler = new EngineApi . TimeoutEventHandler ( this . OnTimedOut );
EngineApi . InitArgs args = new EngineApi . InitArgs ( MessageCookieLayout . Default , localContextId , messageHandler );
if ( timeoutInSeconds > 0 U && timeoutHandler != null )
{
args . pfnTimeout = this . m_internalTimeoutHandler ;
args . nTimeOutSec = timeoutInSeconds ;
}
EngineApi . IFC ( EngineApi . SpInit ( ref args ));
2021-07-11 23:07:04 -05:00
lock ( s_sessions )
2021-07-11 23:04:40 -05:00
{
this . m_owningThread = Thread . CurrentThread ;
2021-07-11 23:07:04 -05:00
s_sessions [ this . m_owningThread ] = this ;
2021-07-11 23:04:40 -05:00
}
}
private void ShutdownLocalMessaging ()
{
2021-07-11 23:07:04 -05:00
lock ( s_sessions )
2021-07-11 23:04:40 -05:00
{
2021-07-11 23:07:04 -05:00
s_sessions . Remove ( this . m_owningThread );
this . m_owningThread = null ;
2021-07-11 23:04:40 -05:00
}
EngineApi . IFC ( EngineApi . SpUninit ());
2021-07-11 23:07:04 -05:00
this . m_messageBufferHandler = null ;
this . m_externalTimeoutHandler = null ;
this . m_internalTimeoutHandler = null ;
2021-07-11 23:04:40 -05:00
}
internal static void DoEvents ( uint nTimeoutInMsecs )
{
EngineApi . SpWaitMessage ( nTimeoutInMsecs , IntPtr . Zero );
EngineApi . SpPeekMessage ( out Win32Api . MSG _ , HWND . NULL , 0 U , 0 U , 1 U , out EngineApi . WorkResult _ );
}
private RenderPort CreatePort (
ConnectionInfo connectionInfo ,
ContextID destinationContextId ,
RENDERGROUP grpObjects )
{
foreach ( RenderPort port in this . m_ports )
Debug2 . Validate ( port . RemoteContext != destinationContextId , typeof ( ArgumentException ), "There already is a RenderPort allocated for this destination context" );
bool foreignByteOrder = false ;
IChannel channel ;
switch ( connectionInfo )
{
case LocalConnectionInfo _ :
2021-07-11 23:07:04 -05:00
channel = new LocalChannel (( LocalConnectionInfo ) connectionInfo );
2021-07-11 23:04:40 -05:00
break ;
case RemoteConnectionInfo _ :
RemoteConnectionInfo connectionInfo1 = ( RemoteConnectionInfo ) connectionInfo ;
2021-07-11 23:07:04 -05:00
channel = new RemoteChannel ( connectionInfo1 );
2021-07-11 23:04:40 -05:00
foreignByteOrder = connectionInfo1 . SwapByteOrder ;
break ;
default :
2021-07-11 23:07:04 -05:00
return null ;
2021-07-11 23:04:40 -05:00
}
RenderPort renderPort = new RenderPort ( this , channel , destinationContextId , grpObjects , MessageCookieLayout . Default , foreignByteOrder );
if ( this . m_isConnected )
renderPort . Connect ();
2021-07-11 23:07:04 -05:00
this . m_ports . Add ( renderPort );
2021-07-11 23:04:40 -05:00
return renderPort ;
}
internal DataBufferTracker CreateDataBufferTracker ( object objUser ) => new DataBufferTracker ( objUser );
internal void ReturnDataBufferTracker ( DataBufferTracker tracker )
{
if ( tracker . Count != 0 )
{
tracker . TrackerEmpty += new EventHandler ( this . OnDataBufferTrackerEmpty );
2021-07-11 23:07:04 -05:00
this . m_activeTrackers . Add ( tracker );
2021-07-11 23:04:40 -05:00
}
else
tracker . Dispose ();
}
private void OnDataBufferTrackerEmpty ( object objSender , EventArgs args )
{
DataBufferTracker dataBufferTracker = ( DataBufferTracker ) objSender ;
2021-07-11 23:07:04 -05:00
this . m_activeTrackers . Remove ( dataBufferTracker );
2021-07-11 23:04:40 -05:00
dataBufferTracker . TrackerEmpty -= new EventHandler ( this . OnDataBufferTrackerEmpty );
dataBufferTracker . Dispose ();
}
private void DisposeRemainingDataBufferTrackers ()
{
if ( this . m_activeTrackers . Count <= 0 )
return ;
foreach ( DataBufferTracker activeTracker in this . m_activeTrackers )
activeTracker . Dispose ();
this . m_activeTrackers . Clear ();
}
internal void Connect ()
{
Debug2 . Throw (! this . m_isConnected , "MessagingSession is already connected" );
foreach ( RenderPort port in this . m_ports )
port . Connect ();
this . Synchronize ();
this . StartNewBatch ();
this . m_isConnected = true ;
}
internal void Disconnect ()
{
Debug2 . Throw ( this . m_isConnected , "MessagingSession is not connected" );
this . FlushCurrentBatch ( true );
this . Synchronize ();
foreach ( RenderPort port in this . m_ports )
port . DisposeObjectMaps ();
foreach ( RenderPort port in this . m_ports )
port . Dispose ();
this . m_ports . Clear ();
this . m_isConnected = false ;
}
internal void Synchronize ()
{
foreach ( RenderPort port in this . m_ports )
{
port . PingReply += new EventHandler ( this . OnPingReply );
++ this . m_pingRequestCount ;
port . PingConnection ();
}
if ( this . m_isBatchingMessages )
this . FlushBatch ();
while ( this . m_pingRequestCount > 0 )
2021-07-11 23:07:04 -05:00
DoEvents ( uint . MaxValue );
2021-07-11 23:04:40 -05:00
}
private void OnPingReply ( object sender , EventArgs args )
{
( sender as RenderPort ). PingReply -= new EventHandler ( this . OnPingReply );
-- this . m_pingRequestCount ;
}
private void StartNewBatch ()
{
if ( this . m_isBatchingMessages || this . m_ports . Count <= 0 )
return ;
foreach ( RenderPort port in this . m_ports )
port . BeginMessageBatch ( this . m_batchFillCallback );
this . m_isBatchingMessages = true ;
if ( this . m_batchBeginCallbacks == null )
return ;
this . m_batchBeginCallbacks ();
2021-07-11 23:07:04 -05:00
this . m_batchBeginCallbacks = null ;
2021-07-11 23:04:40 -05:00
}
internal void FlushBatch () => this . FlushCurrentBatch ( false );
private void FlushCurrentBatch ( bool stopBatching )
{
if (! this . m_isBatchingMessages )
return ;
if ( this . m_batchEndCallbacks != null )
{
this . m_batchEndCallbacks ();
2021-07-11 23:07:04 -05:00
this . m_batchEndCallbacks = null ;
2021-07-11 23:04:40 -05:00
}
this . m_isBatchingMessages = false ;
BatchCallback deliveryCallbacks = this . m_batchDeliveryCallbacks ;
2021-07-11 23:07:04 -05:00
this . m_batchDeliveryCallbacks = null ;
2021-07-11 23:04:40 -05:00
foreach ( RenderPort port in this . m_ports )
port . EndMessageBatch ( deliveryCallbacks );
if ( stopBatching )
return ;
this . StartNewBatch ();
}
internal void ScheduleBatchFlush ()
{
if ( this . m_fBatchFlushRequested )
return ;
this . AssertOwningThread ();
this . DeferredInvoke ( this . m_batchFlushInvokeItem , DeferredInvokePriority . Low );
this . m_fBatchFlushRequested = true ;
}
internal void ProcessDeferredFlushBatch ( object args )
{
this . AssertOwningThread ();
if (! this . m_fBatchFlushRequested )
return ;
this . FlushBatch ();
this . m_fBatchFlushRequested = false ;
}
public void NotifyOnBeginBatch ( BatchCallback newCallback )
{
if (! this . m_isBatchingMessages )
return ;
this . m_batchBeginCallbacks += newCallback ;
}
public void NotifyOnEndBatch ( BatchCallback newCallback , bool notifyEmptyBatches )
{
if (! this . m_isBatchingMessages )
return ;
if ( notifyEmptyBatches )
this . ScheduleBatchFlush ();
this . m_batchEndCallbacks += newCallback ;
}
public void NotifyOnCurrentBatchDelivered ( BatchCallback newCallback )
{
if (! this . m_isBatchingMessages )
return ;
this . m_batchDeliveryCallbacks += newCallback ;
}
private void OnBatchFirstMessage () => this . ScheduleBatchFlush ();
private unsafe int OnIncomingMessageBuffer (
IntPtr pData ,
uint hContext ,
EngineApi . BufferInfo * pBufferInfo ,
void * pvBufferData )
{
2021-07-11 23:07:04 -05:00
RenderPort renderPort = null ;
2021-07-11 23:04:40 -05:00
for ( int index = 0 ; index < this . m_ports . Count ; ++ index )
{
RenderPort port = ( RenderPort ) this . m_ports [ index ];
if ( port . RemoteContext == pBufferInfo -> idContextSrc )
{
renderPort = port ;
break ;
}
}
Debug2 . Throw ( renderPort != null , "Expected a render port if we are receiving buffers" );
renderPort . ProcessMessageBuffer ( pBufferInfo , pvBufferData );
return 0 ;
}
private void OnTimedOut ( IntPtr pData )
{
if ( this . m_externalTimeoutHandler == null )
return ;
this . m_externalTimeoutHandler ();
}
internal void AssertOwningThread ()
{
}
internal bool IsOwningThread () => this . m_owningThread == Thread . CurrentThread ;
internal void DeferredInvoke ( Delegate method , object args , DeferredInvokePriority priority ) => this . DeferredInvoke ( method , args , priority , TimeSpan . FromMilliseconds ( 0.0 ));
internal void DeferredInvoke (
SharedRenderObject owner ,
Delegate method ,
object args ,
DeferredInvokePriority priority )
{
this . DeferredInvoke ( owner , method , args , priority , TimeSpan . FromMilliseconds ( 0.0 ));
}
internal void DeferredInvoke (
Delegate method ,
object args ,
DeferredInvokePriority priority ,
TimeSpan delay )
{
2021-07-11 23:07:04 -05:00
this . DeferredInvoke ( null , method , args , priority , delay );
2021-07-11 23:04:40 -05:00
}
internal void DeferredInvoke (
SharedRenderObject instanceOwner ,
Delegate method ,
object args ,
DeferredInvokePriority priority ,
TimeSpan delay )
{
if ( this . m_owningThread == null )
return ;
DeferredInvokeItem deferredInvokeItem = new DeferredInvokeItem ( instanceOwner , method , args );
2021-07-11 23:07:04 -05:00
this . m_renderHost . DeferredInvoke ( priority , deferredInvokeItem , delay );
2021-07-11 23:04:40 -05:00
}
private void DeferredInvoke ( DeferredInvokeItem item , DeferredInvokePriority priority )
{
if ( this . m_owningThread == null )
return ;
2021-07-11 23:07:04 -05:00
this . m_renderHost . DeferredInvoke ( priority , item , TimeSpan . FromMilliseconds ( 0.0 ));
2021-07-11 23:04:40 -05:00
}
protected override void Invariant ()
{
Debug2 . Validate ( this . m_owningThread != null , typeof ( InvalidOperationException ), this . GetType (). ToString ());
Debug2 . Validate ( this . m_renderHost != null , typeof ( InvalidOperationException ), this . GetType (). ToString ());
Debug2 . Validate ( this . m_isConnected , typeof ( InvalidOperationException ), this . GetType (). ToString ());
2021-07-11 22:59:29 -05:00
}
}
}