bulk.hpp 8.79 KB
Newer Older
Matthieu Dorier's avatar
Matthieu Dorier committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/*
 * (C) 2017 The University of Chicago
 * 
 * See COPYRIGHT in top-level directory.
 */
#ifndef __THALLIUM_BULK_HPP
#define __THALLIUM_BULK_HPP

#include <cstdint>
#include <string>
#include <vector>
#include <margo.h>
#include <thallium/endpoint.hpp>
14
#include <thallium/margo_exception.hpp>
Matthieu Dorier's avatar
Matthieu Dorier committed
15 16 17 18

namespace thallium {

class engine;
Matthieu Dorier's avatar
Matthieu Dorier committed
19
class remote_bulk;
Matthieu Dorier's avatar
Matthieu Dorier committed
20

Matthieu Dorier's avatar
Matthieu Dorier committed
21 22 23 24 25
/**
 * @brief bulk objects represent abstractions of memory
 * segments exposed by a process for RDMA operations. A bulk
 * object can be serialized to be sent over RPC to another process.
 */
Matthieu Dorier's avatar
Matthieu Dorier committed
26 27 28
class bulk {

    friend class engine;
Matthieu Dorier's avatar
Matthieu Dorier committed
29
    friend class remote_bulk;
Matthieu Dorier's avatar
Matthieu Dorier committed
30 31 32 33 34 35 36

private:

    engine*   m_engine;
	hg_bulk_t m_bulk;
    bool      m_is_local;

Matthieu Dorier's avatar
Matthieu Dorier committed
37 38 39 40 41 42 43 44 45 46
    /**
     * @brief Constructor. Made private as bulk objects
     * are instanciated by engine::expose (for example),
     * not directory by users.
     *
     * @param e Reference to the engine instance creating the object.
     * @param b Mercury bulk handle.
     * @param local Whether the bulk handle referes to memory that is
     * local to this process.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
47 48 49
	bulk(engine& e, hg_bulk_t b, bool local)
	: m_engine(&e), m_bulk(b), m_is_local(local) {}

Matthieu Dorier's avatar
Matthieu Dorier committed
50 51 52 53
    /**
     * @brief The bulk_segment class represents a portion
     * (represented by offset and size) of a bulk object.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
54 55
    class bulk_segment {

Matthieu Dorier's avatar
Matthieu Dorier committed
56
        friend class remote_bulk;
Matthieu Dorier's avatar
Matthieu Dorier committed
57 58 59 60 61 62 63
        
        std::size_t m_offset;
        std::size_t m_size;
        const bulk& m_bulk;

        public:

Matthieu Dorier's avatar
Matthieu Dorier committed
64 65 66 67 68 69
        /**
         * @brief Constructor. By default the size of the segment will be
         * that of the underlying bulk object, and the offset is 0.
         *
         * @param b Reference to the bulk object from which the segment is taken.
         */
Matthieu Dorier's avatar
Matthieu Dorier committed
70 71 72
        bulk_segment(const bulk& b)
        : m_offset(0), m_size(b.size()), m_bulk(b) {}

Matthieu Dorier's avatar
Matthieu Dorier committed
73 74 75 76 77 78 79
        /**
         * @brief Constructor.
         *
         * @param b Reference to the bulk object from which the segment is taken.
         * @param offset Offset at which the segment starts.
         * @param size Size of the segment.
         */
Matthieu Dorier's avatar
Matthieu Dorier committed
80 81 82
        bulk_segment(const bulk& b, std::size_t offset, std::size_t size)
        : m_offset(offset), m_size(size), m_bulk(b) {}

Matthieu Dorier's avatar
Matthieu Dorier committed
83 84 85
        /**
         * @brief Copy constructor is deleted.
         */
Matthieu Dorier's avatar
Matthieu Dorier committed
86
        bulk_segment(const bulk_segment&) = default;
Matthieu Dorier's avatar
Matthieu Dorier committed
87 88 89 90

        /**
         * @brief Move constructor is default.
         */
Matthieu Dorier's avatar
Matthieu Dorier committed
91 92
        bulk_segment(bulk_segment&&)      = default;

Matthieu Dorier's avatar
Matthieu Dorier committed
93 94 95
        /**
         * @brief Destructor is default.
         */
Matthieu Dorier's avatar
Matthieu Dorier committed
96 97
        ~bulk_segment()                   = default;

Matthieu Dorier's avatar
Matthieu Dorier committed
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
        /**
         * @brief Associates the bulk segment with an endpoint to represent
         * a remote_bulk object.
         *
         * @param ep Endpoint where the bulk object has bee created.
         *
         * @return a remote_bulk object.
         */
        remote_bulk on(const endpoint& ep) const;

        /**
         * @brief Pushes data from the left operand (bulk_segment)
         * to the right operand (remote_bulk). If the size of the
         * segments don't match, the smallest size is used.
         *
         * @param b remote_bulk object towards which to push data.
         *
         * @return the size of data transfered.
         */
        std::size_t operator>>(const remote_bulk& b) const;

        /**
         * @brief Pulls data from the right operand (remote_bulk)
         * to the right operand (bulk_segment). If the size of the
         * segments don't match, the smallest size is used.
         *
         * @param b remote_bulk object from which to pull data.
         *
         * @return the size of data transfered.
         */
        std::size_t operator<<(const remote_bulk& b) const;
Matthieu Dorier's avatar
Matthieu Dorier committed
129 130 131 132
    };

public:

Matthieu Dorier's avatar
Matthieu Dorier committed
133 134 135 136
    /**
     * @brief Default constructor, defined so that one can have a bulk
     * object as class member and associate it later with an actual bulk.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
137 138 139
    bulk()
    : m_engine(nullptr), m_bulk(HG_BULK_NULL), m_is_local(false) {}

Matthieu Dorier's avatar
Matthieu Dorier committed
140 141 142
    /**
     * @brief Copy constructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
143 144
	bulk(const bulk& other)
    : m_engine(other.m_engine), m_bulk(other.m_bulk), m_is_local(other.m_is_local) {
145 146
        hg_return_t ret = margo_bulk_ref_incr(m_bulk);
        MARGO_ASSERT(ret, margo_bulk_ref_incr);
Matthieu Dorier's avatar
Matthieu Dorier committed
147 148
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
149 150 151
    /**
     * @brief Move constructor.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
152 153 154 155 156
	bulk(bulk&& other)
	: m_engine(other.m_engine), m_bulk(other.m_bulk), m_is_local(std::move(other.m_is_local)) {
		other.m_bulk     = HG_BULK_NULL;
	}

Matthieu Dorier's avatar
Matthieu Dorier committed
157 158 159
    /**
     * @brief Copy-assignment operator.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
160 161 162
	bulk& operator=(const bulk& other) {
        if(this == &other) return *this;
        if(m_bulk != HG_BULK_NULL) {
163 164
            hg_return_t ret = margo_bulk_free(m_bulk);
            MARGO_ASSERT(ret, margo_bulk_free);
Matthieu Dorier's avatar
Matthieu Dorier committed
165 166 167 168 169
        }
        m_bulk     = other.m_bulk;
        m_engine   = other.m_engine;
        m_is_local = other.m_is_local;
        if(m_bulk != HG_BULK_NULL) {
170 171
            hg_return_t ret = margo_bulk_ref_incr(m_bulk);
            MARGO_ASSERT(ret, margo_bulk_ref_incr);
Matthieu Dorier's avatar
Matthieu Dorier committed
172 173 174 175
        }
        return *this;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
176 177 178
    /**
     * @brief Move-assignment operator.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
179 180 181
	bulk& operator=(bulk&& other) {
        if(this == &other) return *this;
        if(m_bulk != HG_BULK_NULL) {
182 183
            hg_return_t ret = margo_bulk_free(m_bulk);
            MARGO_ASSERT(ret, margo_bulk_free);
Matthieu Dorier's avatar
Matthieu Dorier committed
184 185 186 187 188 189 190 191
        }
        m_engine     = other.m_engine;
        m_bulk       = other.m_bulk;
        m_is_local   = other.m_is_local;
        other.m_bulk = HG_BULK_NULL;
        return *this;
    }
	
Matthieu Dorier's avatar
Matthieu Dorier committed
192 193 194
    /**
     * @brief Destructor.
     */
195
	~bulk() throw(margo_exception) {
Matthieu Dorier's avatar
Matthieu Dorier committed
196
        if(m_bulk != HG_BULK_NULL) {
197 198
            hg_return_t ret = margo_bulk_free(m_bulk);
            MARGO_ASSERT(ret, margo_bulk_free);
Matthieu Dorier's avatar
Matthieu Dorier committed
199 200 201
        }
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
202 203 204 205 206
    /**
     * @brief Returns the size of the data exposed by the bulk object.
     *
     * @return size of data exposed by the bulk object.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
207 208 209 210 211 212 213
    std::size_t size() const {
        if(m_bulk != HG_BULK_NULL)
            return margo_bulk_get_size(m_bulk);
        else
            return 0;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
214 215 216 217 218
    /**
     * @brief Indicates whether the bulk handle is null.
     *
     * @return true if the bulk handle is null, false otherwise.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
219 220 221 222
    bool is_null() const {
        return m_bulk == HG_BULK_NULL;
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
    /**
     * @brief Builds a remote_bulk object by associating it with an endpoint.
     *
     * @param ep endpoint with which the bulk object should be associated.
     *
     * @return a remote_bulk instance.
     */
    remote_bulk on(const endpoint& ep) const;

    /**
     * @brief Creates a bulk_segment object by selecting a given portion
     * of the bulk object given an offset and a size.
     *
     * @param offset Offset at which the segment starts.
     * @param size Size of the segment.
     *
     * @return a bulk_segment object.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
241 242 243
    bulk_segment select(std::size_t offset, std::size_t size) const;


Matthieu Dorier's avatar
Matthieu Dorier committed
244 245 246 247
    /**
     * @see bulk::select
     */
    bulk_segment operator()(std::size_t offset, std::size_t size) const;
248

Matthieu Dorier's avatar
Matthieu Dorier committed
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
    /**
     * @brief Pushes data from the left operand (entire bulk object)
     * to the right operand (remote_bulk). If the size of the
     * segments don't match, the smallest size is used.
     *
     * @param b remote_bulk object towards which to push data.
     *
     * @return the size of data transfered.
     */
    std::size_t operator>>(const remote_bulk& b) const;

    /**
     * @brief Pulls data from the right operand (remote_bulk)
     * to the left operand (bulk). If the size of the
     * segments don't match, the smallest size is used.
     *
     * @param b remote_bulk object from which to pull data.
     *
     * @return the size of data transfered.
     */
    std::size_t operator<<(const remote_bulk& b) const;

    /**
     * @brief Function that serializes a bulk object into an archive.
     *
     * @tparam A Archive type.
     * @param ar Input archive.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
277 278
    template<typename A>
    void save(A& ar) {
Matthieu Dorier's avatar
Matthieu Dorier committed
279 280 281 282 283 284
        if(m_bulk == HG_BULK_NULL) {
            std::vector<char> buf;
            ar & buf;
        } else {
            hg_size_t s = margo_bulk_get_serialize_size(m_bulk, HG_TRUE);
            std::vector<char> buf(s);
285 286
            hg_return_t ret = margo_bulk_serialize(&buf[0], s, HG_TRUE, m_bulk);
            MARGO_ASSERT(ret, margo_bulk_serialize);
Matthieu Dorier's avatar
Matthieu Dorier committed
287 288
            ar & buf;
        }
Matthieu Dorier's avatar
Matthieu Dorier committed
289 290
    }

Matthieu Dorier's avatar
Matthieu Dorier committed
291 292 293 294 295 296
    /**
     * @brief Deserializes a bulk object from an output archive.
     *
     * @tparam A Archive type.
     * @param ar Output archive.
     */
Matthieu Dorier's avatar
Matthieu Dorier committed
297 298 299 300 301 302 303 304 305 306 307 308 309
    template<typename A>
    void load(A& ar);

};

}

#include <thallium/engine.hpp>

namespace thallium {

template<typename A>
void bulk::load(A& ar) {
Matthieu Dorier's avatar
Matthieu Dorier committed
310 311 312
    if(!is_null()) {
        *this = bulk(); // reset
    }
Matthieu Dorier's avatar
Matthieu Dorier committed
313 314
    std::vector<char> buf;
    ar & buf;
Matthieu Dorier's avatar
Matthieu Dorier committed
315 316
    if(buf.size() > 0) {
        m_engine = &(ar.get_engine());
317 318
        hg_return_t ret = margo_bulk_deserialize(m_engine->m_mid, &m_bulk, &buf[0], buf.size());
        MARGO_ASSERT(ret, margo_bulk_deserialize);
Matthieu Dorier's avatar
Matthieu Dorier committed
319 320
        m_is_local = false;
    }
Matthieu Dorier's avatar
Matthieu Dorier committed
321 322 323 324 325
}

}

#endif