Thread.hx 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. /*
  2. * Copyright (C)2005-2019 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. */
  22. package sys.thread;
  23. import cs.system.threading.Thread as NativeThread;
  24. import cs.system.WeakReference;
  25. import cs.Lib;
  26. abstract Thread(HaxeThread) {
  27. inline function new(thread:HaxeThread) {
  28. this = thread;
  29. }
  30. public static function create(cb:Void->Void):Thread {
  31. var native = new NativeThread(cb);
  32. native.IsBackground = true;
  33. var hx = HaxeThread.allocate(native);
  34. native.Start();
  35. return new Thread(hx);
  36. }
  37. public static inline function current():Thread {
  38. return new Thread(HaxeThread.get(NativeThread.CurrentThread));
  39. }
  40. public static function readMessage(block:Bool):Dynamic {
  41. return current().readMessageImpl(block);
  42. }
  43. public inline function sendMessage(msg:Dynamic):Void {
  44. this.sendMessage(msg);
  45. }
  46. inline function readMessageImpl(block:Bool):Dynamic {
  47. return this.readMessage(block);
  48. }
  49. }
  50. private class HaxeThread {
  51. static final threads = new Map<Int, WeakReference>();
  52. static var allocateCount = 0;
  53. public final native:NativeThread;
  54. final messages = new Deque<Dynamic>();
  55. public static function get(native:NativeThread):HaxeThread {
  56. var native = NativeThread.CurrentThread;
  57. var ref:Null<WeakReference> = null;
  58. Lib.lock(threads, {
  59. var key = native.ManagedThreadId;
  60. ref = threads.get(key);
  61. });
  62. if (ref == null || !ref.IsAlive) {
  63. return allocate(native);
  64. }
  65. return ref.Target;
  66. }
  67. public static function allocate(native:NativeThread):HaxeThread {
  68. allocateCount++;
  69. inline function cleanup() {
  70. if (allocateCount % 100 == 0) {
  71. for (key => ref in threads) {
  72. if (!ref.IsAlive) {
  73. threads.remove(key);
  74. }
  75. }
  76. }
  77. }
  78. var hx = new HaxeThread(native);
  79. var ref = new WeakReference(hx);
  80. Lib.lock(threads, {
  81. cleanup();
  82. threads.set(native.ManagedThreadId, ref);
  83. });
  84. return hx;
  85. }
  86. public function new(native:NativeThread) {
  87. this.native = native;
  88. }
  89. public inline function readMessage(block:Bool):Dynamic {
  90. return messages.pop(block);
  91. }
  92. public function sendMessage(msg:Dynamic):Void {
  93. messages.add(msg);
  94. }
  95. }