Line data Source code
1 : // Copyright 2024 Accenture.
2 :
3 : #pragma once
4 :
5 : #include "platform/estdint.h"
6 :
7 : /**
8 : * This data type provides an abstract runtime mapping between a common shared I/O and
9 : * higher-level instances that can use this I/O.
10 : *
11 : * Usage: create an instance of dynamic client inside the class responsible for distribution of the
12 : * I/O channels that have to be dynamic, and provide public methods for adding and removing the
13 : * dynamic client.
14 : *
15 : * @tparam T - type that contains client's index + index of a channel inside a client.
16 : * @tparam IDynamicClient - type of an object that should be registered as a dynamic client
17 : * @tparam Size - bit width for count of clients, number of clients then is 2^Size
18 : * @tparam dynamicChannelsCount - number of dynamic channels that can be stored in this structure
19 : * @tparam dynamicClientsCount - number of dynamic clients that use this proxy.
20 : */
21 : template<
22 : typename T,
23 : typename IDynamicClient,
24 : int32_t Size,
25 : int32_t dynamicChannelsCount,
26 : int32_t dynamicClientsCount = 0>
27 : struct dynamicClient
28 : {
29 : //[Enum_start]
30 :
31 : enum
32 : {
33 : bitWidthDynamicClientCount = Size,
34 : bitWidthDynamicClientsChannelCount = ((sizeof(T) * 8) - bitWidthDynamicClientCount),
35 : maxDynamicClientCount = (0x01U << bitWidthDynamicClientCount),
36 : channelInvalid = (0x01U << bitWidthDynamicClientsChannelCount) - 1U,
37 : dynamicClientInvalid = (0x01U << bitWidthDynamicClientCount) - 1U,
38 : dynamicChannels = dynamicChannelsCount
39 : };
40 :
41 : //[Enum_end]
42 :
43 : /**
44 : * If dynamicClientsCount is not explicitly specified, maximum possible dynamicClientsCount is
45 : * selected.
46 : */
47 : static T const dynamicClientCountCfg
48 : = (dynamicClientsCount == 0 ? static_cast<int32_t>(maxDynamicClientCount)
49 : : dynamicClientsCount);
50 :
51 : /**
52 : * This structure is responsible for distributing number of clients and number of
53 : * instances per client.
54 : * If T is 8 bit, then dynamicClient can devote N bits to instances' indexing and (8-N) bits to
55 : * indexing inside a single client.
56 : * Example:
57 : * T = uint8_t, Size = 2 --> instanceNumber is in [0..3], numberInsideClient is in [0..31]
58 : */
59 : using tDynamicClientCfg = struct
60 : {
61 : T numberInsideClient : bitWidthDynamicClientsChannelCount;
62 : T instanceNumber : bitWidthDynamicClientCount;
63 : };
64 :
65 : // METHOD_START
66 : /**
67 : * Clean all Clients
68 : */
69 : static void cleanDynamicClients();
70 :
71 : /**
72 : * Check Valid Channel
73 : * @param : number of channel
74 : * @ret : true is valid ,false - not valid
75 : */
76 : static bool getClientValid(T channel);
77 :
78 : /**
79 : * setDynamicClient
80 : * @param : channel number ,
81 : * @param : numberInsideClient , channel number inside the Client
82 : * @param : IDynamicClient* client
83 : * @ret : true , false
84 : */
85 : bool setDynamicClient(T channel, T numberInsideClient, IDynamicClient* client);
86 :
87 : /**
88 : * clearDynamicClient
89 : * @param : channel number ,
90 : * @ret : true , false
91 : */
92 : bool clearDynamicClient(T channel);
93 :
94 : /**
95 : * getClientInstance, channel has to be first checked using `getClientValid()` method
96 : * @param : number of channel
97 : * @ret : IDynamicClient*
98 : */
99 3 : static inline IDynamicClient* getClientInstance(T channel)
100 : {
101 3 : return (fpDynamicClient[fDynamicChannelCfg[channel].instanceNumber]);
102 : }
103 :
104 3 : static inline T getChannelInsideClient(T channel)
105 : {
106 3 : return (fDynamicChannelCfg[channel].numberInsideClient);
107 : }
108 :
109 : static tDynamicClientCfg fDynamicChannelCfg[dynamicChannels];
110 : static IDynamicClient* fpDynamicClient[dynamicClientCountCfg];
111 :
112 : // METHOD_END
113 : };
114 :
115 : template<
116 : typename T,
117 : typename IDynamicClient,
118 : int32_t Size,
119 : int32_t dynamicChannelsCount,
120 : int32_t dynamicClientCount>
121 : typename dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
122 : tDynamicClientCfg
123 : dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
124 : fDynamicChannelCfg[dynamicChannels];
125 :
126 : template<
127 : typename T,
128 : typename IDynamicClient,
129 : int32_t Size,
130 : int32_t dynamicChannels,
131 : int32_t dynamicClientCount>
132 : IDynamicClient* dynamicClient<T, IDynamicClient, Size, dynamicChannels, dynamicClientCount>::
133 : fpDynamicClient[dynamicClientCountCfg];
134 :
135 : template<
136 : typename T,
137 : typename IDynamicClient,
138 : int32_t Size,
139 : int32_t dynamicChannelsCount,
140 : int32_t dynamicClientCount>
141 : void dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
142 : cleanDynamicClients()
143 : {
144 : for (int32_t i = 0; i < (dynamicClientCountCfg); i++)
145 : {
146 : fpDynamicClient[i] = nullptr;
147 : }
148 : for (int32_t i = 0; i < (dynamicChannels); i++)
149 : {
150 : fDynamicChannelCfg[i].numberInsideClient = channelInvalid;
151 : fDynamicChannelCfg[i].instanceNumber = dynamicClientInvalid;
152 : }
153 : }
154 :
155 : template<
156 : typename T,
157 : typename IDynamicClient,
158 : int32_t Size,
159 : int32_t dynamicChannelsCount,
160 : int32_t dynamicClientCount>
161 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
162 : getClientValid(T channel)
163 : {
164 : bool ret = false;
165 : if (channel < dynamicChannels)
166 : {
167 : T instanceNumber = fDynamicChannelCfg[channel].instanceNumber;
168 : if (instanceNumber < dynamicClientCountCfg)
169 : {
170 : if ((instanceNumber < dynamicClientInvalid)
171 : && (fDynamicChannelCfg[channel].numberInsideClient < channelInvalid)
172 : && (fpDynamicClient[instanceNumber] != nullptr))
173 : {
174 : ret = true;
175 : }
176 : }
177 : }
178 :
179 : return ret;
180 : }
181 :
182 : template<
183 : typename T,
184 : typename IDynamicClient,
185 : int32_t Size,
186 : int32_t dynamicChannelsCount,
187 : int32_t dynamicClientCount>
188 3 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
189 : setDynamicClient(T channel, T numberInsideClient, IDynamicClient* client)
190 : {
191 : // range of outputNumber check
192 3 : if (numberInsideClient >= channelInvalid)
193 : {
194 : return false;
195 : }
196 :
197 3 : if (channel < dynamicChannels) // number is out of range
198 : {
199 : uint8_t mySlot = 0xFFU;
200 : uint8_t availableClient = 0xFFU;
201 20 : for (T i = 0; (i < dynamicClientCountCfg) && (availableClient == 0xFFU); i++)
202 : {
203 17 : if (client == fpDynamicClient[i])
204 : {
205 1 : availableClient = static_cast<uint8_t>(i);
206 : }
207 17 : if (fpDynamicClient[i] == nullptr)
208 : {
209 15 : if (mySlot == 0xFFU)
210 : {
211 2 : mySlot = static_cast<uint8_t>(i);
212 : }
213 : }
214 : }
215 : // Occupy slot for client
216 3 : if (availableClient == 0xFFU) // not in Map yet
217 : {
218 2 : if (mySlot != 0xFFU) // placed
219 : {
220 2 : fpDynamicClient[mySlot] = client;
221 : }
222 : else // no free place
223 : {
224 : return false;
225 : }
226 : }
227 : else
228 : {
229 : mySlot = availableClient;
230 : }
231 :
232 3 : fDynamicChannelCfg[channel].numberInsideClient = numberInsideClient;
233 3 : fDynamicChannelCfg[channel].instanceNumber = mySlot;
234 3 : return true;
235 : }
236 : else
237 : {
238 : return false;
239 : }
240 : }
241 :
242 : template<
243 : typename T,
244 : typename IDynamicClient,
245 : int32_t Size,
246 : int32_t dynamicChannelsCount,
247 : int32_t dynamicClientCount>
248 : bool dynamicClient<T, IDynamicClient, Size, dynamicChannelsCount, dynamicClientCount>::
249 : clearDynamicClient(T channel)
250 : {
251 : if (channel < dynamicChannels) // number is out of range
252 : {
253 : T instanceNumber = fDynamicChannelCfg[channel].instanceNumber;
254 : IDynamicClient* client = fpDynamicClient[instanceNumber];
255 :
256 : fDynamicChannelCfg[channel].numberInsideClient = channelInvalid;
257 : fDynamicChannelCfg[channel].instanceNumber = dynamicClientInvalid;
258 : // look for other outputs
259 :
260 : if ((client == nullptr) || (instanceNumber >= dynamicClientCountCfg))
261 : {
262 : return true;
263 : }
264 :
265 : uint8_t availableClient = 0xFFU;
266 : for (T i = 0; i < dynamicClientCountCfg; i++)
267 : {
268 : if (client == fpDynamicClient[i])
269 : {
270 : availableClient = i; // Found a client
271 : break;
272 : }
273 : }
274 : if (availableClient != 0xFFU)
275 : {
276 : bool found = false;
277 : for (T i = 0; i < dynamicChannels; i++)
278 : {
279 : if (fDynamicChannelCfg[i].instanceNumber == availableClient)
280 : {
281 : found = true;
282 : break;
283 : }
284 : }
285 : if (!found)
286 : {
287 : // No client was found, the link can be deleted.
288 : fpDynamicClient[availableClient] = nullptr;
289 : }
290 : }
291 :
292 : return true;
293 : }
294 : else
295 : {
296 : return false;
297 : }
298 : }
|