/// <summary> /// Protected implementation of Dispose pattern. /// </summary> /// <param name="disposing"></param> protected virtual void Dispose(bool disposing) { if (isDisposed || !disposing) { return; } // Close shared memory. // globalMemoryRegionView?.Dispose(); globalMemoryRegionView = null; controlChannelMemoryMapView?.Dispose(); controlChannelMemoryMapView = null; feedbackChannelMemoryMapView?.Dispose(); feedbackChannelMemoryMapView = null; controlChannelNamedEvent?.Dispose(); controlChannelNamedEvent = null; feedbackChannelNamedEvent?.Dispose(); feedbackChannelNamedEvent = null; // Finally dispose the shared config manager. // SharedConfigManager?.Dispose(); SharedConfigManager = null; isDisposed = true; }
/// <summary> /// Initializes a new instance of the <see cref="InterProcessMlosContext"/> class. /// </summary> /// <returns>InterProcessMlosContext instance.</returns> public static InterProcessMlosContext CreateOrOpen() { NamedEvent targetProcessNamedEvent = NamedEvent.CreateOrOpen(TargetProcessEventName); { bool shouldWaitForTargetProcess = false; try { // Try open a global shared memory and check if the tager process is fully initialized. // using SharedMemoryRegionView <MlosProxyInternal.GlobalMemoryRegion> targetProcessMemoryRegionView = SharedMemoryRegionView.OpenExisting <MlosProxyInternal.GlobalMemoryRegion>(GlobalMemoryMapName, SharedMemorySize); if (targetProcessMemoryRegionView.MemoryRegion().GlobalMemoryRegionIndex == 1) { shouldWaitForTargetProcess = true; } } catch (FileNotFoundException) { // If the target process is not running. // shouldWaitForTargetProcess = true; } if (shouldWaitForTargetProcess) { // If the target process is not fully initialized, wait for the signal. // targetProcessNamedEvent.Wait(); targetProcessNamedEvent.Signal(); } } SharedMemoryRegionView <MlosProxyInternal.GlobalMemoryRegion> globalMemoryRegionView = SharedMemoryRegionView.OpenExisting <MlosProxyInternal.GlobalMemoryRegion>(GlobalMemoryMapName, SharedMemorySize); SharedMemoryMapView controlChannelMemoryMapView = SharedMemoryMapView.OpenExisting(ControlChannelMemoryMapName, SharedMemorySize); SharedMemoryMapView feedbackChannelMemoryMapView = SharedMemoryMapView.OpenExisting(FeedbackChannelMemoryMapName, SharedMemorySize); // Create channel synchronization primitives. // NamedEvent controlChannelNamedEvent = NamedEvent.CreateOrOpen(ControlChannelEventName); NamedEvent feedbackChannelNamedEvent = NamedEvent.CreateOrOpen(FeedbackChannelEventName); return(new InterProcessMlosContext( globalMemoryRegionView, controlChannelMemoryMapView, feedbackChannelMemoryMapView, controlChannelNamedEvent, feedbackChannelNamedEvent, targetProcessNamedEvent)); }
/// <summary> /// Tries to open an exiting named event. /// </summary> /// <param name="name"></param> /// <param name="namedEvent"></param> /// <returns></returns> public static bool TryOpenExisting(string name, out NamedEvent namedEvent) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { return(Windows.NamedEvent.TryOpenExisting(name, out namedEvent)); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { return(Linux.NamedSemaphore.TryOpenExisting(name, out namedEvent)); } else { throw new InvalidOperationException("Unsupported OS."); } }
/// <summary> /// Initializes a new instance of the <see cref="InterProcessMlosContext"/> class. /// </summary> /// <param name="globalMemoryRegionView"></param> /// <param name="controlChannelMemoryMapView"></param> /// <param name="feedbackChannelMemoryMapView"></param> /// <param name="controlChannelNamedEvent"></param> /// <param name="feedbackChannelNamedEvent"></param> /// <param name="targetProcessNamedEvent"></param> internal InterProcessMlosContext( SharedMemoryRegionView <MlosProxyInternal.GlobalMemoryRegion> globalMemoryRegionView, SharedMemoryMapView controlChannelMemoryMapView, SharedMemoryMapView feedbackChannelMemoryMapView, NamedEvent controlChannelNamedEvent, NamedEvent feedbackChannelNamedEvent, NamedEvent targetProcessNamedEvent) { this.globalMemoryRegionView = globalMemoryRegionView; this.controlChannelMemoryMapView = controlChannelMemoryMapView; this.feedbackChannelMemoryMapView = feedbackChannelMemoryMapView; this.controlChannelNamedEvent = controlChannelNamedEvent; this.feedbackChannelNamedEvent = feedbackChannelNamedEvent; this.targetProcessNamedEvent = targetProcessNamedEvent; // Create the shared config manager. // SharedConfigManager = new SharedConfigManager(); MlosProxyInternal.GlobalMemoryRegion globalMemoryRegion = globalMemoryRegionView.MemoryRegion(); // Increase the usage counter. When closing global shared memory, we will decrease the counter. // If there is no process using the shared memory, we will clean the OS resources. On Windows OS, // this is no-op; on Linux, we unlink created files. // globalMemoryRegion.AttachedProcessesCount.FetchAdd(1); // Create the control channel instance. // ControlChannel = new SharedChannel <InterProcessSharedChannelPolicy, SharedChannelSpinPolicy>( buffer: controlChannelMemoryMapView.Buffer, size: (uint)controlChannelMemoryMapView.MemSize, sync: globalMemoryRegion.ControlChannelSynchronization) { ChannelPolicy = { NotificationEvent = controlChannelNamedEvent }, }; // Create the feedback channel instance. // FeedbackChannel = new SharedChannel <InterProcessSharedChannelPolicy, SharedChannelSpinPolicy>( buffer: feedbackChannelMemoryMapView.Buffer, size: (uint)feedbackChannelMemoryMapView.MemSize, sync: globalMemoryRegion.FeedbackChannelSynchronization) { ChannelPolicy = { NotificationEvent = feedbackChannelNamedEvent }, }; }
/// <summary> /// Initializes a new instance of the <see cref="InterProcessMlosContext"/> class. /// </summary> /// <returns>InterProcessMlosContext instance.</returns> public static InterProcessMlosContext CreateOrOpen() { // Create or open the memory mapped files. // SharedMemoryRegionView <MlosProxyInternal.GlobalMemoryRegion> globalMemoryRegionView = SharedMemoryRegionView.CreateOrOpen <MlosProxyInternal.GlobalMemoryRegion>(GlobalMemoryMapName, SharedMemorySize); SharedMemoryMapView controlChannelMemoryMapView = SharedMemoryMapView.CreateOrOpen(ControlChannelMemoryMapName, SharedMemorySize); SharedMemoryMapView feedbackChannelMemoryMapView = SharedMemoryMapView.CreateOrOpen(FeedbackChannelMemoryMapName, SharedMemorySize); // Create channel synchronization primitives. // NamedEvent controlChannelNamedEvent = NamedEvent.CreateOrOpen(ControlChannelSemaphoreName); NamedEvent feedbackChannelNamedEvent = NamedEvent.CreateOrOpen(FeedbackChannelSemaphoreName); return(new InterProcessMlosContext( globalMemoryRegionView, controlChannelMemoryMapView, feedbackChannelMemoryMapView, controlChannelNamedEvent, feedbackChannelNamedEvent)); }
/// <summary> /// Initializes a new instance of the <see cref="InterProcessMlosContext"/> class. /// </summary> /// <returns>InterProcessMlosContext instance.</returns> public static InterProcessMlosContext Create() { var targetProcessNamedEvent = NamedEvent.CreateOrOpen(TargetProcessEventName); { bool shouldWaitForTargetProcess = false; try { // Try open a global shared memory and check if the target process is fully initialized. // using var targetProcessMemoryRegionView = SharedMemoryRegionView.OpenExisting <MlosProxyInternal.GlobalMemoryRegion>(GlobalMemoryMapName, MlosInternal.GlobalMemoryRegion.GlobalSharedMemorySize); // If RegisteredSettingsAssemblyCount is 0, the context is not created. // if (targetProcessMemoryRegionView.MemoryRegion().RegisteredSettingsAssemblyCount.Load() == 0) { shouldWaitForTargetProcess = true; } } catch (FileNotFoundException) { // If the target process is not running. // shouldWaitForTargetProcess = true; } if (shouldWaitForTargetProcess) { // If the target process is not fully initialized, wait for the signal. // targetProcessNamedEvent.Wait(); targetProcessNamedEvent.Signal(); } } // Open global memory region. // var globalMemoryRegionView = SharedMemoryRegionView.OpenExisting <MlosProxyInternal.GlobalMemoryRegion>(GlobalMemoryMapName, MlosInternal.GlobalMemoryRegion.GlobalSharedMemorySize); GlobalMemoryRegion globalMemoryRegion = globalMemoryRegionView.MemoryRegion(); // Open existing shared channels memory maps. // globalMemoryRegion.TryOpenExisting( new MlosInternal.MemoryRegionId { Type = MlosInternal.MemoryRegionType.ControlChannel, Index = 0, }, out SharedMemoryMapView controlChannelMemoryMapView); globalMemoryRegion.TryOpenExisting( new MlosInternal.MemoryRegionId { Type = MlosInternal.MemoryRegionType.FeedbackChannel, Index = 0, }, out SharedMemoryMapView feedbackChannelMemoryMapView); // Open existing channel synchronization primitives. // globalMemoryRegion.TryOpenExisting( new MlosInternal.MemoryRegionId { Type = MlosInternal.MemoryRegionType.ControlChannel, Index = 0, }, out NamedEvent controlChannelNamedEvent); globalMemoryRegion.TryOpenExisting( new MlosInternal.MemoryRegionId { Type = MlosInternal.MemoryRegionType.FeedbackChannel, Index = 0, }, out NamedEvent feedbackChannelNamedEvent); return(new InterProcessMlosContext( globalMemoryRegionView, controlChannelMemoryMapView, feedbackChannelMemoryMapView, controlChannelNamedEvent, feedbackChannelNamedEvent, targetProcessNamedEvent)); }
/// <summary> /// Initializes a new instance of the <see cref="InterProcessMlosContext"/> class. /// </summary> /// <param name="globalMemoryRegionView"></param> /// <param name="controlChannelMemoryMapView"></param> /// <param name="feedbackChannelMemoryMapView"></param> /// <param name="controlChannelNamedEvent"></param> /// <param name="feedbackChannelNamedEvent"></param> /// <param name="targetProcessNamedEvent"></param> private InterProcessMlosContext( SharedMemoryRegionView <MlosProxyInternal.GlobalMemoryRegion> globalMemoryRegionView, SharedMemoryMapView controlChannelMemoryMapView, SharedMemoryMapView feedbackChannelMemoryMapView, NamedEvent controlChannelNamedEvent, NamedEvent feedbackChannelNamedEvent, NamedEvent targetProcessNamedEvent) { this.globalMemoryRegionView = globalMemoryRegionView ?? throw new ArgumentNullException(nameof(globalMemoryRegionView)); this.controlChannelMemoryMapView = controlChannelMemoryMapView ?? throw new ArgumentNullException(nameof(controlChannelMemoryMapView)); this.feedbackChannelMemoryMapView = feedbackChannelMemoryMapView ?? throw new ArgumentNullException(nameof(feedbackChannelMemoryMapView)); this.controlChannelNamedEvent = controlChannelNamedEvent ?? throw new ArgumentNullException(nameof(controlChannelNamedEvent)); this.feedbackChannelNamedEvent = feedbackChannelNamedEvent ?? throw new ArgumentNullException(nameof(feedbackChannelNamedEvent)); this.targetProcessNamedEvent = targetProcessNamedEvent ?? throw new ArgumentNullException(nameof(targetProcessNamedEvent)); // Create the shared config manager. // SharedConfigManager = new SharedConfigManager(); MlosProxyInternal.GlobalMemoryRegion globalMemoryRegion = globalMemoryRegionView.MemoryRegion(); // Increase the usage counter. When closing global shared memory, we will decrease the counter. // If there is no process using the shared memory, we will clean the OS resources. On Windows OS, // this is no-op; on Linux, we unlink created files. // globalMemoryRegion.AttachedProcessesCount.FetchAdd(1); // Create the control channel instance. // ControlChannel = new SharedChannel <InterProcessSharedChannelPolicy, SharedChannelSpinPolicy>( buffer: controlChannelMemoryMapView.Buffer, size: (uint)controlChannelMemoryMapView.MemSize, sync: globalMemoryRegion.ControlChannelSynchronization) { ChannelPolicy = { NotificationEvent = controlChannelNamedEvent }, }; // Create the feedback channel instance. // FeedbackChannel = new SharedChannel <InterProcessSharedChannelPolicy, SharedChannelSpinPolicy>( buffer: feedbackChannelMemoryMapView.Buffer, size: (uint)feedbackChannelMemoryMapView.MemSize, sync: globalMemoryRegion.FeedbackChannelSynchronization) { ChannelPolicy = { NotificationEvent = feedbackChannelNamedEvent }, }; // Register config region if available. // if (globalMemoryRegion.TryOpenExisting( new MlosInternal.MemoryRegionId { Type = MlosInternal.MemoryRegionType.SharedConfig, Index = 0, }, out SharedMemoryMapView sharedConfigMemoryMap)) { var sharedMemoryRegionView = new SharedMemoryRegionView <MlosProxyInternal.SharedConfigMemoryRegion>(sharedConfigMemoryMap); SharedConfigManager.RegisterSharedConfigMemoryRegion(sharedMemoryRegionView); } else { sharedConfigMemoryMap?.Dispose(); } }