26 #ifndef PDI_REF_ANY_H_    27 #define PDI_REF_ANY_H_    34 #include <unordered_map>    36 #include <pdi/array_datatype.h>    37 #include <pdi/pdi_fwd.h>    38 #include <pdi/datatype.h>    39 #include <pdi/error.h>    40 #include <pdi/record_datatype.h>    41 #include <pdi/scalar_datatype.h>    50 template<
bool R, 
bool W>
    59 struct Ref_access<R, true> {
    67 struct Ref_access<true, false> {
    69     typedef const void* type;
   117                  m_read_locks{readable ? 0 : 1},
   118                  m_write_locks{writable ? 0 : 1}
   132             assert(m_read_locks == 0 || m_read_locks == 1);
   133             assert(m_write_locks == 0 || m_write_locks == 1);
   134             assert(m_notifications.empty());
   166             m_type{std::move(type)},
   184             m_type{std::move(type)},
   191                     delete (cloned_type);
   193                 }, readable, writable};
   222         if ( !other.m_content ) 
return NULL;
   223         if ( !other.m_content->m_data ) 
return NULL;
   224         return other.m_content;
   248     const Datatype& type() 
const noexcept;
   252         return std::hash<Referenced_data*>()(get_content(*
this));
   271 template<
bool R, 
bool W>
   272 class PDI_EXPORT Ref_any:
   289         link(get_content(other));
   298     template<
bool OR, 
bool OW>
   302         link(get_content(other));
   311         if (!other.m_content) 
return;
   315         m_content = other.m_content;
   316         other.m_content = 
nullptr;
   330         if (type->datasize() && !data && (readable||writable)) {
   331             throw Type_error{
"Referencing null data with non-null size"};
   334             link(
new Referenced_data(data, freefunc, std::move(type), readable,  writable));
   347             std::pair<void*, Datatype_uptr> subref_info = other.
type().
subaccess(get_content(other)->m_data, accessor);
   349                     get_content(other)->m_buffer,
   351                     std::move(subref_info.second)));
   360     Ref_any(
Ref other, 
const std::vector<std::unique_ptr<Datatype::Accessor_base>>& accessors):
   364             std::pair<void*, Datatype_uptr> subref_info = other.
type().
subaccess(get_content(other)->m_data, accessors);
   366                     get_content(other)->m_buffer,
   368                     std::move(subref_info.second)));
   379     Ref_any& operator= (Ref_any&& other) noexcept
   382         if (&other ==  
this) 
return *
this;
   386         if (other.is_null()) 
return *
this;
   388         other.m_content->m_buffer->m_notifications.erase(&other);
   390         m_content = other.m_content;
   391         other.m_content = 
nullptr;
   395     Ref_any& operator= (
const Ref_any& other) 
const noexcept
   398         if (&other ==  
this) 
return *
this;
   402         link(get_content(other));
   409         return m_content == get_content(o);
   415         return m_content != get_content(o);
   421         return m_content < get_content(o);
   427         return m_content > get_content(o);
   433         return m_content <= get_content(o);
   439         return m_content >= get_content(o);
   447     Ref operator[] (
const std::string& member_name)
 const   450             throw Type_error{
"Cannot access member from empty Ref: `{}'", member_name};
   460     Ref operator[] (
const char* member_name)
 const   462         return this->operator[](std::string(member_name));
   470     Ref operator[] (std::size_t index)
 const   473             throw Type_error{
"Cannot access array index from empty Ref: `{}'", index};
   483     Ref operator[] (std::pair<std::size_t, std::size_t> slice)
 const   486             throw Type_error{
"Cannot access array slice from empty Ref: `{}'", index};
   495     operator typename Ref_access<R, W>::type()
 const   504     typename Ref_access<R, W>::type 
get() 
const   506         if (is_null()) 
throw Right_error{
"Trying to dereference a null reference"};
   507         return m_content->m_data;
   514     typename Ref_access<R, W>::type 
get(std::nothrow_t) 
const noexcept
   516         if (is_null()) 
return nullptr;
   517         return m_content->m_data;
   526         static_assert(R, 
"Cannot get scalar_value from Ref without read access");
   527         if (
const Scalar_datatype* scalar_type = dynamic_cast<const Scalar_datatype*>(&type())) {
   529                 switch (scalar_type->buffersize()) {
   531                     return *
static_cast<const uint8_t*
>(m_content->m_data);
   533                     return *
static_cast<const uint16_t*
>(m_content->m_data);
   535                     return *
static_cast<const uint32_t*
>(m_content->m_data);
   537                     return *
static_cast<const uint64_t*
>(m_content->m_data);
   539                     throw Type_error{
"Unknown size of unsigned integer datatype"};
   542                 switch (scalar_type->buffersize()) {
   544                     return *
static_cast<const int8_t*
>(m_content->m_data);
   546                     return *
static_cast<const int16_t*
>(m_content->m_data);
   548                     return *
static_cast<const int32_t*
>(m_content->m_data);
   550                     return *
static_cast<const int64_t*
>(m_content->m_data);
   552                     throw Type_error{
"Unknown size of integer datatype"};
   555                 switch (type().buffersize()) {
   557                     return *
static_cast<const float*
>(m_content->m_data);
   560                     return *
static_cast<const double*
>(m_content->m_data);
   563                     throw Type_error{
"Unknown size of float datatype"};
   566                 throw Type_error{
"Unknown datatype to get value"};
   569         throw Type_error{
"Expected scalar, found invalid type instead: {}", type().debug_string()};
   576     operator bool () const noexcept
   585         if (m_content) unlink();
   595         return do_copy(*
this);
   606         if (is_null()) 
return nullptr;
   609         while (!m_content->m_buffer->m_notifications.empty()) {
   611             const Reference_base* key = m_content->m_buffer->m_notifications.begin()->first;
   613             m_content->m_buffer->m_notifications.begin()->second(*
this);
   615             m_content->m_buffer->m_notifications.erase(key);
   618         void* result = m_content->m_data;
   619         m_content->m_data = 
nullptr;
   620         m_content->m_buffer->m_delete = []() {}; 
   633         if (!is_null()) m_content->m_buffer->m_notifications[
this] = notifier;
   644     bool PDI_NO_EXPORT is_null() 
const noexcept
   646         if (!m_content) 
return true;
   647         if (!m_content->m_data) {
   658     void PDI_NO_EXPORT unlink() 
const noexcept
   661         m_content->m_buffer->m_notifications.erase(
this);
   662         if (R || W) --m_content->m_buffer->m_write_locks;
   663         if (W) --m_content->m_buffer->m_read_locks;
   664         --m_content->m_owners;
   665         if (!m_content->m_owners) 
delete m_content;
   679         if (!content || !content->
m_data) 
return; 
   684         if (R || W) ++m_content->m_buffer->m_write_locks;
   685         if (W) ++m_content->m_buffer->m_read_locks;
   694 template<
bool R, 
bool W>
   695 struct hash<
PDI::Ref_any<R,W>> {
   704 #endif //  PDI_REF_ANY_H_ virtual Datatype_uptr clone_type() const =0
Creates a new datatype as an exact copy of this one. 
A descriptor for data on which references can point. 
Definition: ref_any.h:143
Accessor to get single element from array. 
Definition: array_datatype.h:61
T scalar_value()
Returns a scalar value of type T taken from the data buffer. 
Definition: ref_any.h:524
Definition: scalar_datatype.h:38
std::unordered_map< const Reference_base *, std::function< void(Ref)> > m_notifications
Nullification notifications registered on this instance. 
Definition: ref_any.h:106
A Datatype is a Datatype_template that accepts no argument. 
Definition: datatype.h:46
virtual void destroy_data(void *ptr) const =0
Function used to delete the data behind the datatype. 
Base class for datatype accesssors, that allow to get pointer to subtype. 
Definition: datatype.h:52
Ref_any(const Ref_any &other) noexcept
Copies an existing reference. 
Definition: ref_any.h:286
void * m_data
In-memory location of the data. 
Definition: ref_any.h:149
A dynamically typed reference to data with automatic memory management and read/write locking semanti...
Definition: pdi_fwd.h:85
~Referenced_buffer()
Definition: ref_any.h:128
static Referenced_data * get_content(const Reference_base &other) noexcept
Function to access the content from a reference with different access right. 
Definition: ref_any.h:220
Ref_any(Ref other, const Datatype::Accessor_base &accessor)
Creates a subreference from reference. 
Definition: ref_any.h:343
Accessor to get a slice of an array, returns array of the same subtype. 
Definition: array_datatype.h:84
size_t hash() const noexcept
Definition: ref_any.h:250
int m_owners
Number of references to this buffer. 
Definition: ref_any.h:94
std::unique_ptr< Datatype > Datatype_uptr
Definition: pdi_fwd.h:74
Datatype_uptr m_type
Type of the data. 
Definition: ref_any.h:152
Referenced_data(Referenced_buffer *buffer, void *data, Datatype_uptr type)
Constructs a new data descriptor from an already referenced buffer. 
Definition: ref_any.h:163
Reference_base() noexcept
Constructs a null reference. 
Definition: ref_any.h:233
std::function< void()> m_delete
The function to call to deallocate the buffer memory. 
Definition: ref_any.h:91
int m_read_locks
Number of locks preventing read access. 
Definition: ref_any.h:97
int m_owners
Number of references to this data. 
Definition: ref_any.h:155
void * release() noexcept
Releases ownership of the referenced raw data by nullifying all existing references. 
Definition: ref_any.h:604
A descriptor for a buffer in which references can point. 
Definition: ref_any.h:88
~Ref_any()
Destructor. 
Definition: ref_any.h:374
Referenced_data(void *data, std::function< void(void *)> freefunc, Datatype_uptr type, bool readable, bool writable)
Constructs a new data descriptor. 
Definition: ref_any.h:182
Referenced_buffer * m_buffer
The buffer in which the data lives. 
Definition: ref_any.h:146
void reset() noexcept
Nullify the reference. 
Definition: ref_any.h:583
Ref_any(void *data, std::function< void(void *)> freefunc, Datatype_uptr type, bool readable, bool writable)
Creates a reference to currently unreferenced data. 
Definition: ref_any.h:327
int m_write_locks
Number of locks preventing write access. 
Definition: ref_any.h:103
Definition: array_datatype.h:37
void on_nullify(std::function< void(Ref)> notifier) const noexcept
Registers a nullification callback. 
Definition: ref_any.h:631
Ref_any(const Ref_any< OR, OW > &other) noexcept
Copies an existing reference with different privileges. 
Definition: ref_any.h:299
Ref_any(Ref other, const std::vector< std::unique_ptr< Datatype::Accessor_base >> &accessors)
Creates a subreference from reference. 
Definition: ref_any.h:360
Ref_any(Ref_any &&other) noexcept
Moves an existing reference. 
Definition: ref_any.h:308
Referenced_data * m_content
Pointer on the data content, can be null if the ref is null. 
Definition: ref_any.h:215
std::pair< void *, Datatype_uptr > subaccess(void *from, const Accessor_base &accessor) const
Creates datatype of subtype and returns it with a moved pointer. 
Member accessor for record datatype. 
Definition: record_datatype.h:48
A common base for all references, whatever their access privileges. 
Definition: ref_any.h:80
const Datatype & type() const noexcept
accesses the type of the referenced raw data 
Ref copy() const
Makes a copy of the raw content behind this reference and returns a new reference. 
Definition: ref_any.h:593
Referenced_buffer(std::function< void()> deleter, bool readable, bool writable) noexcept
Constructs a new buffer descriptor. 
Definition: ref_any.h:114
~Referenced_data()
Definition: ref_any.h:203