decoder_allocators.cpp 4.79 KB
Newer Older
Jens Auer's avatar
Jens Auer committed
1
/*
2
    Copyright (c) 2007-2016 Contributors as noted in the AUTHORS file
Jens Auer's avatar
Jens Auer committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29

    This file is part of libzmq, the ZeroMQ core engine in C++.

    libzmq is free software; you can redistribute it and/or modify it under
    the terms of the GNU Lesser General Public License (LGPL) as published
    by the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    As a special exception, the Contributors give you permission to link
    this library with independent modules to produce an executable,
    regardless of the license terms of these independent modules, and to
    copy and distribute the resulting executable under terms of your choice,
    provided that you also meet, for each linked independent module, the
    terms and conditions of the license of that module. An independent
    module is a module which is not derived from or based on this library.
    If you modify this library, you must extend this exception to your
    version of the library.

    libzmq is distributed in the hope that it will be useful, but WITHOUT
    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
    License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

30
#include "precompiled.hpp"
Jens Auer's avatar
Jens Auer committed
31 32 33 34 35 36
#include "decoder_allocators.hpp"

#include <cmath>

#include "msg.hpp"

37 38
zmq::shared_message_memory_allocator::shared_message_memory_allocator (
  std::size_t bufsize_) :
39 40 41 42 43 44
    _buf (NULL),
    _buf_size (0),
    _max_size (bufsize_),
    _msg_content (NULL),
    _max_counters (static_cast<size_t> (
      std::ceil (static_cast<double> (_max_size)
45
                 / static_cast<double> (msg_t::max_vsm_size))))
Jens Auer's avatar
Jens Auer committed
46 47 48
{
}

49
zmq::shared_message_memory_allocator::shared_message_memory_allocator (
50
  std::size_t bufsize_, std::size_t max_messages_) :
51 52 53 54 55
    _buf (NULL),
    _buf_size (0),
    _max_size (bufsize_),
    _msg_content (NULL),
    _max_counters (max_messages_)
Jens Auer's avatar
Jens Auer committed
56 57 58
{
}

59
zmq::shared_message_memory_allocator::~shared_message_memory_allocator ()
Jens Auer's avatar
Jens Auer committed
60
{
61
    deallocate ();
Jens Auer's avatar
Jens Auer committed
62 63
}

64
unsigned char *zmq::shared_message_memory_allocator::allocate ()
Jens Auer's avatar
Jens Auer committed
65
{
66
    if (_buf) {
Jens Auer's avatar
Jens Auer committed
67
        // release reference count to couple lifetime to messages
68
        zmq::atomic_counter_t *c =
69
          reinterpret_cast<zmq::atomic_counter_t *> (_buf);
Jens Auer's avatar
Jens Auer committed
70 71 72 73

        // if refcnt drops to 0, there are no message using the buffer
        // because either all messages have been closed or only vsm-messages
        // were created
74
        if (c->sub (1)) {
Jens Auer's avatar
Jens Auer committed
75 76
            // buffer is still in use as message data. "Release" it and create a new one
            // release pointer because we are going to create a new buffer
77
            release ();
Jens Auer's avatar
Jens Auer committed
78 79 80 81
        }
    }

    // if buf != NULL it is not used by any message so we can re-use it for the next run
82
    if (!_buf) {
Jens Auer's avatar
Jens Auer committed
83
        // allocate memory for reference counters together with reception buffer
84
        std::size_t const allocationsize =
85 86
          _max_size + sizeof (zmq::atomic_counter_t)
          + _max_counters * sizeof (zmq::msg_t::content_t);
Jens Auer's avatar
Jens Auer committed
87

88 89
        _buf = static_cast<unsigned char *> (std::malloc (allocationsize));
        alloc_assert (_buf);
Jens Auer's avatar
Jens Auer committed
90

91
        new (_buf) atomic_counter_t (1);
92
    } else {
Jens Auer's avatar
Jens Auer committed
93
        // release reference count to couple lifetime to messages
94
        zmq::atomic_counter_t *c =
95
          reinterpret_cast<zmq::atomic_counter_t *> (_buf);
96
        c->set (1);
Jens Auer's avatar
Jens Auer committed
97 98
    }

99 100 101 102
    _buf_size = _max_size;
    _msg_content = reinterpret_cast<zmq::msg_t::content_t *> (
      _buf + sizeof (atomic_counter_t) + _max_size);
    return _buf + sizeof (zmq::atomic_counter_t);
Jens Auer's avatar
Jens Auer committed
103 104
}

105
void zmq::shared_message_memory_allocator::deallocate ()
Jens Auer's avatar
Jens Auer committed
106
{
107 108 109
    zmq::atomic_counter_t *c = reinterpret_cast<zmq::atomic_counter_t *> (_buf);
    if (_buf && !c->sub (1)) {
        std::free (_buf);
110
    }
111
    clear ();
Jens Auer's avatar
Jens Auer committed
112 113
}

114
unsigned char *zmq::shared_message_memory_allocator::release ()
Jens Auer's avatar
Jens Auer committed
115
{
116
    unsigned char *b = _buf;
117 118 119 120 121 122
    clear ();
    return b;
}

void zmq::shared_message_memory_allocator::clear ()
{
123 124 125
    _buf = NULL;
    _buf_size = 0;
    _msg_content = NULL;
Jens Auer's avatar
Jens Auer committed
126 127
}

128
void zmq::shared_message_memory_allocator::inc_ref ()
Jens Auer's avatar
Jens Auer committed
129
{
130
    (reinterpret_cast<zmq::atomic_counter_t *> (_buf))->add (1);
Jens Auer's avatar
Jens Auer committed
131 132
}

133
void zmq::shared_message_memory_allocator::call_dec_ref (void *, void *hint_)
134
{
135 136
    zmq_assert (hint_);
    unsigned char *buf = static_cast<unsigned char *> (hint_);
137
    zmq::atomic_counter_t *c = reinterpret_cast<zmq::atomic_counter_t *> (buf);
Jens Auer's avatar
Jens Auer committed
138

139 140 141
    if (!c->sub (1)) {
        c->~atomic_counter_t ();
        std::free (buf);
Jens Auer's avatar
Jens Auer committed
142 143 144 145 146
        buf = NULL;
    }
}


147
std::size_t zmq::shared_message_memory_allocator::size () const
Jens Auer's avatar
Jens Auer committed
148
{
149
    return _buf_size;
Jens Auer's avatar
Jens Auer committed
150 151
}

152
unsigned char *zmq::shared_message_memory_allocator::data ()
Jens Auer's avatar
Jens Auer committed
153
{
154
    return _buf + sizeof (zmq::atomic_counter_t);
155
}