µOS++ IIIe Reference 7.0.0
The third edition of µOS++, a POSIX inspired open source framework, written in C++
Loading...
Searching...
No Matches
device-registry.h
Go to the documentation of this file.
1/*
2 * This file is part of the µOS++ distribution.
3 * (https://github.com/micro-os-plus)
4 * Copyright (c) 2015-2023 Liviu Ionescu. All rights reserved.
5 *
6 * Permission to use, copy, modify, and/or distribute this software
7 * for any purpose is hereby granted, under the terms of the MIT license.
8 *
9 * If a copy of the license was not distributed with this file, it can
10 * be obtained from https://opensource.org/licenses/mit/.
11 */
12
13#ifndef CMSIS_PLUS_POSIX_IO_DEVICE_REGISTRY_H_
14#define CMSIS_PLUS_POSIX_IO_DEVICE_REGISTRY_H_
15
16// ----------------------------------------------------------------------------
17
18#if defined(__cplusplus)
19
20// ----------------------------------------------------------------------------
21
22#if defined(OS_USE_OS_APP_CONFIG_H)
23#include <cmsis-plus/os-app-config.h>
24#endif
25
28
29#include <cstddef>
30#include <cassert>
31#include <cstring>
32
33// ----------------------------------------------------------------------------
34
35#pragma GCC diagnostic push
36#if defined(__clang__)
37#pragma clang diagnostic ignored "-Wc++98-compat"
38#endif
39
40// ----------------------------------------------------------------------------
41
42namespace os
43{
44 namespace posix
45 {
46 // ========================================================================
47
53 template<typename T>
55 {
56 public:
57
58 using value_type = T;
59 using pointer = T*;
60 using reference = T&;
61
62 // --------------------------------------------------------------------
63
69 public:
70
71 // Do not allow to create instances of this class.
72 device_registry () = delete;
73
78 // The rule of five.
79 device_registry (const value_type&) = delete;
80 device_registry (value_type&&) = delete;
82 operator= (const value_type&) = delete;
84 operator= (value_type&&) = delete;
85
90 ~device_registry () = delete;
91
96 // --------------------------------------------------------------------
102 public:
103
104 static void
106
107 static value_type*
108 identify_device (const char* path);
109
114 // --------------------------------------------------------------------
115 private:
116
121 // Since devices may be constructed statically, so may ask
122 // to be linked here at any time, this list must be initialised
123 // before any static constructor.
124 // With the order of static constructors unknown, this means it
125 // must be allocated in the BSS and will be initialised to 0 by
126 // the startup code.
127 using device_list = utils::intrusive_list<device,
128 utils::double_list_links, &device::registry_links_, T>;
129 static device_list registry_list__;
130
134 };
135
136 // ==========================================================================
137 } /* namespace posix */
138} /* namespace os */
139
140// ===== Inline & template implementations ====================================
141
142namespace os
143{
144 namespace posix
145 {
146 // ========================================================================
147
148 template<typename T>
149 void
151 {
152#if defined(DEBUG)
153
154#pragma GCC diagnostic push
155#if defined(__clang__)
156#elif defined(__GNUC__)
157#pragma GCC diagnostic ignored "-Waggregate-return"
158#endif
159 for (auto&& d : registry_list__)
160 {
161 // Validate the device name by checking duplicates.
162 if (std::strcmp (device->name (), d.name ()) == 0)
163 {
164 trace::puts ("Duplicate device name. Abort.");
165 std::abort ();
166 }
167 }
168#pragma GCC diagnostic push
169
170#endif // DEBUG
171
172 registry_list__.link (*device);
173
174 trace::printf ("Device '%s%s' linked\n", value_type::device_prefix (),
175 device->name ());
176 }
177
181 template<typename T>
182 T*
184 {
185 assert(path != nullptr);
186
187 auto prefix = value_type::device_prefix ();
188 if (std::strncmp (prefix, path, std::strlen (prefix)) != 0)
189 {
190 // The device prefix does not match, not a device.
191 return nullptr;
192 }
193
194 // The prefix was identified; try to match the rest of the path.
195 auto name = path + std::strlen (prefix);
196
197 for (auto&& p : registry_list__)
198 {
199 if (p.match_name (name))
200 {
201 return static_cast<value_type*> (&p);
202 }
203 }
204
205 // Not a known device.
206 return nullptr;
207 }
208
213#pragma GCC diagnostic push
214#if defined(__clang__)
215#pragma clang diagnostic ignored "-Wexit-time-destructors"
216#pragma clang diagnostic ignored "-Wglobal-constructors"
217#endif
218
219 // Initialised to 0 by BSS.
220 template<typename T>
222
223#pragma GCC diagnostic pop
224
229 // ==========================================================================
230 } /* namespace posix */
231} /* namespace os */
232
233#pragma GCC diagnostic pop
234
235// ----------------------------------------------------------------------------
236
237#endif /* __cplusplus */
238
239// ----------------------------------------------------------------------------
240
241#endif /* CMSIS_PLUS_POSIX_IO_DEVICE_REGISTRY_H_ */
Devices registry static class.
static value_type * identify_device(const char *path)
static void link(value_type *device)
Base device class.
Definition device.h:68
const char * name(void) const
Definition device.h:307
List of intrusive nodes.
Definition lists.h:705
int puts(const char *s)
Write the string and a line terminator to the trace device.
Definition trace.cpp:103
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:60
System namespace.