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