private static DynamicMethod BuildDispatchingMethod(IActor handler, IStructSizeCounter counter, Func <Type, int> messageIdGetter) { var handlerType = handler.GetType(); var handleMethods = ActorRegistry.GetHandleMethods(handlerType) .ToDictionary(m => messageIdGetter(m.GetParameters()[1].ParameterType.GetElementType()), m => m) .OrderBy(kvp => kvp.Key) .ToArray(); var dm = new DynamicMethod("ReadMessagesFor_" + handlerType.Namespace.Replace(".", "_") + handlerType.Name, typeof(void), new[] { typeof(MessageReader), typeof(int), typeof(ByteChunk) }, handlerType.Assembly.Modules.First(), true); var actorField = typeof(MessageReader).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Single(fi => fi.FieldType == typeof(IActor)); var il = dm.GetILGenerator(); // push handler il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, actorField); il.Emit(OpCodes.Castclass, handlerType); var endLbl = il.DefineLabel(); // dispatch foreach (var method in handleMethods) { var lbl = il.DefineLabel(); il.Emit(OpCodes.Ldarg_1); // messageTypeId il.Emit(OpCodes.Ldc_I4, method.Key); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brfalse_S, lbl); // push envelope il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof(ByteChunk).GetField("Pointer")); //var messageType = method.Value.GetParameters()[1].ParameterType.GetElementType(); //il.Emit(OpCodes.Ldc_I4, (int)Marshal.OffsetOf(messageType, Envelope.FieldName)); //il.Emit(OpCodes.Add); // push message il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof(ByteChunk).GetField("Pointer")); il.EmitCall(OpCodes.Callvirt, method.Value, null); il.Emit(OpCodes.Br_S, endLbl); il.MarkLabel(lbl); } // nothing was called, pop il.Emit(OpCodes.Pop); // end label il.MarkLabel(endLbl); il.Emit(OpCodes.Ret); return(dm); }
private static DynamicMethod BuildDispatchingMethod(IActor handler, IStructSizeCounter counter, Func<Type, int> messageIdGetter) { var handlerType = handler.GetType(); var handleMethods = ActorRegistry.GetHandleMethods(handlerType) .ToDictionary(m => messageIdGetter(m.GetParameters()[1].ParameterType.GetElementType()), m => m) .OrderBy(kvp => kvp.Key) .ToArray(); var dm = new DynamicMethod("ReadMessagesFor_" + handlerType.Namespace.Replace(".", "_") + handlerType.Name, typeof (void), new[] {typeof (MessageReader), typeof (int), typeof (ByteChunk)}, handlerType.Assembly.Modules.First(), true); var actorField = typeof (MessageReader).GetFields(BindingFlags.NonPublic | BindingFlags.Instance) .Single(fi => fi.FieldType == typeof (IActor)); var il = dm.GetILGenerator(); // push handler il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, actorField); il.Emit(OpCodes.Castclass, handlerType); var endLbl = il.DefineLabel(); // dispatch foreach (var method in handleMethods) { var lbl = il.DefineLabel(); il.Emit(OpCodes.Ldarg_1); // messageTypeId il.Emit(OpCodes.Ldc_I4, method.Key); il.Emit(OpCodes.Ceq); il.Emit(OpCodes.Brfalse_S, lbl); // push envelope il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof (ByteChunk).GetField("Pointer")); //var messageType = method.Value.GetParameters()[1].ParameterType.GetElementType(); //il.Emit(OpCodes.Ldc_I4, (int)Marshal.OffsetOf(messageType, Envelope.FieldName)); //il.Emit(OpCodes.Add); // push message il.Emit(OpCodes.Ldarg_2); il.Emit(OpCodes.Ldfld, typeof (ByteChunk).GetField("Pointer")); il.EmitCall(OpCodes.Callvirt, method.Value, null); il.Emit(OpCodes.Br_S, endLbl); il.MarkLabel(lbl); } // nothing was called, pop il.Emit(OpCodes.Pop); // end label il.MarkLabel(endLbl); il.Emit(OpCodes.Ret); return dm; }
public MessageReader(IActor handler, IStructSizeCounter counter, Func<Type, int> messageIdGetter) { _handler = handler; var dm = BuildDispatchingMethod(handler, counter, messageIdGetter); _reader = (Action<MessageReader, int, ByteChunk>) dm.CreateDelegate(typeof (Action<MessageReader, int, ByteChunk>)); }
public MessageReader(IActor handler, IStructSizeCounter counter, Func <Type, int> messageIdGetter) { _handler = handler; var dm = BuildDispatchingMethod(handler, counter, messageIdGetter); _reader = (Action <MessageReader, int, ByteChunk>) dm.CreateDelegate(typeof(Action <MessageReader, int, ByteChunk>)); }
public static LongLookup<MessageMetadata> BuildMetadata(IStructSizeCounter counter, Func<Type, int> messageIdGetter, Type[] structTypes) { var keys = structTypes.Select(GetKey).ToArray(); var values = structTypes.Select(type => new MessageMetadata(messageIdGetter(type), (short) counter.GetSize(type), (short) (int) Marshal.OffsetOf(type, Envelope.FieldName))).ToArray(); var metadata = new LongLookup<MessageMetadata>(keys, values); return metadata; }
public static LongLookup <MessageMetadata> BuildMetadata(IStructSizeCounter counter, Func <Type, int> messageIdGetter, Type[] structTypes) { var keys = structTypes.Select(GetKey).ToArray(); var values = structTypes.Select(type => new MessageMetadata(messageIdGetter(type), (short)counter.GetSize(type), (short)(int)Marshal.OffsetOf(type, Envelope.FieldName))).ToArray(); var metadata = new LongLookup <MessageMetadata>(keys, values); return(metadata); }
public CompositeActor(IActor[] actors, IStructSizeCounter counter, Func <Type, int> messageIdGetter) { if (actors.Length > MaxActors) { throw new ArgumentException($"Too many actors. Can composite only up to {MaxActors}"); } var messageTypes = actors.Select(a => new ActorDescriptor(a)) .SelectMany(descriptor => descriptor.HandledMessageTypes) .Distinct() .ToArray(); Descriptor = new ActorDescriptor(messageTypes); _readers = actors.Select(a => new MessageReader(a, counter, messageIdGetter)).ToArray(); _count = _readers.Length; _messageMap = BuildMessageMap(actors, messageIdGetter); _batchAware = actors.OfType <IBatchAware>().ToArray(); }
public CompositeActor(IActor[] actors, IStructSizeCounter counter, Func<Type, int> messageIdGetter) { if (actors.Length > MaxActors) { throw new ArgumentException($"Too many actors. Can composite only up to {MaxActors}"); } var messageTypes = actors.Select(a => new ActorDescriptor(a)) .SelectMany(descriptor => descriptor.HandledMessageTypes) .Distinct() .ToArray(); Descriptor = new ActorDescriptor(messageTypes); _readers = actors.Select(a => new MessageReader(a, counter, messageIdGetter)).ToArray(); _count = _readers.Length; _messageMap = BuildMessageMap(actors, messageIdGetter); _batchAware = actors.OfType<IBatchAware>().ToArray(); }
public Runner(IRingBuffer buffer, IStructSizeCounter counter, Func <Type, int> messageIdGetter, int batchSize, params IActor[] actors) { Buffer = buffer; _batchSize = batchSize; if (actors.Length > 1) { var actor = new CompositeActor(actors, counter, messageIdGetter); _batchAware = actor; _handler = actor.MessageHandler; Descriptor = actor.Descriptor; } else { _handler = new MessageReader(actors[0], counter, messageIdGetter).MessageHandlerImpl; Descriptor = new ActorDescriptor(actors[0]); _batchAware = actors[0] as IBatchAware; } }
public Runner(IRingBuffer buffer, IStructSizeCounter counter, Func<Type, int> messageIdGetter, int batchSize, params IActor[] actors) { Buffer = buffer; _batchSize = batchSize; if (actors.Length > 1) { var actor = new CompositeActor(actors, counter, messageIdGetter); _batchAware = actor; _handler = actor.MessageHandler; Descriptor = actor.Descriptor; } else { _handler = new MessageReader(actors[0], counter, messageIdGetter).MessageHandlerImpl; Descriptor = new ActorDescriptor(actors[0]); _batchAware = actors[0] as IBatchAware; } }
public static IMessageWriter Build(IStructSizeCounter counter, Func <Type, int> messageIdGetter, Type[] structTypes, ModuleBuilder module) { const string metadataFieldName = "metadata"; var writer = module.DefineType("MessageWriter", typeof(SomeWriter).Attributes, typeof(object)); writer.PadBefore(); var metadataField = writer.DefineField(metadataFieldName, LookupType, FieldAttributes.Public); writer.PadAfter(); writer.AddInterfaceImplementation(typeof(IMessageWriter)); BuildWriteMethod(writer, metadataField); // initialize var metadata = MessageMetadata.BuildMetadata(counter, messageIdGetter, structTypes); var instance = Activator.CreateInstance(writer.CreateType()); instance.GetType().GetField(metadataFieldName).SetValue(instance, metadata); return((IMessageWriter)instance); }