Skip to content

Commit 66850f5

Browse files
committed
arduino_new updates (doc, example, array)
1 parent c72ced2 commit 66850f5

File tree

3 files changed

+219
-11
lines changed

3 files changed

+219
-11
lines changed

cores/esp8266/core_esp8266_features.h

Lines changed: 46 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,15 +35,53 @@
3535

3636
#ifdef __cplusplus
3737

38-
extern "C++"
39-
template <typename T, typename ...TConstructorArgs>
40-
T* new0 (TConstructorArgs... TconstructorArgs)
38+
#include <stdlib.h> // malloc()
39+
#include <stddef.h> // size_t
40+
41+
namespace arduino
4142
{
42-
T* ptr = (T*)malloc(sizeof(T));
43-
if (ptr)
44-
new (ptr) T(TconstructorArgs...);
45-
return ptr;
46-
}
43+
extern "C++"
44+
template <typename T, typename ...TConstructorArgs>
45+
T* new4arduino (size_t n, TConstructorArgs... TconstructorArgs)
46+
{
47+
if (n == 0)
48+
return nullptr;
49+
size_t offs = n == 1? 0: sizeof(size_t);
50+
T* ptr = (T*)malloc(offs + (n * sizeof(T)));
51+
if (ptr)
52+
{
53+
if (n > 1)
54+
*(size_t*)(ptr) = n;
55+
for (size_t i = 0; i < n; i++)
56+
new (ptr + offs + i * sizeof(T)) T(TconstructorArgs...);
57+
return ptr + offs;
58+
}
59+
return nullptr;
60+
}
61+
62+
// new0<>() and new0array<>() below are necessary only
63+
// because of variadic macro lack of feature, for example with:
64+
// #define arduino_new(Type, ...) arduino::new0array<Type>(1, __VA_ARGS__)
65+
// this arduino_new ^^ macro cannot be used with no arguments after 'Type'
66+
// hint: VA_OPT is c++20
67+
68+
extern "C++"
69+
template <typename T, typename ...TConstructorArgs>
70+
T* new0 (TConstructorArgs... TconstructorArgs)
71+
{
72+
return new4arduino<T>(1, TconstructorArgs...);
73+
}
74+
75+
extern "C++"
76+
template <typename T, size_t n, typename ...TConstructorArgs>
77+
T* new0array (TConstructorArgs... TconstructorArgs)
78+
{
79+
return new4arduino<T>(n, TconstructorArgs...);
80+
}
81+
}
82+
83+
#define arduino_new(Type, ...) arduino::new0<Type>(__VA_ARGS__)
84+
#define arduino_newarray(Type, n, ...) arduino::new0array<Type, n>(__VA_ARGS__)
4785

4886
#endif // __cplusplus
4987

doc/reference.rst

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ C++
255255

256256
History: `#6269 <https://github.com/esp8266/Arduino/issues/6269>`__ `#6309 <https://github.com/esp8266/Arduino/pull/6309>`__ `#6312 <https://github.com/esp8266/Arduino/pull/6312>`__
257257

258-
- New optional allocator ``new0``
258+
- New optional allocator ``arduino_new``
259259

260260
A new optional global allocator is introduced with a different semantic:
261261

@@ -273,7 +273,17 @@ C++
273273
.. code:: cpp
274274
275275
// with new:
276+
276277
SomeClass* sc = new SomeClass(arg1, arg2, ...);
278+
delete sc;
279+
280+
SomeClass* scs = new SomeClass[42];
281+
delete scs;
282+
283+
// with arduino_new:
284+
285+
SomeClass* sc = arduino_new(SomeClass, arg1, arg2, ...);
286+
delete[] sc;
277287
278-
// with new0:
279-
SomeClass* sc = new0<SomeClass>(arg1, arg2, ...);
288+
SomeClass* scs = arduino_newarray(SomeClass, 42);
289+
delete[] scs;
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
2+
// show arduino_new benefits
3+
// released to public domain
4+
// result is below
5+
6+
class SomeClass {
7+
public:
8+
SomeClass(const String& s1 = emptyString, const String& s2 = emptyString) {
9+
Serial.printf("SomeClass@%p(%s)(%s)\n", this, s1.c_str(), s2.c_str());
10+
}
11+
12+
~SomeClass() {
13+
Serial.printf("~ SomeClass @%p\n", this);
14+
}
15+
};
16+
17+
class oom {
18+
private:
19+
char large [65000];
20+
public:
21+
oom() {
22+
Serial.printf("this constructor should not be called\n");
23+
}
24+
};
25+
26+
void setup() {
27+
28+
Serial.begin(115200);
29+
Serial.printf("\n\narduino_new benefits\n\n");
30+
delay(5000); // avoid too frequent bootloop
31+
32+
// arduino_new / arduino_newarray api
33+
34+
Serial.printf("\n----- arduino_new:\n");
35+
auto an = arduino_new(SomeClass);
36+
delete an;
37+
38+
Serial.printf("\n----- arduino_new with oom:\n");
39+
auto anoom = arduino_new(oom);
40+
Serial.printf("nullptr: %p\n", anoom);
41+
delete anoom;
42+
43+
Serial.printf("\n----- arduino_new with constructor parameters:\n");
44+
auto ancp = arduino_new(SomeClass, "param1", "param2");
45+
delete ancp;
46+
47+
Serial.printf("\n----- arduino_newarray[2]\n");
48+
auto ana2 = arduino_newarray(SomeClass, 2);
49+
Serial.printf("@:%p s=%zd s(2)=%zd\n", ana2, sizeof(SomeClass), sizeof(SomeClass[2]));
50+
Serial.printf("0: %p\n", &ana2[0]);
51+
Serial.printf("1: %p\n", &ana2[1]);
52+
delete [] ana2;
53+
54+
Serial.printf("\n----- arduino_newarray[2] (with constructor parameters)\n");
55+
auto ana2cp = arduino_newarray(SomeClass, 2, "param1");
56+
Serial.printf("@:%p s=%zd s(2)=%zd\n", ana2cp, sizeof(SomeClass), sizeof(SomeClass[2]));
57+
Serial.printf("0: %p\n", &ana2cp[0]);
58+
Serial.printf("1: %p\n", &ana2cp[1]);
59+
delete [] ana2cp;
60+
61+
Serial.printf("\n----- arduino_newarray[100000]\n");
62+
auto anaX = arduino_newarray(SomeClass, 100000);
63+
Serial.printf("@:%p\n", anaX);
64+
65+
// standard c++ api for new and new[]
66+
67+
Serial.printf("\n----- new\n");
68+
auto sn = new SomeClass;
69+
delete sn;
70+
71+
Serial.printf("\n----- new with oom: (abort() with option 'Exceptions: Disabled (new can abort)'\n");
72+
auto snoom = new oom;
73+
Serial.printf("nullptr: %p\n", snoom);
74+
delete snoom;
75+
76+
Serial.printf("\n----- new[2]\n");
77+
auto sna2 = new SomeClass[2];
78+
Serial.printf("@:%p s=%zd s(2)=%zd\n", sna2, sizeof(SomeClass), sizeof(SomeClass[2]));
79+
Serial.printf("0: %p\n", &sna2[0]);
80+
Serial.printf("1: %p\n", &sna2[1]);
81+
delete [] sna2;
82+
83+
Serial.printf("\n----- new[10000] (badly fails with 'Exceptions: Legacy' or '...Disabled'\n");
84+
auto snaX = new SomeClass[100000];
85+
Serial.printf("@:%p\n", snaX);
86+
}
87+
88+
void loop() {
89+
}
90+
91+
//////////////////////////////
92+
#if 0
93+
94+
Result with:
95+
Exceptions: Legacy(new can return nullptr)
96+
97+
//////////////////////////////
98+
99+
arduino_new benefits
100+
101+
---- - arduino_new:
102+
SomeClass@0x3fff1864()()
103+
~ SomeClass @0x3fff1864
104+
105+
---- - arduino_new with oom:
106+
nullptr: 0
107+
108+
---- - arduino_new with constructor parameters:
109+
SomeClass@0x3fff1864(param1)(param2)
110+
~ SomeClass @0x3fff1864
111+
112+
---- - arduino_newarray[2]
113+
SomeClass@0x3fff1868()()
114+
SomeClass@0x3fff1869()()
115+
@: 0x3fff1868 s = 1 s(2) = 2
116+
0: 0x3fff1868
117+
1: 0x3fff1869
118+
~ SomeClass @0x3fff1869
119+
~ SomeClass @0x3fff1868
120+
121+
---- - arduino_newarray[2](with constructor parameters)
122+
SomeClass@0x3fff1868(param1)()
123+
SomeClass@0x3fff1869(param1)()
124+
@: 0x3fff1868 s = 1 s(2) = 2
125+
0: 0x3fff1868
126+
1: 0x3fff1869
127+
~ SomeClass @0x3fff1869
128+
~ SomeClass @0x3fff1868
129+
130+
---- - arduino_newarray[100000]
131+
@: 0
132+
133+
---- - new
134+
SomeClass@0x3fff1864()()
135+
~ SomeClass @0x3fff1864
136+
137+
----- new with oom: (abort() with option 'Exceptions: Disabled (new can abort)'
138+
this constructor should not be called
139+
nullptr: 0
140+
141+
---- - new[2]
142+
SomeClass@0x3fff1868()()
143+
SomeClass@0x3fff1869()()
144+
@:0x3fff1868 s = 1 s(2) = 2
145+
0: 0x3fff1868
146+
1: 0x3fff1869
147+
~ SomeClass @0x3fff1869
148+
~ SomeClass @0x3fff1868
149+
150+
---- - new[10000](badly fails with 'Exceptions: Legacy' or '...Disabled'
151+
152+
Exception(29):
153+
epc1 = 0x402013de epc2 = 0x00000000 epc3 = 0x00000000 excvaddr = 0x00000000 depc = 0x00000000
154+
155+
>>> stack >>>
156+
157+
...
158+
//////////////////////////////
159+
160+
#endif

0 commit comments

Comments
 (0)