Files
scylladb/core/temporary_buffer.hh
Paweł Dziepak 5d65f045f5 temporary_buffer: use posix_memalign() return value
The proper way to test whether posix_memalign() failed is to check its
return value, not the content of the pointer.

This also silences "ignoring return value of 'posix_memalign()'" diagnostic
messages.

Signed-off-by: Paweł Dziepak <pdziepak@quarnos.org>
Reviewed-by: Raphael S. Carvalho <raphaelsc@cloudius-systems.com>
2015-04-20 10:32:11 +03:00

113 lines
3.7 KiB
C++

/*
* This file is open source software, licensed to you under the terms
* of the Apache License, Version 2.0 (the "License"). See the NOTICE file
* distributed with this work for additional information regarding copyright
* ownership. You may not use this file except in compliance with the License.
*
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
/*
* Copyright (C) 2014 Cloudius Systems, Ltd.
*/
#ifndef TEMPORARY_BUFFER_HH_
#define TEMPORARY_BUFFER_HH_
#include "deleter.hh"
#include "util/eclipse.hh"
#include <malloc.h>
// A temporary_buffer either points inside a larger buffer, or, if the requested size
// is too large, or if the larger buffer is scattered, contains its own storage.
template <typename CharType>
class temporary_buffer {
static_assert(sizeof(CharType) == 1, "must buffer stream of bytes");
CharType* _buffer;
size_t _size;
deleter _deleter;
public:
explicit temporary_buffer(size_t size)
: _buffer(static_cast<CharType*>(malloc(size * sizeof(CharType)))), _size(size)
, _deleter(make_free_deleter(_buffer)) {
if (size && !_buffer) {
throw std::bad_alloc();
}
}
//explicit temporary_buffer(CharType* borrow, size_t size) : _buffer(borrow), _size(size) {}
temporary_buffer()
: _buffer(nullptr)
, _size(0) {}
temporary_buffer(const temporary_buffer&) = delete;
temporary_buffer(temporary_buffer&& x) : _buffer(x._buffer), _size(x._size), _deleter(std::move(x._deleter)) {
x._buffer = nullptr;
x._size = 0;
}
temporary_buffer(CharType* buf, size_t size, deleter d)
: _buffer(buf), _size(size), _deleter(std::move(d)) {}
void operator=(const temporary_buffer&) = delete;
temporary_buffer& operator=(temporary_buffer&& x) {
if (this != &x) {
_buffer = x._buffer;
_size = x._size;
_deleter = std::move(x._deleter);
x._buffer = nullptr;
x._size = 0;
}
return *this;
}
const CharType* get() const { return _buffer; }
CharType* get_write() { return _buffer; }
size_t size() const { return _size; }
const CharType* begin() { return _buffer; }
const CharType* end() { return _buffer + _size; }
temporary_buffer prefix(size_t size) && {
auto ret = std::move(*this);
ret._size = size;
return ret;
}
CharType operator[](size_t pos) const {
return _buffer[pos];
}
bool empty() const { return !size(); }
operator bool() { return size(); }
temporary_buffer share() {
return temporary_buffer(_buffer, _size, _deleter.share());
}
temporary_buffer share(size_t pos, size_t len) {
auto ret = share();
ret._buffer += pos;
ret._size = len;
return ret;
}
void trim_front(size_t pos) {
_buffer += pos;
_size -= pos;
}
void trim(size_t pos) {
_size = pos;
}
deleter release() {
return std::move(_deleter);
}
static temporary_buffer aligned(size_t alignment, size_t size) {
void *ptr = nullptr;
auto ret = ::posix_memalign(&ptr, alignment, size * sizeof(CharType));
auto buf = static_cast<CharType*>(ptr);
if (ret) {
throw std::bad_alloc();
}
return temporary_buffer(buf, size, make_free_deleter(buf));
}
};
#endif /* TEMPORARY_BUFFER_HH_ */