aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/transport/zero_copy.cpp
blob: 27f41329bc4e0ed74a1108b635ecf9b66f3a57f1 (plain)
1
2
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
//
// Copyright 2010 Ettus Research LLC
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
//

#include <uhd/transport/zero_copy.hpp>
#include <boost/cstdint.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>

using namespace uhd::transport;

/***********************************************************************
 * The pure-virtual deconstructor needs an implementation to be happy
 **********************************************************************/
managed_recv_buffer::~managed_recv_buffer(void){
    /* NOP */
}

/***********************************************************************
 * Phony zero-copy recv interface implementation
 **********************************************************************/

//! phony zero-copy recv buffer implementation
class managed_recv_buffer_impl : public managed_recv_buffer{
public:
    managed_recv_buffer_impl(const boost::asio::const_buffer &buff) : _buff(buff){
        /* NOP */
    }

    ~managed_recv_buffer_impl(void){
        delete [] this->cast<const boost::uint8_t *>();
    }

private:
    const boost::asio::const_buffer &get(void) const{
        return _buff;
    }

    const boost::asio::const_buffer _buff;
};

//! phony zero-copy recv interface implementation
struct phony_zero_copy_recv_if::impl{
    size_t max_buff_size;
};

phony_zero_copy_recv_if::phony_zero_copy_recv_if(size_t max_buff_size){
    _impl = UHD_PIMPL_MAKE(impl, ());
    _impl->max_buff_size = max_buff_size;
}

phony_zero_copy_recv_if::~phony_zero_copy_recv_if(void){
    /* NOP */
}

managed_recv_buffer::sptr phony_zero_copy_recv_if::get_recv_buff(void){
    //allocate memory
    boost::uint8_t *recv_mem = new boost::uint8_t[_impl->max_buff_size];

    //call recv() with timeout option
    size_t num_bytes = this->recv(boost::asio::buffer(recv_mem, _impl->max_buff_size));

    //create a new managed buffer to house the data
    return managed_recv_buffer::sptr(
        new managed_recv_buffer_impl(boost::asio::buffer(recv_mem, num_bytes))
    );
}

/***********************************************************************
 * Phony zero-copy send interface implementation
 **********************************************************************/

//! phony zero-copy send buffer implementation
class managed_send_buffer_impl : public managed_send_buffer{
public:
    typedef boost::function<size_t(const boost::asio::const_buffer &)> send_fcn_t;

    managed_send_buffer_impl(
        const boost::asio::mutable_buffer &buff,
        const send_fcn_t &send_fcn
    ):
        _buff(buff),
        _send_fcn(send_fcn)
    {
        /* NOP */
    }

    ~managed_send_buffer_impl(void){
        /* NOP */
    }

    void commit(size_t num_bytes){
        _send_fcn(boost::asio::buffer(_buff, num_bytes));
    }

private:
    const boost::asio::mutable_buffer &get(void) const{
        return _buff;
    }

    const boost::asio::mutable_buffer _buff;
    const send_fcn_t                  _send_fcn;
};

//! phony zero-copy send interface implementation
struct phony_zero_copy_send_if::impl{
    boost::uint8_t *send_mem;
    managed_send_buffer::sptr send_buff;
};

phony_zero_copy_send_if::phony_zero_copy_send_if(size_t max_buff_size){
    _impl = UHD_PIMPL_MAKE(impl, ());
    _impl->send_mem = new boost::uint8_t[max_buff_size];
    _impl->send_buff = managed_send_buffer::sptr(new managed_send_buffer_impl(
        boost::asio::buffer(_impl->send_mem, max_buff_size),
        boost::bind(&phony_zero_copy_send_if::send, this, _1)
    ));
}

phony_zero_copy_send_if::~phony_zero_copy_send_if(void){
    delete [] _impl->send_mem;
}

managed_send_buffer::sptr phony_zero_copy_send_if::get_send_buff(void){
    return _impl->send_buff; //FIXME there is only ever one send buff, we assume that the caller doesnt hang onto these
}