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 }