mirror of
https://github.com/zeromq/libzmq.git
synced 2025-10-20 22:31:33 +02:00
Fixed wrong handling of shared messages
The shared reference count was not shared but copied. msg_t cannot store the refcnt itsef but has to store a pointer to an externally allocated (shared) refcnter. The changes to lmsg are reverted to use content_t again. Howver, this introduces an allocation in v2_decoder when creating the message which can be avoided. When allocating the reception buffer, space is allocated for the maximum number of reference counts (8192 / max_vsm_size = 8192/64 = 128 zmq:atomic_counter objects). This increases the buffer by 128*sizeof(atomic_counter) = 128*4 = 512 bytes only. When creating a message, the refcnt member is set to the address of one of the pre-allocated atomic_counter_t objects. To do so, a new msg_t type zcmsg is introduced because msg::copy must discriminate between the message types when releasing memory.
This commit is contained in:
@@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <cmath>
|
||||
|
||||
#include "platform.hpp"
|
||||
#ifdef ZMQ_HAVE_WINDOWS
|
||||
@@ -44,7 +45,8 @@
|
||||
zmq::shared_message_memory_allocator::shared_message_memory_allocator(size_t bufsize_):
|
||||
buf(NULL),
|
||||
bufsize( 0 ),
|
||||
maxsize( bufsize_ )
|
||||
maxsize( bufsize_ ),
|
||||
msg_refcnt( NULL )
|
||||
{
|
||||
|
||||
}
|
||||
@@ -67,9 +69,14 @@ unsigned char* zmq::shared_message_memory_allocator::allocate()
|
||||
// @todo aligmnet padding may be needed
|
||||
if (!buf)
|
||||
{
|
||||
buf = (unsigned char *) malloc(bufsize + sizeof(zmq::atomic_counter_t));
|
||||
// allocate memory for reference counters together with reception buffer
|
||||
size_t const maxCounters = std::ceil( (double)max_size / (double)msg_t::max_vsm_size);
|
||||
size_t const allocationsize = maxsize + sizeof(zmq::atomic_counter_t) + maxCounters * sizeof(zmq::atomic_counter_t);
|
||||
|
||||
buf = (unsigned char *) malloc(allocationsize);
|
||||
alloc_assert (buf);
|
||||
new(buf) atomic_counter_t(1);
|
||||
msg_refcnt = reinterpret_cast<zmq::atomic_counter_t*>( buf + sizeof(atomic_counter_t) + maxsize );
|
||||
}
|
||||
|
||||
bufsize = maxsize;
|
||||
@@ -81,6 +88,7 @@ void zmq::shared_message_memory_allocator::deallocate()
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
bufsize = 0;
|
||||
msg_refcnt = NULL;
|
||||
}
|
||||
|
||||
unsigned char* zmq::shared_message_memory_allocator::release()
|
||||
@@ -88,16 +96,11 @@ unsigned char* zmq::shared_message_memory_allocator::release()
|
||||
unsigned char* b = buf;
|
||||
buf = NULL;
|
||||
bufsize = 0;
|
||||
msg_refcnt = NULL;
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::reset(unsigned char* b)
|
||||
{
|
||||
deallocate();
|
||||
buf = b;
|
||||
}
|
||||
|
||||
void zmq::shared_message_memory_allocator::inc_ref()
|
||||
{
|
||||
((zmq::atomic_counter_t*)buf)->add(1);
|
||||
@@ -204,6 +207,7 @@ int zmq::v2_decoder_t::size_ready(uint64_t msg_size, unsigned char const* read_p
|
||||
|
||||
// the current message can exceed the current buffer. We have to copy the buffer
|
||||
// data into a new message and complete it in the next receive.
|
||||
|
||||
if (unlikely ((unsigned char*)read_pos + msg_size > (data() + size())))
|
||||
{
|
||||
// a new message has started, but the size would exceed the pre-allocated arena
|
||||
@@ -214,12 +218,13 @@ int zmq::v2_decoder_t::size_ready(uint64_t msg_size, unsigned char const* read_p
|
||||
{
|
||||
// construct message using n bytes from the buffer as storage
|
||||
// increase buffer ref count
|
||||
rc = in_progress.init( (unsigned char*)read_pos,
|
||||
msg_size, shared_message_memory_allocator::call_dec_ref,
|
||||
buffer() );
|
||||
// if the message will be a large message, pass a valid refcnt memory location as well
|
||||
rc = in_progress.init( (unsigned char*)read_pos, msg_size,
|
||||
shared_message_memory_allocator::call_dec_ref, buffer(),
|
||||
create_refcnt() );
|
||||
|
||||
// For small messages, data has been copied and refcount does not have to be increased
|
||||
if (in_progress.is_lmsg())
|
||||
if (in_progress.is_zcmsg())
|
||||
{
|
||||
inc_ref();
|
||||
}
|
||||
|
Reference in New Issue
Block a user