@@ -35,6 +35,7 @@ SOFTWARE.
3535
3636#include " shadesmar/concurrency/scope.h"
3737#include " shadesmar/macros.h"
38+ #include " shadesmar/memory/copier.h"
3839#include " shadesmar/memory/memory.h"
3940
4041namespace shm ::pubsub {
@@ -61,8 +62,13 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
6162 " queue_size must be power of two" );
6263
6364 public:
65+ Topic (const std::string &topic, memory::Copier *copier, bool copy = false )
66+ : memory::Memory<TopicElem, queue_size>(topic),
67+ copy_ (copy),
68+ copier_ (copier) {}
69+
6470 explicit Topic (const std::string &topic, bool copy = false )
65- : memory::Memory<TopicElem, queue_size> (topic), copy_( copy) {}
71+ : Topic (topic, nullptr , copy) {}
6672
6773 bool write (void *data, size_t size) {
6874 /*
@@ -102,14 +108,13 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
102108 return _read_without_copy (oh, elem);
103109 }
104110
105- bool read (std::unique_ptr<uint8_t []> &msg, size_t *size, // NOLINT
106- uint32_t pos) {
111+ bool read (memory::Ptr *ptr, uint32_t pos) {
107112 /*
108113 * Read into a raw array. We pass `size` as a reference to store
109114 * the size of the message.
110115 */
111116 TopicElem *elem = &(this ->shared_queue_ ->elements [pos & (queue_size - 1 )]);
112- return _read_bin (msg, size , elem);
117+ return _read_bin (ptr , elem);
113118 }
114119
115120 inline __attribute__ ((always_inline)) uint32_t fetch_add_counter() {
@@ -124,6 +129,10 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
124129 this ->shared_queue_ ->counter .fetch_add (1 );
125130 }
126131
132+ inline __attribute__ ((always_inline)) memory::Copier *copier() const {
133+ return copier_;
134+ }
135+
127136 private:
128137 bool _write_rcu (void *data, size_t size, TopicElem *elem) {
129138 /*
@@ -139,7 +148,12 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
139148 if (new_addr == nullptr ) {
140149 return false ;
141150 }
142- std::memcpy (new_addr, data, size);
151+
152+ if (copier_ == nullptr ) {
153+ std::memcpy (new_addr, data, size);
154+ } else {
155+ copier_->user_to_shm (new_addr, data, size);
156+ }
143157
144158 void *old_addr;
145159 bool prev_empty;
@@ -195,18 +209,19 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
195209 * So we bite the cost of the extra function call before checking
196210 * for emptiness.
197211 */
198- auto src = std::unique_ptr<uint8_t []>(new uint8_t [elem->size ]);
199- size_t size;
200212
201- if (_read_bin (src, &size, elem)) {
202- *oh = msgpack::unpack (reinterpret_cast <const char *>(src.get ()), size);
213+ memory::Ptr ptr;
214+
215+ if (_read_bin (&ptr, elem)) {
216+ *oh = msgpack::unpack (reinterpret_cast <const char *>(ptr.ptr ), ptr.size );
217+ free (ptr.ptr );
203218 return true ;
204219 }
220+
205221 return false ;
206222 }
207223
208- bool _read_bin (std::unique_ptr<uint8_t []> &msg, size_t *size, // NOLINT
209- TopicElem *elem) {
224+ bool _read_bin (memory::Ptr *ptr, TopicElem *elem) {
210225 /*
211226 * Code path:
212227 * 1. Acquire sharable lock
@@ -218,14 +233,21 @@ class Topic : public memory::Memory<_TopicElem<LockT>, queue_size> {
218233
219234 if (elem->empty ) return false ;
220235
221- *size = elem->size ;
222- msg = std::unique_ptr<uint8_t []>(new uint8_t [*size]);
223236 auto *dst = this ->raw_buf_ ->get_address_from_handle (elem->addr_hdl );
224- std::memcpy (msg.get (), dst, *size);
237+
238+ ptr->size = elem->size ;
239+ if (copier_ != nullptr ) {
240+ ptr->ptr = copier_->alloc (ptr->size );
241+ copier_->shm_to_user (ptr->ptr , dst, ptr->size );
242+ } else {
243+ ptr->ptr = malloc (ptr->size );
244+ std::memcpy (ptr->ptr , dst, ptr->size );
245+ }
225246
226247 return true ;
227248 }
228249
250+ memory::Copier *copier_;
229251 bool copy_{};
230252};
231253} // namespace shm::pubsub
0 commit comments