Fawkes API  Fawkes Development Version
message.h
1 
2 /***************************************************************************
3  * message.h - BlackBoard message
4  *
5  * Created: Sun Oct 08 00:08:10 2006
6  * Copyright 2006-2010 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #ifndef _INTERFACE_MESSAGE_H_
25 #define _INTERFACE_MESSAGE_H_
26 
27 #include <core/exceptions/software.h>
28 #include <core/utils/refcount.h>
29 #include <interface/field_iterator.h>
30 #include <interface/types.h>
31 
32 #include <cstring>
33 #include <type_traits>
34 
35 #define INTERFACE_MESSAGE_TYPE_SIZE_ 64
36 
37 namespace fawkes {
38 
39 class Mutex;
40 class Interface;
41 class InterfaceFieldIterator;
42 class Time;
43 
44 class Message : public RefCount
45 {
46  friend Interface;
47 
48 public:
49  Message(const char *type);
50  Message(const Message *mesg);
51  Message(const Message &mesg);
52  virtual ~Message();
53 
54  Message &operator=(const Message &m);
55 
56  unsigned int id() const;
57  void set_id(unsigned int message_id);
58  void mark_enqueued();
59  bool enqueued() const;
60  const Time * time_enqueued() const;
61 
62  unsigned int sender_id() const;
63  const char * sender_thread_name() const;
64  Interface * interface() const;
65  const char * type() const;
66 
69 
70  unsigned int num_fields() const;
71 
72  const void * datachunk() const;
73  unsigned int datasize() const;
74 
75  unsigned int hops() const;
76  void set_hops(unsigned int hops);
77 
78  void set_from_chunk(const void *chunk);
79 
80  unsigned int recipient() const;
81 
82  virtual Message *clone() const;
83 
84  /** Check if message has desired type.
85  * @return true, if message has desired type, false otherwise
86  */
87  template <class MessageType>
88  bool is_of_type();
89 
90  /** Cast message to given type if possible.
91  * Check with is_of_type() first if the message has the requested type.
92  * @return message casted to requested type
93  * @throw TypeMismatchException thrown if the message is not of the requested type
94  */
95  template <class MessageType>
96  MessageType *as_type();
97 
98 private: // fields
99  unsigned int message_id_;
100  unsigned int hops_;
101  bool enqueued_;
102  Time * time_enqueued_;
103 
104  unsigned int recipient_interface_mem_serial;
105  unsigned int sender_interface_instance_serial;
106 
107  char * _type;
108  char * _sender_thread_name;
109  unsigned int _sender_id;
110 
111  Interface *_transmit_via_iface;
112 
113  interface_fieldinfo_t *fieldinfo_list_;
114 
115  unsigned int num_fields_;
116 
117 private: // methods
118  void set_interface(Interface *iface);
119 
120 protected:
122  const char * name,
123  size_t length,
124  void * value,
125  const char * enumtype = 0,
126  const interface_enum_map_t *enum_map = 0);
127 
128  void * data_ptr;
129  unsigned int data_size;
130 
131  /** Timestamp data, must be present and first entries for each interface
132  * data structs! This leans on timeval struct. */
133  typedef struct
134  {
135  int64_t timestamp_sec; /**< time in seconds since Unix epoch */
136  int64_t timestamp_usec; /**< additional time microseconds */
138  message_data_ts_t *data_ts; /**< data timestamp aliasing pointer */
139 };
140 
141 template <class MessageType>
142 bool
144 {
145  return (dynamic_cast<MessageType *>(this) != 0);
146 }
147 
148 template <class MessageType>
149 MessageType *
151 {
152  MessageType *m = dynamic_cast<MessageType *>(this);
153  if (m) {
154  return m;
155  } else {
156  throw fawkes::TypeMismatchException("Message is not of requested type");
157  }
158 }
159 
160 /** Set a field and return whether it changed
161  * @param field The interface field to change
162  * @param value The new value
163  * @return Whether the new value is different from the old
164  */
165 template <class FieldT, class DataT>
166 bool
167 change_field(FieldT &field, const DataT &value)
168 {
169  bool rv = field != value;
170  field = value;
171  return rv;
172 }
173 
174 /** Set a string field and return whether it changed
175  * @param field The interface field to change
176  * @param value The new value
177  * @return Whether the new value is different from the old
178  */
179 template <class FieldT, std::size_t Size>
180 bool
181 change_field(FieldT (&field)[Size], const char *value)
182 {
183  bool change = ::strncmp(field, value, Size);
184  ::strncpy(field, value, Size - 1);
185  field[Size - 1] = 0;
186  return change;
187 }
188 
189 /** Set an array field and return whether it changed
190  * @param field The interface field to change
191  * @param value The new value
192  * @return Whether the new value is different from the old
193  */
194 template <class FieldT, std::size_t Size, class DataT>
195 typename std::enable_if<!std::is_same<FieldT, char>::value, bool>::type
196 change_field(FieldT (&field)[Size], const DataT *value)
197 {
198  bool change = ::memcmp(field, value, Size);
199  ::memcpy(field, value, sizeof(FieldT) * Size);
200  return change;
201 }
202 
203 /** Set an array field value at a certain index and return whether it changed
204  * @param field The interface field to change
205  * @param index Index into the array field
206  * @param value The new value
207  * @return Whether the new value is different from the old
208  */
209 template <class FieldT, std::size_t Size, class DataT>
210 bool
211 change_field(FieldT (&field)[Size], unsigned int index, const DataT &value)
212 {
213  if (index >= Size)
214  throw Exception("Index value %u is out of bounds (0..%u)", index, Size - 1);
215  bool change = field[index] != value;
216  field[index] = value;
217  return change;
218 }
219 
220 } // end namespace fawkes
221 
222 #endif
fawkes::Message::enqueued
bool enqueued() const
Check is message has been enqueued.
Definition: message.cpp:229
fawkes::Message::datachunk
const void * datachunk() const
Get pointer to data.
Definition: message.cpp:261
fawkes::interface_fieldtype_t
interface_fieldtype_t
Interface field type.
Definition: types.h:36
fawkes::Message
Base class for all messages passed through interfaces in Fawkes BlackBoard.
Definition: message.h:45
fawkes::Message::fields_end
InterfaceFieldIterator fields_end()
Invalid iterator.
Definition: message.cpp:364
fawkes::Message::data_ptr
void * data_ptr
Pointer to memory that contains local data.
Definition: message.h:128
fawkes::Message::set_id
void set_id(unsigned int message_id)
Set message ID.
Definition: message.cpp:198
fawkes::Message::mark_enqueued
void mark_enqueued()
Mark message as being enqueued.
Definition: message.cpp:214
fawkes::Message::data_ts
message_data_ts_t * data_ts
data timestamp aliasing pointer
Definition: message.h:138
fawkes::Message::sender_thread_name
const char * sender_thread_name() const
Get sender of message.
Definition: message.cpp:307
fawkes::Message::time_enqueued
const Time * time_enqueued() const
Get time when message was enqueued.
Definition: message.cpp:242
fawkes::Message::Message
Message(const char *type)
Constructor.
Definition: message.cpp:62
fawkes::Message::interface
Interface * interface() const
Get transmitting interface.
Definition: message.cpp:337
fawkes::Message::sender_id
unsigned int sender_id() const
Get ID of sender.
Definition: message.cpp:316
fawkes::Message::message_data_ts_t
Timestamp data, must be present and first entries for each interface data structs!...
Definition: message.h:134
fawkes::Message::fields
InterfaceFieldIterator fields()
Get iterator over all fields of this interface instance.
Definition: message.cpp:355
fawkes::TypeMismatchException
Type mismatch.
Definition: software.h:44
fawkes::InterfaceFieldIterator
Interface field iterator.
Definition: field_iterator.h:39
fawkes
Fawkes library namespace.
fawkes::interface_fieldinfo_t
Interface field info list.
Definition: types.h:58
fawkes::Message::data_size
unsigned int data_size
Size of memory needed to hold all data.
Definition: message.h:129
fawkes::Interface
Base class for all Fawkes BlackBoard interfaces.
Definition: interface.h:79
fawkes::Message::set_hops
void set_hops(unsigned int hops)
Set number of hops.
Definition: message.cpp:207
fawkes::Message::datasize
unsigned int datasize() const
Get size of data.
Definition: message.cpp:270
fawkes::interface_enum_map_t
std::map< int, std::string > interface_enum_map_t
Map of enum integer to string values.
Definition: types.h:54
fawkes::Message::type
const char * type() const
Get message type.
Definition: message.cpp:346
fawkes::Message::num_fields
unsigned int num_fields() const
Get the number of fields in the message.
Definition: message.cpp:373
fawkes::Time
A class for handling time.
Definition: time.h:93
fawkes::Message::add_fieldinfo
void add_fieldinfo(interface_fieldtype_t type, const char *name, size_t length, void *value, const char *enumtype=0, const interface_enum_map_t *enum_map=0)
Add an entry to the info list.
Definition: message.cpp:400
fawkes::Message::~Message
virtual ~Message()
Destructor.
Definition: message.cpp:162
fawkes::RefCount
Reference counting base class.
Definition: refcount.h:32
fawkes::Message::operator=
Message & operator=(const Message &m)
Assign this message to given message.
Definition: message.cpp:293
fawkes::Message::as_type
MessageType * as_type()
Cast message to given type if possible.
Definition: message.h:150
fawkes::Message::set_from_chunk
void set_from_chunk(const void *chunk)
Set from raw data chunk.
Definition: message.cpp:281
fawkes::Message::hops
unsigned int hops() const
Get number of hops.
Definition: message.cpp:189
fawkes::Message::message_data_ts_t::timestamp_usec
int64_t timestamp_usec
additional time microseconds
Definition: message.h:136
fawkes::Message::clone
virtual Message * clone() const
Clone this message.
Definition: message.cpp:383
fawkes::Message::id
unsigned int id() const
Get message ID.
Definition: message.cpp:180
fawkes::Message::is_of_type
bool is_of_type()
Check if message has desired type.
Definition: message.h:143
fawkes::Message::recipient
unsigned int recipient() const
Get recipient memory serial.
Definition: message.cpp:251
fawkes::Message::message_data_ts_t::timestamp_sec
int64_t timestamp_sec
time in seconds since Unix epoch
Definition: message.h:135
fawkes::change_field
bool change_field(FieldT &field, const DataT &value)
Set a field and return whether it changed.
Definition: message.h:167
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36