AsyncLogTargetWrapper.cs 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. using System;
  2. using System.Collections.Concurrent;
  3. using System.Threading;
  4. namespace Ryujinx.Common.Logging
  5. {
  6. public enum AsyncLogTargetOverflowAction
  7. {
  8. /// <summary>
  9. /// Block until there's more room in the queue
  10. /// </summary>
  11. Block = 0,
  12. /// <summary>
  13. /// Discard the overflowing item
  14. /// </summary>
  15. Discard = 1
  16. }
  17. public class AsyncLogTargetWrapper : ILogTarget
  18. {
  19. private ILogTarget _target;
  20. private Thread _messageThread;
  21. private BlockingCollection<LogEventArgs> _messageQueue;
  22. private readonly int _overflowTimeout;
  23. public AsyncLogTargetWrapper(ILogTarget target)
  24. : this(target, -1, AsyncLogTargetOverflowAction.Block)
  25. { }
  26. public AsyncLogTargetWrapper(ILogTarget target, int queueLimit, AsyncLogTargetOverflowAction overflowAction)
  27. {
  28. _target = target;
  29. _messageQueue = new BlockingCollection<LogEventArgs>(queueLimit);
  30. _overflowTimeout = overflowAction == AsyncLogTargetOverflowAction.Block ? -1 : 0;
  31. _messageThread = new Thread(() => {
  32. while (!_messageQueue.IsCompleted)
  33. {
  34. try
  35. {
  36. _target.Log(this, _messageQueue.Take());
  37. }
  38. catch (InvalidOperationException)
  39. {
  40. // IOE means that Take() was called on a completed collection.
  41. // Some other thread can call CompleteAdding after we pass the
  42. // IsCompleted check but before we call Take.
  43. // We can simply catch the exception since the loop will break
  44. // on the next iteration.
  45. }
  46. }
  47. });
  48. _messageThread.IsBackground = true;
  49. _messageThread.Start();
  50. }
  51. public void Log(object sender, LogEventArgs e)
  52. {
  53. if (!_messageQueue.IsAddingCompleted)
  54. {
  55. _messageQueue.TryAdd(e, _overflowTimeout);
  56. }
  57. }
  58. public void Dispose()
  59. {
  60. _messageQueue.CompleteAdding();
  61. _messageThread.Join();
  62. }
  63. }
  64. }