public static unsafe void Advise <T>(this Ipc scope, string method, Action <T> proxy) where T : struct { CallFrameListDescriptor *descriptor = null; //scope.GetObject<CallFrameListDescriptor>("CallFrameListDescriptor:" + method); CallFrameListNode * node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + descriptor->CallFrameListHead); //Seek to the end of the frame list while (Interlocked.CompareExchange(ref node->NextCallFrame, 0, 0) != 0) { node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + node->NextCallFrame); } //The current value of node is the one before any calls we'd process new Thread(() => { while (true) { //while there's no node to process, wait patiently while (Interlocked.CompareExchange(ref node->NextCallFrame, 0, 0) == 0) { Thread.Sleep(1); } //Move to the unprocessed frame node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + node->NextCallFrame); //Process it Ipc <T> frameData = scope.GetObject <T>("CallFrame:" + node->FrameId); proxy(frameData.Value); } }).Start(); }
public static unsafe void QueueCall <T>(this Ipc scope, string method, T frameContent) where T : struct { CallFrameListDescriptor *descriptor = null; //scope.GetObject<CallFrameListDescriptor>("CallFrameListDescriptor:" + method); CallFrameListNode * node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + descriptor->CallFrameListHead); Luid id = new Luid { Whole = Guid.NewGuid() }; MemoryMappedFile data; //Get a space to store the frame in do { try { data = MemoryMappedFile.CreateNew($"{scope.Name}:CallFrames:{id.Low}", Marshal.SizeOf <T>(), MemoryMappedFileAccess.ReadWrite); //Write frameContent into data break; } catch { id = new Luid { Whole = Guid.NewGuid() }; } } while (true); //Acquire the tail of the call frame list while (Interlocked.CompareExchange(ref node->NextCallFrame, id.Low, 0) != 0) { node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + node->NextCallFrame); } node = null; //scope.GetObject<CallFrameListNode>("CallFrameListNode:" + id.Low); //Write the current time to the call frame so it may be reclaimed at some point //write Interlocked.Exchange(ref descriptor->CallFrameListHead, id.Low); }
public Ipc <T> GetObject <T>(string name) where T : struct { return(Ipc <T> .CreateOrAttach($"{_name}:obj:{name}")); }
public static void Main(string[] args) { Console.Title = Process.GetCurrentProcess().Id.ToString(); Ipc scope = Ipc.Scope("Demo"); Guid allBinding = scope.Bind("MyEvent", DoThing); string targettedEvent = "MyEvent" + Process.GetCurrentProcess().Id; scope.Bind("cls" + Process.GetCurrentProcess().Id, Console.Clear); Guid binding = scope.Bind(targettedEvent, DoThing); IFoo foo = scope.GetFoo("Foo"); _foo = foo; while (true) { string cmd = Console.ReadLine(); string v; switch (cmd) { case "r": scope.Call("MyEvent"); break; case "d": scope.Unbind(allBinding); break; case "rr": allBinding = scope.Bind("MyEvent", DoThing); break; case "x": v = Console.ReadLine(); if (v == null) { break; } foo.X = uint.Parse(v); break; case "y": v = Console.ReadLine(); if (v == null) { break; } foo.Y = uint.Parse(v); break; case "q": scope.Unbind(allBinding); scope.Unbind(binding); Environment.Exit(0); return; default: if (cmd != null && cmd.StartsWith("msg:")) { scope.Call(cmd.Substring(4)); } break; } } }