1 /**
2  * Miscellaneous types.
3  */
4 module asynchronous.types;
5 
6 import std.algorithm;
7 import std.container.array;
8 import std.exception;
9 import std.traits;
10 
11 struct Coroutine
12 {
13 }
14 
15 template UNSPECIFIED(E)
16 if (is(E == enum))
17 {
18     E UNSPECIFIED()
19     {
20         return cast(E) 0;
21     }
22 }
23 
24 /**
25  * This operation was cancelled.
26  */
27 class CancelledException : Exception
28 {
29     this(string message = null, string file = __FILE__, size_t line = __LINE__,
30         Throwable next = null) @safe pure nothrow
31     {
32         super(message, file, line, next);
33     }
34 }
35 
36 /**
37  * This operation is not allowed in this state.
38  */
39 class InvalidStateException : Exception
40 {
41     this(string message = null, string file = __FILE__, size_t line = __LINE__,
42         Throwable next = null) @safe pure nothrow
43     {
44         super(message, file, line, next);
45     }
46 }
47 
48 /**
49  * This operation exceeded the given deadline.
50  */
51 class TimeoutException : Exception
52 {
53     this(string message = null, string file = __FILE__, size_t line = __LINE__,
54         Throwable next = null) @safe pure nothrow
55     {
56         super(message, file, line, next);
57     }
58 }
59 
60 /**
61  * This operation is not implemented.
62  */
63 class NotImplementedException : Exception
64 {
65     this(string message = null, string file = __FILE__, size_t line = __LINE__,
66         Throwable next = null) @safe pure nothrow
67     {
68         super(message, file, line, next);
69     }
70 }
71 
72 class ResourcePool(T, TArgs...)
73 if (is(T == class))
74 {
75     private size_t inUseCount;
76     private Array!bool inUseFlags;
77     private Array!T resources;
78 
79     private TArgs tArgs;
80 
81     this(TArgs tArgs)
82     {
83         this.tArgs = tArgs;
84     }
85 
86     T acquire(TResetArgs...)(TResetArgs tResetArgs)
87     out (result)
88     {
89         assert(result !is null);
90     }
91     body
92     {
93         auto count = inUseFlags[].countUntil!"!a";
94         T result = null;
95 
96         if (count >= 0)
97         {
98             inUseFlags[count] = true;
99             result = resources[count];
100         }
101         else
102         {
103             inUseFlags.insertBack(true);
104             result = new T(tArgs);
105             resources.insertBack(result);
106         }
107 
108         static if (hasMember!(T, "reset"))
109             result.reset(tResetArgs);
110 
111         ++inUseCount;
112         return result;
113     }
114 
115     void release(T t)
116     {
117         auto count = resources[].countUntil!(a => a is t);
118 
119         enforce(count >= 0, "Cannot release non-acquired resource");
120 
121         static if (hasMember!(T, "reset"))
122             resources[count].reset;
123 
124         inUseFlags[count] = false;
125         --inUseCount;
126     }
127 
128     bool empty()
129     {
130         return inUseCount == 0;
131     }
132 
133     override string toString() const
134     {
135         import std.format : format;
136 
137         return "%s(length: %s, capacity: %s)".format(typeid(this),
138             inUseCount, inUseFlags.length);
139     }
140 }