BackgroundContextWorker.cs 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using Ryujinx.Common;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Threading;
  5. namespace Ryujinx.Graphics.OpenGL
  6. {
  7. unsafe class BackgroundContextWorker : IDisposable
  8. {
  9. [ThreadStatic]
  10. public static bool InBackground;
  11. private readonly Thread _thread;
  12. private bool _running;
  13. private readonly AutoResetEvent _signal;
  14. private readonly Queue<Action> _work;
  15. private readonly ObjectPool<ManualResetEventSlim> _invokePool;
  16. private readonly IOpenGLContext _backgroundContext;
  17. public BackgroundContextWorker(IOpenGLContext backgroundContext)
  18. {
  19. _backgroundContext = backgroundContext;
  20. _running = true;
  21. _signal = new AutoResetEvent(false);
  22. _work = new Queue<Action>();
  23. _invokePool = new ObjectPool<ManualResetEventSlim>(() => new ManualResetEventSlim(), 10);
  24. _thread = new Thread(Run);
  25. _thread.Start();
  26. }
  27. public bool HasContext() => _backgroundContext.HasContext();
  28. private void Run()
  29. {
  30. InBackground = true;
  31. _backgroundContext.MakeCurrent();
  32. while (_running)
  33. {
  34. Action action;
  35. lock (_work)
  36. {
  37. _work.TryDequeue(out action);
  38. }
  39. if (action != null)
  40. {
  41. action();
  42. }
  43. else
  44. {
  45. _signal.WaitOne();
  46. }
  47. }
  48. _backgroundContext.Dispose();
  49. }
  50. public void Invoke(Action action)
  51. {
  52. ManualResetEventSlim actionComplete = _invokePool.Allocate();
  53. lock (_work)
  54. {
  55. _work.Enqueue(() =>
  56. {
  57. action();
  58. actionComplete.Set();
  59. });
  60. }
  61. _signal.Set();
  62. actionComplete.Wait();
  63. actionComplete.Reset();
  64. _invokePool.Release(actionComplete);
  65. }
  66. public void Dispose()
  67. {
  68. _running = false;
  69. _signal.Set();
  70. _thread.Join();
  71. _signal.Dispose();
  72. }
  73. }
  74. }