1 /******************************************************************************* 2 3 Registry implementation for multi-threaded access 4 5 This registry allows to look up a `Tid` based on a `string`. 6 It is extracted from the `std.concurrency` module to make it reusable 7 8 *******************************************************************************/ 9 10 module geod24.Registry; 11 12 import core.sync.mutex; 13 import geod24.concurrency; 14 15 /// Ditto 16 public shared struct Registry 17 { 18 private Tid[string] tidByName; 19 private string[][Tid] namesByTid; 20 private Mutex registryLock; 21 22 /// Initialize this registry, creating the Mutex 23 public void initialize() @safe nothrow 24 { 25 this.registryLock = new shared Mutex; 26 } 27 28 /** 29 * Gets the Tid associated with name. 30 * 31 * Params: 32 * name = The name to locate within the registry. 33 * 34 * Returns: 35 * The associated Tid or Tid.init if name is not registered. 36 */ 37 Tid locate(string name) 38 { 39 synchronized (registryLock) 40 { 41 if (shared(Tid)* tid = name in this.tidByName) 42 return *cast(Tid*)tid; 43 return Tid.init; 44 } 45 } 46 47 /** 48 * Associates name with tid. 49 * 50 * Associates name with tid in a process-local map. When the thread 51 * represented by tid terminates, any names associated with it will be 52 * automatically unregistered. 53 * 54 * Params: 55 * name = The name to associate with tid. 56 * tid = The tid register by name. 57 * 58 * Returns: 59 * true if the name is available and tid is not known to represent a 60 * defunct thread. 61 */ 62 bool register(string name, Tid tid) 63 { 64 synchronized (registryLock) 65 { 66 if (name in tidByName) 67 return false; 68 if (tid.mbox.isClosed) 69 return false; 70 this.namesByTid[tid] ~= name; 71 this.tidByName[name] = cast(shared)tid; 72 return true; 73 } 74 } 75 76 /** 77 * Removes the registered name associated with a tid. 78 * 79 * Params: 80 * name = The name to unregister. 81 * 82 * Returns: 83 * true if the name is registered, false if not. 84 */ 85 bool unregister(string name) 86 { 87 import std.algorithm.mutation : remove, SwapStrategy; 88 import std.algorithm.searching : countUntil; 89 90 synchronized (registryLock) 91 { 92 if (shared(Tid)* tid = name in this.tidByName) 93 { 94 auto allNames = *cast(Tid*)tid in this.namesByTid; 95 auto pos = countUntil(*allNames, name); 96 remove!(SwapStrategy.unstable)(*allNames, pos); 97 this.tidByName.remove(name); 98 return true; 99 } 100 return false; 101 } 102 } 103 }