, ++ 2049 , , , .
, ++, - . ( , ).
, , , ( ), (, , ).
. , , , , , , / .
, , , ,
toplevel, -.
, , .
, , ?
API, . - -, , .
" " , . , , .
, , .
, , - (.. , ), - , .
,
-, , , .
, ( ) .
.
#include <cstdint>
#include <cstdio>
#include <new>
typedef uint8_t id_t;
enum class MessageID { WorldPeace, Armaggedon };
#define SMALL_BUF_SIZE 64
class Message {
id_t m_messageId;
uint8_t* m_data;
uint8_t m_localData[SMALL_BUF_SIZE];
public:
Message (MessageID messageId, size_t size)
{
m_messageId = (id_t)messageId;
m_data = size <= SMALL_BUF_SIZE ? m_localData : new uint8_t[size];
}
~Message ()
{
if (m_data != m_localData) delete m_data;
}
void * location (void)
{
return m_data;
}
};
#define BuildMessage(msg, id, obj, ... ) \
Message msg(MessageID::id, sizeof(obj)); \
new (msg.location()) obj (__VA_ARGS__); \
struct small {
int a, b, c;
small (int a, int b, int c) :a(a),b(b),c(c) {}
};
struct big {
int lump[1000];
};
int main(void)
{
BuildMessage(msg1, WorldPeace, small, 1, 2, 3)
BuildMessage(msg2, Armaggedon, big)
}
.
, .
, , - 64 , , .
, , , .
, && . , , .
, , && , .
Message, , , : , - .
Message, , , .
, , , .
, .
, , , , -.
.
, -.
, . , - .
, DMA, , .
- .
#include <cstdint>
#include <new>
enum class MessageID : uint8_t { WorldPeace, Armaggedon };
struct MessageHeader {
MessageID id;
uint8_t __padding;
uint16_t size;
};
#define SMALL_BUF_SIZE 64
int some_DMA_trick(int destination, void * data, uint16_t size);
class mMessage {
MessageHeader m_header;
uint8_t m_localData[SMALL_BUF_SIZE];
MessageHeader * m_head;
public:
mMessage (MessageID messageId, uint16_t size)
{
m_head = size <= SMALL_BUF_SIZE
? &m_header
: (MessageHeader *) new uint8_t[size + sizeof (m_header)];
m_head->id = messageId;
m_head->size = size;
}
~mMessage ()
{
if (m_head != &m_header) delete m_head;
}
void * location (void)
{
return m_head+1;
}
int send(int destination)
{
return some_DMA_trick (destination, m_head, (uint16_t)(m_head->size + sizeof (m_head)));
}
};
#define BuildMessage(msg, obj, id, ... ) \
mMessage msg (MessageID::id, sizeof(obj)); \
new (msg.location()) obj (__VA_ARGS__); \
#include <utility>
template<typename T>
struct storage
{
enum { local = sizeof(T)<=SMALL_BUF_SIZE };
};
class tMessage {
protected:
MessageHeader * m_head;
tMessage(MessageHeader * head, MessageID id, uint16_t size)
: m_head(head)
{
m_head->id = id;
m_head->size = size;
}
public:
int send(int destination)
{
return some_DMA_trick (destination, m_head, (uint16_t)(m_head->size + sizeof (*m_head)));
}
};
template<bool local_storage, typename message_contents>
class aMessage {};
template<typename T>
class aMessage<false, T> : public tMessage
{
public:
template<class... Args>
aMessage(MessageID id, Args...args)
: tMessage(
(MessageHeader *)new uint8_t[sizeof(T)+sizeof(*m_head)],
id, sizeof(T))
{
new (m_head+1) T(std::forward<Args>(args)...);
}
~aMessage ()
{
delete m_head;
}
T& contents(void) { return *(T*)(m_head+1); }
};
template<typename T>
class aMessage<true, T> : public tMessage
{
MessageHeader m_header;
uint8_t m_data[sizeof(T)];
public:
template<class... Args>
aMessage(MessageID id, Args...args)
: tMessage(
&m_header,
id, sizeof(T))
{
new (m_head+1) T(std::forward<Args>(args)...);
}
T& contents(void) { return *(T*)(m_head+1); }
};
#define Message(T) aMessage<storage<T>::local, T>
#include <cstdio>
#include <cstring>
int some_DMA_trick(int destination, void * data, uint16_t size)
{
printf("sending %d bytes @%p to %08X\n", size, data, destination);
return 1;
}
struct gizmo {
char * s;
gizmo(void) { s = nullptr; };
gizmo (const gizmo& g) = delete;
gizmo (const char * msg)
{
s = new char[strlen(msg) + 3];
strcpy(s, msg);
strcat(s, "#");
}
gizmo (gizmo&& g)
{
s = g.s;
g.s = nullptr;
strcat(s, "*");
}
~gizmo()
{
delete s;
}
gizmo& operator=(gizmo g)
{
std::swap(s, g.s);
return *this;
}
bool operator!=(gizmo& g)
{
return strcmp (s, g.s) != 0;
}
};
struct small {
int a, b, c;
gizmo g;
small (gizmo g, int a, int b, int c)
: a(a), b(b), c(c), g(std::move(g))
{
}
void trace(void)
{
printf("small: %d %d %d %s\n", a, b, c, g.s);
}
};
struct big {
gizmo lump[1000];
big(const char * msg = "?")
{
for (size_t i = 0; i != sizeof(lump) / sizeof(lump[0]); i++)
lump[i] = gizmo (msg);
}
void trace(void)
{
printf("big: set to ");
gizmo& first = lump[0];
for (size_t i = 1; i != sizeof(lump) / sizeof(lump[0]); i++)
if (lump[i] != first) { printf(" Erm... mostly "); break; }
printf("%s\n", first.s);
}
};
int main(void)
{
BuildMessage(mmsg1, small, WorldPeace, gizmo("Hi"), 1, 2, 3);
BuildMessage(mmsg2, big , Armaggedon, "Doom");
((small *)mmsg1.location())->trace();
((big *)mmsg2.location())->trace();
mmsg1.send(0x1000);
mmsg2.send(0x2000);
Message (small) tmsg1(MessageID::WorldPeace, gizmo("Hello"), 4, 5, 6);
Message (big ) tmsg2(MessageID::Armaggedon, "Damnation");
tmsg1.contents().trace();
tmsg2.contents().trace();
tmsg1.send(0x3000);
tmsg2.send(0x4000);
}
:
small: 1 2 3 Hi
big: set to Doom
sending 20 bytes @0xbf81be20 to 00001000
sending 4004 bytes @0x9e58018 to 00002000
small: 4 5 6 Hello
big: set to Damnation
sending 20 bytes @0xbf81be0c to 00003000
sending 4004 bytes @0x9e5ce50 to 00004000
.
, , , , , .
, , . . .
, .
- , .
. , .
68 (64 - sizeof (contents object)).
, , . , .
, . , , .
, , send.
, IMHO.
, , . , BSP.
, , , .
.
, - , , , .
, , , ( ) .
, 64 . , - , , .
, , , , , .
, , , .