µ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++ project (https://micro-os-plus.github.io/).
3 * Copyright (c) 2015-2025 Liviu Ionescu. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software
6 * for any purpose is hereby granted, under the terms of the MIT license.
7 *
8 * If a copy of the license was not distributed with this file, it can
9 * be obtained from https://opensource.org/licenses/mit.
10 */
11
12#ifndef CMSIS_PLUS_POSIX_IO_DEVICE_REGISTRY_H_
13#define CMSIS_PLUS_POSIX_IO_DEVICE_REGISTRY_H_
14
15// ----------------------------------------------------------------------------
16
17#if defined(__cplusplus)
18
19// ----------------------------------------------------------------------------
20
21#if defined(OS_USE_OS_APP_CONFIG_H)
22#include <cmsis-plus/os-app-config.h>
23#endif
24
27
28#include <cstddef>
29#include <cassert>
30#include <cstring>
31
32// ----------------------------------------------------------------------------
33
34#pragma GCC diagnostic push
35#if defined(__clang__)
36#pragma clang diagnostic ignored "-Wc++98-compat"
37#endif
38
39// ----------------------------------------------------------------------------
40
41namespace os
42{
43 namespace posix
44 {
45 // ========================================================================
46
52 template <typename T>
54 {
55 public:
56 using value_type = T;
57 using pointer = T*;
58 using reference = T&;
59
60 // ----------------------------------------------------------------------
61
67 public:
68 // Do not allow to create instances of this class.
69 device_registry () = delete;
70
75 // The rule of five.
76 device_registry (const value_type&) = delete;
77 device_registry (value_type&&) = delete;
79 operator= (const value_type&)
80 = delete;
82 operator= (value_type&&)
83 = delete;
84
89 ~device_registry () = delete;
90
95 // ----------------------------------------------------------------------
101 public:
102 static void
104
105#pragma GCC diagnostic push
106#if defined(__clang__)
107#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
108#endif
109 static value_type*
110 identify_device (const char* path);
111#pragma GCC diagnostic pop
112
117 // ----------------------------------------------------------------------
118 private:
123 // Since devices may be constructed statically, so may ask
124 // to be linked here at any time, this list must be initialised
125 // before any static constructor.
126 // With the order of static constructors unknown, this means it
127 // must be allocated in the BSS and will be initialised to 0 by
128 // the startup code.
129 using device_list
131 &device::registry_links_, T>;
132 static device_list registry_list__;
133
137 };
138
139 // ========================================================================
140 } /* namespace posix */
141} /* namespace os */
142
143// ===== Inline & template implementations ====================================
144
145namespace os
146{
147 namespace posix
148 {
149 // ========================================================================
150
151 template <typename T>
152 void
154 {
155#if defined(DEBUG)
156
157#pragma GCC diagnostic push
158#if defined(__clang__)
159#elif defined(__GNUC__)
160#pragma GCC diagnostic ignored "-Waggregate-return"
161#endif
162 for (auto&& d : registry_list__)
163 {
164 // Validate the device name by checking duplicates.
165 if (std::strcmp (device->name (), d.name ()) == 0)
166 {
167 trace::puts ("Duplicate device name. Abort.");
168 std::abort ();
169 }
170 }
171#pragma GCC diagnostic push
172
173#endif // DEBUG
174
175 registry_list__.link (*device);
176
177 trace::printf ("Device '%s%s' linked\n", value_type::device_prefix (),
178 device->name ());
179 }
180
184 template <typename T>
185 T*
187 {
188 assert (path != nullptr);
189
190 auto prefix = value_type::device_prefix ();
191 if (std::strncmp (prefix, path, std::strlen (prefix)) != 0)
192 {
193 // The device prefix does not match, not a device.
194 return nullptr;
195 }
196
197#pragma GCC diagnostic push
198#if defined(__clang__)
199#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
200#endif
201 // The prefix was identified; try to match the rest of the path.
202 auto name = path + std::strlen (prefix);
203#pragma GCC diagnostic pop
204
205 for (auto&& p : registry_list__)
206 {
207 if (p.match_name (name))
208 {
209 return static_cast<value_type*> (&p);
210 }
211 }
212
213 // Not a known device.
214 return nullptr;
215 }
216
221#pragma GCC diagnostic push
222#if defined(__clang__)
223#pragma clang diagnostic ignored "-Wexit-time-destructors"
224#pragma clang diagnostic ignored "-Wglobal-constructors"
225#endif
226
227 // Initialised to 0 by BSS.
228 template <typename T>
231
232#pragma GCC diagnostic pop
233
238 // ========================================================================
239 } /* namespace posix */
240} /* namespace os */
241
242#pragma GCC diagnostic pop
243
244// ----------------------------------------------------------------------------
245
246#endif /* __cplusplus */
247
248// ----------------------------------------------------------------------------
249
250#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:67
const char * name(void) const
Definition device.h:304
List of intrusive nodes.
Definition lists.h:690
int puts(const char *s)
Write the string and a line terminator to the trace device.
Definition trace.cpp:102
int printf(const char *format,...)
Write a formatted string to the trace device.
Definition trace.cpp:59
System namespace.