Skip to content

Commit

Permalink
Type erasure (#231)
Browse files Browse the repository at this point in the history
* Implemented array_wrapper for type erasure

* Added missing methods and members in value_ptr

* Plugged array_wrapper

* Removed class array_base

* operator== workaround implementation to avoid OSX bug

* Specialized basic_common_reference of nullable

* Workaround OSX issue

* Fixed iterator_tag of layouts
  • Loading branch information
JohanMabille authored Oct 10, 2024
1 parent ffc06fb commit 2148ad2
Show file tree
Hide file tree
Showing 25 changed files with 635 additions and 304 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ set(SPARROW_HEADERS
${SPARROW_INCLUDE_DIR}/sparrow/details/3rdparty/float16_t.hpp
# layout
${SPARROW_INCLUDE_DIR}/sparrow/layout/array_base.hpp
${SPARROW_INCLUDE_DIR}/sparrow/layout/array_wrapper.hpp
${SPARROW_INCLUDE_DIR}/sparrow/layout/dictionary_encoded_array.hpp
${SPARROW_INCLUDE_DIR}/sparrow/layout/dictionary_encoded_array/dictionary_encoded_array_bitmap_iterator.hpp
${SPARROW_INCLUDE_DIR}/sparrow/layout/dictionary_encoded_array/dictionary_encoded_array_iterator.hpp
Expand Down
4 changes: 2 additions & 2 deletions include/sparrow/array_factory.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@

#include "sparrow/arrow_array_schema_proxy.hpp"
#include "sparrow/config/config.hpp"
#include "sparrow/layout/array_base.hpp"
#include "sparrow/layout/array_wrapper.hpp"
#include "sparrow/utils/memory.hpp"

namespace sparrow
{
SPARROW_API cloning_ptr<array_base> array_factory(arrow_proxy proxy);
SPARROW_API cloning_ptr<array_wrapper> array_factory(arrow_proxy proxy);

}
54 changes: 8 additions & 46 deletions include/sparrow/layout/array_base.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,34 +36,6 @@ namespace sparrow
return {arrow_proxy.buffers()[bitmap_buffer_index].data(), bitmap_size};
}

/**
* Base class for array type erasure
*/
class array_base
{
public:

virtual ~array_base() = default;

array_base(array_base&&) = delete;
array_base& operator=(const array_base&) = delete;
array_base& operator=(array_base&&) = delete;

array_base* clone() const;

enum data_type data_type() const;

protected:

array_base(enum data_type dt);
array_base(const array_base&) = default;

private:

enum data_type m_data_type;
virtual array_base* clone_impl() const = 0;
};

/**
* Base class for array_inner_types specialization
*
Expand Down Expand Up @@ -167,24 +139,8 @@ namespace sparrow
friend class layout_iterator<self_type, true>;
};

/*****************************
* array_base implementation *
*****************************/

inline array_base* array_base::clone() const
{
return clone_impl();
}

inline enum data_type array_base::data_type() const
{
return m_data_type;
}

inline array_base::array_base(enum data_type dt)
: m_data_type(dt)
{
}
template <class D>
bool operator==(const array_crtp_base<D>& lhs, const array_crtp_base<D>& rhs);

/**********************************
* array_crtp_base implementation *
Expand Down Expand Up @@ -335,4 +291,10 @@ namespace sparrow
{
return *static_cast<const derived_type*>(this);
}

template <class D>
bool operator==(const array_crtp_base<D>& lhs, const array_crtp_base<D>& rhs)
{
return std::ranges::equal(lhs, rhs);
}
}
187 changes: 187 additions & 0 deletions include/sparrow/layout/array_wrapper.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
// Copyright 2024 Man Group Operations Limited
//
// Licensed under the Apache License, Version 2.0 (the "License");
// 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 mplied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <memory>
#include <variant>

#include "sparrow/types/data_traits.hpp"
#include "sparrow/utils/memory.hpp"

namespace sparrow
{
/**
* Base class for array type erasure
*/
class array_wrapper
{
public:

using wrapper_ptr = std::unique_ptr<array_wrapper>;

virtual ~array_wrapper() = default;

array_wrapper(array_wrapper&&) = delete;
array_wrapper& operator=(const array_wrapper&) = delete;
array_wrapper& operator=(array_wrapper&&) = delete;

wrapper_ptr clone() const;

enum data_type data_type() const;

protected:

array_wrapper(enum data_type dt);
array_wrapper(const array_wrapper&) = default;

private:

enum data_type m_data_type;
virtual wrapper_ptr clone_impl() const = 0;
};

template <class T>
class array_wrapper_impl : public array_wrapper
{
public:

array_wrapper_impl(T&& ar);
array_wrapper_impl(T* ar);
array_wrapper_impl(std::shared_ptr<T> ar);

virtual ~array_wrapper_impl() = default;

T& get_wrapped();
const T& get_wrapped() const;

private:

using wrapper_ptr = array_wrapper::wrapper_ptr;

constexpr enum data_type get_data_type() const;

array_wrapper_impl(const array_wrapper_impl&);
wrapper_ptr clone_impl() const override;

using storage_type = std::variant<value_ptr<T>, std::shared_ptr<T>, T*>;
storage_type m_storage;
T* p_array;
};

template <class T>
T& unwrap_array(array_wrapper&);

template <class T>
const T& unwrap_array(const array_wrapper&);

/********************************
* array_wrapper implementation *
********************************/

inline auto array_wrapper::clone() const -> wrapper_ptr
{
return clone_impl();
}

inline enum data_type array_wrapper::data_type() const
{
return m_data_type;
}

inline array_wrapper::array_wrapper(enum data_type dt)
: m_data_type(dt)
{
}

/*************************************
* array_wrapper_impl implementation *
*************************************/

template <class T>
array_wrapper_impl<T>::array_wrapper_impl(T&& ar)
: array_wrapper(this->get_data_type())
, m_storage(value_ptr<T>(std::move(ar)))
, p_array(std::get<value_ptr<T>>(m_storage).get())
{
}

template <class T>
array_wrapper_impl<T>::array_wrapper_impl(T* ar)
: array_wrapper(this->get_data_type())
, m_storage(ar)
, p_array(ar)
{
}

template <class T>
array_wrapper_impl<T>::array_wrapper_impl(std::shared_ptr<T> ar)
: array_wrapper(this->get_data_type())
, m_storage(ar)
, p_array(ar.get())
{
}

template <class T>
T& array_wrapper_impl<T>::get_wrapped()
{
return *p_array;
}

template <class T>
const T& array_wrapper_impl<T>::get_wrapped() const
{
return *p_array;
}

template <class T>
constexpr enum data_type array_wrapper_impl<T>::get_data_type() const
{
return arrow_traits<typename T::inner_value_type>::type_id;
}

template <class T>
array_wrapper_impl<T>::array_wrapper_impl(const array_wrapper_impl& rhs)
: array_wrapper(rhs)
, m_storage(rhs.m_storage)
{
p_array = std::visit([](auto&& arg)
{
using U = std::decay_t<decltype(arg)>;
if constexpr (std::is_same_v<U, T*>)
return arg;
else
return arg.get();
}, m_storage);
}

template <class T>
auto array_wrapper_impl<T>::clone_impl() const -> wrapper_ptr
{
return wrapper_ptr{new array_wrapper_impl<T>(*this)};
}

template <class T>
T& unwrap_array(array_wrapper& ar)
{
return static_cast<array_wrapper_impl<T>&>(ar).get_wrapped();
}

template <class T>
const T& unwrap_array(const array_wrapper& ar)
{
return static_cast<const array_wrapper_impl<T>&>(ar).get_wrapped();
}
}

18 changes: 3 additions & 15 deletions include/sparrow/layout/dictionary_encoded_array.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "sparrow/arrow_array_schema_proxy.hpp"
#include "sparrow/layout/array_base.hpp"
#include "sparrow/layout/array_wrapper.hpp"
#include "sparrow/layout/dictionary_encoded_array/dictionary_encoded_array_bitmap_iterator.hpp"
#include "sparrow/layout/dictionary_encoded_array/dictionary_encoded_array_iterator.hpp"
#include "sparrow/layout/primitive_array.hpp"
Expand Down Expand Up @@ -80,8 +81,7 @@ namespace sparrow
};

template <std::integral IT, class SL, layout_offset OT>
class dictionary_encoded_array final : public array_base,
public array_crtp_base<dictionary_encoded_array<IT, SL, OT>>
class dictionary_encoded_array final : public array_crtp_base<dictionary_encoded_array<IT, SL, OT>>
{
public:

Expand Down Expand Up @@ -109,7 +109,6 @@ namespace sparrow
using const_bitmap_range = typename base_type::const_bitmap_range;

explicit dictionary_encoded_array(arrow_proxy);
~dictionary_encoded_array() override = default;

using base_type::size;

Expand All @@ -132,9 +131,6 @@ namespace sparrow
const_value_iterator value_cbegin() const;
const_value_iterator value_cend() const;

dictionary_encoded_array(const dictionary_encoded_array&) = default;
dictionary_encoded_array* clone_impl() const override;

keys_layout m_keys_layout;
values_layout m_values_layout;

Expand All @@ -156,8 +152,7 @@ namespace sparrow

template <std::integral IT, class SL, layout_offset OT>
dictionary_encoded_array<IT, SL, OT>::dictionary_encoded_array(arrow_proxy proxy)
: array_base(proxy.data_type())
, base_type(std::move(proxy))
: base_type(std::move(proxy))
, m_keys_layout(create_keys_layout(storage()))
, m_values_layout(create_values_layout(storage()))
{
Expand Down Expand Up @@ -227,13 +222,6 @@ namespace sparrow
return sparrow::next(value_cbegin(), size());
}

template <std::integral IT, class SL, layout_offset OT>
dictionary_encoded_array<IT, SL, OT>* dictionary_encoded_array<IT, SL, OT>::clone_impl() const
{
arrow_proxy copy = storage();
return new dictionary_encoded_array<IT, SL, OT>(std::move(copy));
}

template <std::integral T, class SL, layout_offset OT>
typename dictionary_encoded_array<T, SL, OT>::values_layout
dictionary_encoded_array<T, SL, OT>::create_values_layout(arrow_proxy& proxy)
Expand Down
Loading

0 comments on commit 2148ad2

Please sign in to comment.