123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203 |
- using System;
- using System.Collections.Concurrent;
- using System.Collections.Generic;
- using System.Linq;
- using System.Reflection;
- using Vinno.IUS.Common.IO;
- using Vinno.IUS.Common.Log;
- namespace Vinno.IUS.Common.Network.Transfer
- {
- /// <summary>
- /// Message Pool
- /// </summary>
- public static class MessagePool
- {
- private static int _maximumMsgOfEachType = 10;
- private static bool _enabled;
- private static readonly object _getMessageLock = new Object();
- /// <summary>
- /// get Message pool is or not cached
- /// </summary>
- public static bool Enabled => _enabled;
- /// <summary>
- /// Maxinum of messages of each type
- /// </summary>
- public static int MaximumMessageOfEachType => _maximumMsgOfEachType;
- private static readonly ConcurrentDictionary<string, int?> MaxSpecialTypeMessageDictionary = new ConcurrentDictionary<string, int?>();
- private static readonly ConcurrentDictionary<Type, Stack<Message>> AvailableMessagePool = new ConcurrentDictionary<Type, Stack<Message>>();
- /// <summary>
- /// Get idle message from message pool
- /// if all message of type of T is working ,so get new message
- /// </summary>
- /// <typeparam name="T">Message</typeparam>
- /// <returns>T </returns>
- public static T GetMessage<T>() where T : Message
- {
- try
- {
- if (Enabled)
- {
- if (AvailableMessagePool.TryGetValue(typeof(T), out Stack<Message> messageStack))
- {
- lock (_getMessageLock)
- {
- if (messageStack.Count > 0)
- {
- var message = messageStack?.Pop();
- if (message != null)
- {
- return message as T;
- }
- }
- }
- }
- }
- }
- catch (Exception e)
- {
- throw new Exception($"{e}");
- }
- return NewMessage<T>();
- }
- private static T NewMessage<T>() where T : Message
- {
- var message = Activator.CreateInstance(typeof(T), new object[] { }) as Message;
- return message as T;
- }
- /// <summary>
- /// Release current message
- /// this message changed busy to idle
- /// </summary>
- /// <param name="message"></param>
- public static void Recover(Message message)
- {
- if (message == null)
- {
- return;
- }
- if (Enabled)
- {
- try
- {
- var messageType = message.GetType();
- AvailableMessagePool.AddOrUpdate(messageType, s =>
- {
- var stack = new Stack<Message>();
- stack.Push(RevertToMessage(message));
- return stack;
- }, (s, m) =>
- {
- var maximum = _maximumMsgOfEachType;
- MaxSpecialTypeMessageDictionary.TryGetValue(messageType.Name, out int? specialMaximum);
- if (specialMaximum != null)
- {
- maximum = specialMaximum.Value;
- }
- if (m.Count < maximum)
- {
- m.Push(RevertToMessage(message));
- }
- return m;
- });
- }
- catch (Exception e)
- {
- throw new InvalidOperationException($"MessagePool Recover,Error:{e}");
- }
- }
- }
- private static Message RevertToMessage(Message message)
- {
- var properties = message.GetType().GetProperties();
- foreach (var propertyInfo in properties)
- {
-
- if (propertyInfo.CanWrite)
- {
- if (propertyInfo.Name == nameof(message.Element) || propertyInfo.Name == nameof(message.Tag))
- {
- continue;
- }
- var defaultvalue = GetDefaultValue(propertyInfo.PropertyType);
- propertyInfo.SetValue(message, defaultvalue);
- }
- }
- return message;
- }
- private static object GetDefaultValue(Type type)
- {
- object value = null;
- switch (type.Name)
- {
- case nameof(String):
- value = string.Empty;
- break;
- case nameof(Enum):
- value = default(Enum);
- break;
- case nameof(Int32):
- value = 0;
- break;
- case nameof(Int16):
- value = 0;
- break;
- case nameof(Int64):
- value = 0;
- break;
- case nameof(Single):
- value = 0;
- break;
- case nameof(Double):
- value = 0;
- break;
- case nameof(Boolean):
- value = false;
- break;
- case nameof(DateTime):
- value = default(DateTime);
- break;
- case nameof(IBuffer):
- value = new ByteBuffer(new byte[0]);
- break;
- case "Byte[]":
- value = new byte[0];
- break;
- }
- return value;
- }
- public static void Initialize(IMessagePoolConfig config)
- {
- if (config !=null)
- {
- _enabled = config.Enabled;
- _maximumMsgOfEachType = config.MaximumNumberOfMessages;
- foreach (var key in config.CustomMessageCountDictionary)
- {
- MaxSpecialTypeMessageDictionary.GetOrAdd(key.Key, key.Value);
- }
- }
- }
- }
- /// <summary>
- /// interface message pool config
- /// </summary>
- public interface IMessagePoolConfig
- {
- /// <summary>
- /// MessagePool Enabled
- /// </summary>
- bool Enabled { get; }
- /// <summary>
- /// Maximum number of messages per type
- /// </summary>
- int MaximumNumberOfMessages { get; }
- /// <summary>
- /// custom message count,string:message name,int:maximum count of message
- /// </summary>
- Dictionary<string, int> CustomMessageCountDictionary { get; }
- }
- }
|