Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-08-27 08:47:18

0001 // Licensed to the Apache Software Foundation (ASF) under one
0002 // or more contributor license agreements.  See the NOTICE file
0003 // distributed with this work for additional information
0004 // regarding copyright ownership.  The ASF licenses this file
0005 // to you under the Apache License, Version 2.0 (the
0006 // "License"); you may not use this file except in compliance
0007 // with the License.  You may obtain a copy of the License at
0008 //
0009 //   http://www.apache.org/licenses/LICENSE-2.0
0010 //
0011 // Unless required by applicable law or agreed to in writing,
0012 // software distributed under the License is distributed on an
0013 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0014 // KIND, either express or implied.  See the License for the
0015 // specific language governing permissions and limitations
0016 // under the License.
0017 
0018 #pragma once
0019 
0020 #include <cstdint>
0021 #include <cstring>
0022 #include <memory>
0023 #include <optional>
0024 #include <string>
0025 #include <string_view>
0026 #include <utility>
0027 #include <vector>
0028 
0029 #include "arrow/device.h"
0030 #include "arrow/status.h"
0031 #include "arrow/type_fwd.h"
0032 #include "arrow/util/macros.h"
0033 #include "arrow/util/span.h"
0034 #include "arrow/util/visibility.h"
0035 
0036 namespace arrow {
0037 
0038 // ----------------------------------------------------------------------
0039 // Buffer classes
0040 
0041 /// \class Buffer
0042 /// \brief Object containing a pointer to a piece of contiguous memory with a
0043 /// particular size.
0044 ///
0045 /// Buffers have two related notions of length: size and capacity. Size is
0046 /// the number of bytes that might have valid data. Capacity is the number
0047 /// of bytes that were allocated for the buffer in total.
0048 ///
0049 /// The Buffer base class does not own its memory, but subclasses often do.
0050 ///
0051 /// The following invariant is always true: Size <= Capacity
0052 class ARROW_EXPORT Buffer {
0053  public:
0054   ARROW_DISALLOW_COPY_AND_ASSIGN(Buffer);
0055 
0056   /// \brief Construct from buffer and size without copying memory
0057   ///
0058   /// \param[in] data a memory buffer
0059   /// \param[in] size buffer size
0060   ///
0061   /// \note The passed memory must be kept alive through some other means
0062   Buffer(const uint8_t* data, int64_t size)
0063       : is_mutable_(false),
0064         is_cpu_(true),
0065         data_(data),
0066         size_(size),
0067         capacity_(size),
0068         device_type_(DeviceAllocationType::kCPU) {
0069     SetMemoryManager(default_cpu_memory_manager());
0070   }
0071 
0072   Buffer(const uint8_t* data, int64_t size, std::shared_ptr<MemoryManager> mm,
0073          std::shared_ptr<Buffer> parent = NULLPTR,
0074          std::optional<DeviceAllocationType> device_type_override = std::nullopt)
0075       : is_mutable_(false),
0076         data_(data),
0077         size_(size),
0078         capacity_(size),
0079         parent_(std::move(parent)) {
0080     // SetMemoryManager will also set device_type_
0081     SetMemoryManager(std::move(mm));
0082     // If a device type is specified, use that instead. Example of when this can be
0083     // useful: the CudaMemoryManager can set device_type_ to kCUDA, but you can specify
0084     // device_type_override=kCUDA_HOST as the device type to override it.
0085     if (device_type_override != std::nullopt) {
0086       device_type_ = *device_type_override;
0087     }
0088   }
0089 
0090   Buffer(uintptr_t address, int64_t size, std::shared_ptr<MemoryManager> mm,
0091          std::shared_ptr<Buffer> parent = NULLPTR)
0092       : Buffer(reinterpret_cast<const uint8_t*>(address), size, std::move(mm),
0093                std::move(parent)) {}
0094 
0095   /// \brief Construct from string_view without copying memory
0096   ///
0097   /// \param[in] data a string_view object
0098   ///
0099   /// \note The memory viewed by data must not be deallocated in the lifetime of the
0100   /// Buffer; temporary rvalue strings must be stored in an lvalue somewhere
0101   explicit Buffer(std::string_view data)
0102       : Buffer(reinterpret_cast<const uint8_t*>(data.data()),
0103                static_cast<int64_t>(data.size())) {}
0104 
0105   virtual ~Buffer() = default;
0106 
0107   /// An offset into data that is owned by another buffer, but we want to be
0108   /// able to retain a valid pointer to it even after other shared_ptr's to the
0109   /// parent buffer have been destroyed
0110   ///
0111   /// This method makes no assertions about alignment or padding of the buffer but
0112   /// in general we expected buffers to be aligned and padded to 64 bytes.  In the future
0113   /// we might add utility methods to help determine if a buffer satisfies this contract.
0114   Buffer(const std::shared_ptr<Buffer>& parent, const int64_t offset, const int64_t size)
0115       : Buffer(parent->data_ + offset, size) {
0116     parent_ = parent;
0117     SetMemoryManager(parent->memory_manager_);
0118   }
0119 
0120   uint8_t operator[](std::size_t i) const { return data_[i]; }
0121 
0122   /// \brief Construct a new std::string with a hexadecimal representation of the buffer.
0123   /// \return std::string
0124   std::string ToHexString();
0125 
0126   /// Return true if both buffers are the same size and contain the same bytes
0127   /// up to the number of compared bytes
0128   bool Equals(const Buffer& other, int64_t nbytes) const;
0129 
0130   /// Return true if both buffers are the same size and contain the same bytes
0131   bool Equals(const Buffer& other) const;
0132 
0133   /// Copy a section of the buffer into a new Buffer.
0134   Result<std::shared_ptr<Buffer>> CopySlice(
0135       const int64_t start, const int64_t nbytes,
0136       MemoryPool* pool = default_memory_pool()) const;
0137 
0138   /// Zero bytes in padding, i.e. bytes between size_ and capacity_.
0139   void ZeroPadding() {
0140 #ifndef NDEBUG
0141     CheckMutable();
0142 #endif
0143     // A zero-capacity buffer can have a null data pointer
0144     if (capacity_ != 0) {
0145       memset(mutable_data() + size_, 0, static_cast<size_t>(capacity_ - size_));
0146     }
0147   }
0148 
0149   /// \brief Construct an immutable buffer that takes ownership of the contents
0150   /// of an std::string (without copying it).
0151   ///
0152   /// \param[in] data a string to own
0153   /// \return a new Buffer instance
0154   static std::shared_ptr<Buffer> FromString(std::string data);
0155 
0156   /// \brief Construct an immutable buffer that takes ownership of the contents
0157   /// of an std::vector (without copying it). Only vectors of TrivialType objects
0158   /// (integers, floating point numbers, ...) can be wrapped by this function.
0159   ///
0160   /// \param[in] vec a vector to own
0161   /// \return a new Buffer instance
0162   template <typename T>
0163   static std::shared_ptr<Buffer> FromVector(std::vector<T> vec) {
0164     static_assert(std::is_trivial_v<T>,
0165                   "Buffer::FromVector can only wrap vectors of trivial objects");
0166 
0167     if (vec.empty()) {
0168       return std::shared_ptr<Buffer>{new Buffer()};
0169     }
0170 
0171     auto* data = reinterpret_cast<uint8_t*>(vec.data());
0172     auto size_in_bytes = static_cast<int64_t>(vec.size() * sizeof(T));
0173     return std::shared_ptr<Buffer>{
0174         new Buffer{data, size_in_bytes},
0175         // Keep the vector's buffer alive inside the shared_ptr's destructor until after
0176         // we have deleted the Buffer. Note we can't use this trick in FromString since
0177         // std::string's data is inline for short strings so moving invalidates pointers
0178         // into the string's buffer.
0179         [vec = std::move(vec)](Buffer* buffer) { delete buffer; }};
0180   }
0181 
0182   /// \brief Create buffer referencing typed memory with some length without
0183   /// copying
0184   /// \param[in] data the typed memory as C array
0185   /// \param[in] length the number of values in the array
0186   /// \return a new shared_ptr<Buffer>
0187   template <typename T, typename SizeType = int64_t>
0188   static std::shared_ptr<Buffer> Wrap(const T* data, SizeType length) {
0189     return std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(data),
0190                                     static_cast<int64_t>(sizeof(T) * length));
0191   }
0192 
0193   /// \brief Create buffer referencing std::vector with some length without
0194   /// copying
0195   /// \param[in] data the vector to be referenced. If this vector is changed,
0196   /// the buffer may become invalid
0197   /// \return a new shared_ptr<Buffer>
0198   template <typename T>
0199   static std::shared_ptr<Buffer> Wrap(const std::vector<T>& data) {
0200     return std::make_shared<Buffer>(reinterpret_cast<const uint8_t*>(data.data()),
0201                                     static_cast<int64_t>(sizeof(T) * data.size()));
0202   }
0203 
0204   /// \brief Copy buffer contents into a new std::string
0205   /// \return std::string
0206   /// \note Can throw std::bad_alloc if buffer is large
0207   std::string ToString() const;
0208 
0209   /// \brief View buffer contents as a std::string_view
0210   /// \return std::string_view
0211   explicit operator std::string_view() const {
0212     return {reinterpret_cast<const char*>(data_), static_cast<size_t>(size_)};
0213   }
0214 
0215   /// \brief Return a pointer to the buffer's data
0216   ///
0217   /// The buffer has to be a CPU buffer (`is_cpu()` is true).
0218   /// Otherwise, an assertion may be thrown or a null pointer may be returned.
0219   ///
0220   /// To get the buffer's data address regardless of its device, call `address()`.
0221   const uint8_t* data() const {
0222 #ifndef NDEBUG
0223     CheckCPU();
0224 #endif
0225     return ARROW_PREDICT_TRUE(is_cpu_) ? data_ : NULLPTR;
0226   }
0227 
0228   /// \brief Return a pointer to the buffer's data cast to a specific type
0229   ///
0230   /// The buffer has to be a CPU buffer (`is_cpu()` is true).
0231   /// Otherwise, an assertion may be thrown or a null pointer may be returned.
0232   template <typename T>
0233   const T* data_as() const {
0234     return reinterpret_cast<const T*>(data());
0235   }
0236 
0237   /// \brief Return the buffer's data as a span
0238   template <typename T>
0239   util::span<const T> span_as() const {
0240     return util::span(data_as<T>(), static_cast<size_t>(size() / sizeof(T)));
0241   }
0242 
0243   /// \brief Return a writable pointer to the buffer's data
0244   ///
0245   /// The buffer has to be a mutable CPU buffer (`is_cpu()` and `is_mutable()`
0246   /// are true).  Otherwise, an assertion may be thrown or a null pointer may
0247   /// be returned.
0248   ///
0249   /// To get the buffer's mutable data address regardless of its device, call
0250   /// `mutable_address()`.
0251   uint8_t* mutable_data() {
0252 #ifndef NDEBUG
0253     CheckCPU();
0254     CheckMutable();
0255 #endif
0256     return ARROW_PREDICT_TRUE(is_cpu_ && is_mutable_) ? const_cast<uint8_t*>(data_)
0257                                                       : NULLPTR;
0258   }
0259 
0260   /// \brief Return a writable pointer to the buffer's data cast to a specific type
0261   ///
0262   /// The buffer has to be a mutable CPU buffer (`is_cpu()` and `is_mutable()`
0263   /// are true).  Otherwise, an assertion may be thrown or a null pointer may
0264   /// be returned.
0265   template <typename T>
0266   T* mutable_data_as() {
0267     return reinterpret_cast<T*>(mutable_data());
0268   }
0269 
0270   /// \brief Return the buffer's mutable data as a span
0271   template <typename T>
0272   util::span<T> mutable_span_as() {
0273     return util::span(mutable_data_as<T>(), static_cast<size_t>(size() / sizeof(T)));
0274   }
0275 
0276   /// \brief Return the device address of the buffer's data
0277   uintptr_t address() const { return reinterpret_cast<uintptr_t>(data_); }
0278 
0279   /// \brief Return a writable device address to the buffer's data
0280   ///
0281   /// The buffer has to be a mutable buffer (`is_mutable()` is true).
0282   /// Otherwise, an assertion may be thrown or 0 may be returned.
0283   uintptr_t mutable_address() const {
0284 #ifndef NDEBUG
0285     CheckMutable();
0286 #endif
0287     return ARROW_PREDICT_TRUE(is_mutable_) ? reinterpret_cast<uintptr_t>(data_) : 0;
0288   }
0289 
0290   /// \brief Return the buffer's size in bytes
0291   int64_t size() const { return size_; }
0292 
0293   /// \brief Return the buffer's capacity (number of allocated bytes)
0294   int64_t capacity() const { return capacity_; }
0295 
0296   /// \brief Whether the buffer is directly CPU-accessible
0297   ///
0298   /// If this function returns true, you can read directly from the buffer's
0299   /// `data()` pointer.  Otherwise, you'll have to `View()` or `Copy()` it.
0300   bool is_cpu() const { return is_cpu_; }
0301 
0302   /// \brief Whether the buffer is mutable
0303   ///
0304   /// If this function returns true, you are allowed to modify buffer contents
0305   /// using the pointer returned by `mutable_data()` or `mutable_address()`.
0306   bool is_mutable() const { return is_mutable_; }
0307 
0308   const std::shared_ptr<Device>& device() const { return memory_manager_->device(); }
0309 
0310   const std::shared_ptr<MemoryManager>& memory_manager() const { return memory_manager_; }
0311 
0312   DeviceAllocationType device_type() const { return device_type_; }
0313 
0314   std::shared_ptr<Buffer> parent() const { return parent_; }
0315 
0316   /// \brief Get a RandomAccessFile for reading a buffer
0317   ///
0318   /// The returned file object reads from this buffer's underlying memory.
0319   static Result<std::shared_ptr<io::RandomAccessFile>> GetReader(std::shared_ptr<Buffer>);
0320 
0321   /// \brief Get a OutputStream for writing to a buffer
0322   ///
0323   /// The buffer must be mutable.  The returned stream object writes into the buffer's
0324   /// underlying memory (but it won't resize it).
0325   static Result<std::shared_ptr<io::OutputStream>> GetWriter(std::shared_ptr<Buffer>);
0326 
0327   /// \brief Copy buffer
0328   ///
0329   /// The buffer contents will be copied into a new buffer allocated by the
0330   /// given MemoryManager.  This function supports cross-device copies.
0331   static Result<std::shared_ptr<Buffer>> Copy(std::shared_ptr<Buffer> source,
0332                                               const std::shared_ptr<MemoryManager>& to);
0333 
0334   /// \brief Copy a non-owned buffer
0335   ///
0336   /// This is useful for cases where the source memory area is externally managed
0337   /// (its lifetime not tied to the source Buffer), otherwise please use Copy().
0338   static Result<std::unique_ptr<Buffer>> CopyNonOwned(
0339       const Buffer& source, const std::shared_ptr<MemoryManager>& to);
0340 
0341   /// \brief View buffer
0342   ///
0343   /// Return a Buffer that reflects this buffer, seen potentially from another
0344   /// device, without making an explicit copy of the contents.  The underlying
0345   /// mechanism is typically implemented by the kernel or device driver, and may
0346   /// involve lazy caching of parts of the buffer contents on the destination
0347   /// device's memory.
0348   ///
0349   /// If a non-copy view is unsupported for the buffer on the given device,
0350   /// nullptr is returned.  An error can be returned if some low-level
0351   /// operation fails (such as an out-of-memory condition).
0352   static Result<std::shared_ptr<Buffer>> View(std::shared_ptr<Buffer> source,
0353                                               const std::shared_ptr<MemoryManager>& to);
0354 
0355   /// \brief View or copy buffer
0356   ///
0357   /// Try to view buffer contents on the given MemoryManager's device, but
0358   /// fall back to copying if a no-copy view isn't supported.
0359   static Result<std::shared_ptr<Buffer>> ViewOrCopy(
0360       std::shared_ptr<Buffer> source, const std::shared_ptr<MemoryManager>& to);
0361 
0362   virtual std::shared_ptr<Device::SyncEvent> device_sync_event() const { return NULLPTR; }
0363 
0364  protected:
0365   bool is_mutable_;
0366   bool is_cpu_;
0367   const uint8_t* data_;
0368   int64_t size_;
0369   int64_t capacity_;
0370   DeviceAllocationType device_type_;
0371 
0372   // null by default, but may be set
0373   std::shared_ptr<Buffer> parent_;
0374 
0375  private:
0376   // private so that subclasses are forced to call SetMemoryManager()
0377   std::shared_ptr<MemoryManager> memory_manager_;
0378 
0379  protected:
0380   Buffer();
0381 
0382   void CheckMutable() const;
0383   void CheckCPU() const;
0384 
0385   void SetMemoryManager(std::shared_ptr<MemoryManager> mm) {
0386     memory_manager_ = std::move(mm);
0387     is_cpu_ = memory_manager_->is_cpu();
0388     device_type_ = memory_manager_->device()->device_type();
0389   }
0390 };
0391 
0392 /// \defgroup buffer-slicing-functions Functions for slicing buffers
0393 ///
0394 /// @{
0395 
0396 /// \brief Construct a view on a buffer at the given offset and length.
0397 ///
0398 /// This function cannot fail and does not check for errors (except in debug builds)
0399 static inline std::shared_ptr<Buffer> SliceBuffer(const std::shared_ptr<Buffer>& buffer,
0400                                                   const int64_t offset,
0401                                                   const int64_t length) {
0402   return std::make_shared<Buffer>(buffer, offset, length);
0403 }
0404 
0405 /// \brief Construct a view on a buffer at the given offset, up to the buffer's end.
0406 ///
0407 /// This function cannot fail and does not check for errors (except in debug builds)
0408 static inline std::shared_ptr<Buffer> SliceBuffer(const std::shared_ptr<Buffer>& buffer,
0409                                                   const int64_t offset) {
0410   int64_t length = buffer->size() - offset;
0411   return SliceBuffer(buffer, offset, length);
0412 }
0413 
0414 /// \brief Input-checking version of SliceBuffer
0415 ///
0416 /// An Invalid Status is returned if the requested slice falls out of bounds.
0417 ARROW_EXPORT
0418 Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
0419                                                 int64_t offset);
0420 /// \brief Input-checking version of SliceBuffer
0421 ///
0422 /// An Invalid Status is returned if the requested slice falls out of bounds.
0423 /// Note that unlike SliceBuffer, `length` isn't clamped to the available buffer size.
0424 ARROW_EXPORT
0425 Result<std::shared_ptr<Buffer>> SliceBufferSafe(const std::shared_ptr<Buffer>& buffer,
0426                                                 int64_t offset, int64_t length);
0427 
0428 /// \brief Like SliceBuffer, but construct a mutable buffer slice.
0429 ///
0430 /// If the parent buffer is not mutable, behavior is undefined (it may abort
0431 /// in debug builds).
0432 ARROW_EXPORT
0433 std::shared_ptr<Buffer> SliceMutableBuffer(const std::shared_ptr<Buffer>& buffer,
0434                                            const int64_t offset, const int64_t length);
0435 
0436 /// \brief Like SliceBuffer, but construct a mutable buffer slice.
0437 ///
0438 /// If the parent buffer is not mutable, behavior is undefined (it may abort
0439 /// in debug builds).
0440 static inline std::shared_ptr<Buffer> SliceMutableBuffer(
0441     const std::shared_ptr<Buffer>& buffer, const int64_t offset) {
0442   int64_t length = buffer->size() - offset;
0443   return SliceMutableBuffer(buffer, offset, length);
0444 }
0445 
0446 /// \brief Input-checking version of SliceMutableBuffer
0447 ///
0448 /// An Invalid Status is returned if the requested slice falls out of bounds.
0449 ARROW_EXPORT
0450 Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
0451     const std::shared_ptr<Buffer>& buffer, int64_t offset);
0452 /// \brief Input-checking version of SliceMutableBuffer
0453 ///
0454 /// An Invalid Status is returned if the requested slice falls out of bounds.
0455 /// Note that unlike SliceBuffer, `length` isn't clamped to the available buffer size.
0456 ARROW_EXPORT
0457 Result<std::shared_ptr<Buffer>> SliceMutableBufferSafe(
0458     const std::shared_ptr<Buffer>& buffer, int64_t offset, int64_t length);
0459 
0460 /// @}
0461 
0462 /// \class MutableBuffer
0463 /// \brief A Buffer whose contents can be mutated. May or may not own its data.
0464 class ARROW_EXPORT MutableBuffer : public Buffer {
0465  public:
0466   MutableBuffer(uint8_t* data, const int64_t size) : Buffer(data, size) {
0467     is_mutable_ = true;
0468   }
0469 
0470   MutableBuffer(uint8_t* data, const int64_t size, std::shared_ptr<MemoryManager> mm)
0471       : Buffer(data, size, std::move(mm)) {
0472     is_mutable_ = true;
0473   }
0474 
0475   MutableBuffer(const std::shared_ptr<Buffer>& parent, const int64_t offset,
0476                 const int64_t size);
0477 
0478   /// \brief Create buffer referencing typed memory with some length
0479   /// \param[in] data the typed memory as C array
0480   /// \param[in] length the number of values in the array
0481   /// \return a new shared_ptr<Buffer>
0482   template <typename T, typename SizeType = int64_t>
0483   static std::shared_ptr<Buffer> Wrap(T* data, SizeType length) {
0484     return std::make_shared<MutableBuffer>(reinterpret_cast<uint8_t*>(data),
0485                                            static_cast<int64_t>(sizeof(T) * length));
0486   }
0487 
0488  protected:
0489   MutableBuffer() : Buffer(NULLPTR, 0) {}
0490 };
0491 
0492 /// \class ResizableBuffer
0493 /// \brief A mutable buffer that can be resized
0494 class ARROW_EXPORT ResizableBuffer : public MutableBuffer {
0495  public:
0496   /// Change buffer reported size to indicated size, allocating memory if
0497   /// necessary.  This will ensure that the capacity of the buffer is a multiple
0498   /// of 64 bytes as defined in Layout.md.
0499   /// Consider using ZeroPadding afterwards, to conform to the Arrow layout
0500   /// specification.
0501   ///
0502   /// @param new_size The new size for the buffer.
0503   /// @param shrink_to_fit Whether to shrink the capacity if new size < current size
0504   virtual Status Resize(const int64_t new_size, bool shrink_to_fit) = 0;
0505   Status Resize(const int64_t new_size) {
0506     return Resize(new_size, /*shrink_to_fit=*/true);
0507   }
0508 
0509   /// Ensure that buffer has enough memory allocated to fit the indicated
0510   /// capacity (and meets the 64 byte padding requirement in Layout.md).
0511   /// It does not change buffer's reported size and doesn't zero the padding.
0512   virtual Status Reserve(const int64_t new_capacity) = 0;
0513 
0514   template <class T>
0515   Status TypedResize(const int64_t new_nb_elements, bool shrink_to_fit = true) {
0516     return Resize(sizeof(T) * new_nb_elements, shrink_to_fit);
0517   }
0518 
0519   template <class T>
0520   Status TypedReserve(const int64_t new_nb_elements) {
0521     return Reserve(sizeof(T) * new_nb_elements);
0522   }
0523 
0524  protected:
0525   ResizableBuffer(uint8_t* data, int64_t size) : MutableBuffer(data, size) {}
0526   ResizableBuffer(uint8_t* data, int64_t size, std::shared_ptr<MemoryManager> mm)
0527       : MutableBuffer(data, size, std::move(mm)) {}
0528 };
0529 
0530 /// \defgroup buffer-allocation-functions Functions for allocating buffers
0531 ///
0532 /// @{
0533 
0534 /// \brief Allocate a fixed size mutable buffer from a memory pool, zero its padding.
0535 ///
0536 /// \param[in] size size of buffer to allocate
0537 /// \param[in] pool a memory pool
0538 ARROW_EXPORT
0539 Result<std::unique_ptr<Buffer>> AllocateBuffer(const int64_t size,
0540                                                MemoryPool* pool = NULLPTR);
0541 ARROW_EXPORT
0542 Result<std::unique_ptr<Buffer>> AllocateBuffer(const int64_t size, int64_t alignment,
0543                                                MemoryPool* pool = NULLPTR);
0544 
0545 /// \brief Allocate a resizeable buffer from a memory pool, zero its padding.
0546 ///
0547 /// \param[in] size size of buffer to allocate
0548 /// \param[in] pool a memory pool
0549 ARROW_EXPORT
0550 Result<std::unique_ptr<ResizableBuffer>> AllocateResizableBuffer(
0551     const int64_t size, MemoryPool* pool = NULLPTR);
0552 ARROW_EXPORT
0553 Result<std::unique_ptr<ResizableBuffer>> AllocateResizableBuffer(
0554     const int64_t size, const int64_t alignment, MemoryPool* pool = NULLPTR);
0555 
0556 /// \brief Allocate a bitmap buffer from a memory pool
0557 /// no guarantee on values is provided.
0558 ///
0559 /// \param[in] length size in bits of bitmap to allocate
0560 /// \param[in] pool memory pool to allocate memory from
0561 ARROW_EXPORT
0562 Result<std::shared_ptr<Buffer>> AllocateBitmap(int64_t length,
0563                                                MemoryPool* pool = NULLPTR);
0564 
0565 /// \brief Allocate a zero-initialized bitmap buffer from a memory pool
0566 ///
0567 /// \param[in] length size in bits of bitmap to allocate
0568 /// \param[in] pool memory pool to allocate memory from
0569 ARROW_EXPORT
0570 Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length,
0571                                                     MemoryPool* pool = NULLPTR);
0572 
0573 ARROW_EXPORT
0574 Result<std::shared_ptr<Buffer>> AllocateEmptyBitmap(int64_t length, int64_t alignment,
0575                                                     MemoryPool* pool = NULLPTR);
0576 
0577 /// \brief Concatenate multiple buffers into a single buffer
0578 ///
0579 /// \param[in] buffers to be concatenated
0580 /// \param[in] pool memory pool to allocate the new buffer from
0581 ARROW_EXPORT
0582 Result<std::shared_ptr<Buffer>> ConcatenateBuffers(const BufferVector& buffers,
0583                                                    MemoryPool* pool = NULLPTR);
0584 
0585 /// @}
0586 
0587 }  // namespace arrow