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)},
188 std::shared_ptr<Datatype> cloned_type = m_type->clone_type();
190 cloned_type->destroy_data(data);
192 }, readable, writable};
221 if ( !other.m_content )
return NULL;
222 if ( !other.m_content->m_data )
return NULL;
223 return other.m_content;
247 const Datatype& type()
const noexcept;
251 return std::hash<Referenced_data*>()(get_content(*
this));
270 template<
bool R,
bool W>
271 class PDI_EXPORT Ref_any:
288 link(get_content(other));
297 template<
bool OR,
bool OW>
301 link(get_content(other));
310 if (!other.m_content)
return;
314 m_content = other.m_content;
315 other.m_content =
nullptr;
329 if (type->datasize() && !data && (readable||writable)) {
330 throw Type_error{
"Referencing null data with non-null size"};
333 link(
new Referenced_data(data, freefunc, std::move(type), readable, writable));
346 std::pair<void*, Datatype_uptr> subref_info = other.
type().
subaccess(get_content(other)->m_data, accessor);
348 get_content(other)->m_buffer,
350 std::move(subref_info.second)));
359 Ref_any(
Ref other,
const std::vector<std::unique_ptr<Datatype::Accessor_base>>& accessors):
363 std::pair<void*, Datatype_uptr> subref_info = other.
type().
subaccess(get_content(other)->m_data, accessors);
365 get_content(other)->m_buffer,
367 std::move(subref_info.second)));
378 Ref_any& operator= (Ref_any&& other) noexcept
381 if (&other ==
this)
return *
this;
385 if (other.is_null())
return *
this;
387 other.m_content->m_buffer->m_notifications.erase(&other);
389 m_content = other.m_content;
390 other.m_content =
nullptr;
394 Ref_any& operator= (
const Ref_any& other)
const noexcept
397 if (&other ==
this)
return *
this;
401 link(get_content(other));
408 return m_content == get_content(o);
414 return m_content != get_content(o);
420 return m_content < get_content(o);
426 return m_content > get_content(o);
432 return m_content <= get_content(o);
438 return m_content >= get_content(o);
446 Ref operator[] (
const std::string& member_name)
const 449 throw Type_error{
"Cannot access member from empty Ref: `{}'", member_name};
459 Ref operator[] (
const char* member_name)
const 461 return this->operator[](std::string(member_name));
469 Ref operator[] (std::size_t index)
const 472 throw Type_error{
"Cannot access array index from empty Ref: `{}'", index};
482 Ref operator[] (std::pair<std::size_t, std::size_t> slice)
const 485 throw Type_error{
"Cannot access array slice from empty Ref: `{}'", index};
494 operator typename Ref_access<R, W>::type()
const 503 typename Ref_access<R, W>::type
get()
const 505 if (is_null())
throw Right_error{
"Trying to dereference a null reference"};
506 return m_content->m_data;
513 typename Ref_access<R, W>::type
get(std::nothrow_t)
const noexcept
515 if (is_null())
return nullptr;
516 return m_content->m_data;
525 static_assert(R,
"Cannot get scalar_value from Ref without read access");
526 if (
const Scalar_datatype* scalar_type = dynamic_cast<const Scalar_datatype*>(&type())) {
528 switch (scalar_type->buffersize()) {
530 return *
static_cast<const uint8_t*
>(m_content->m_data);
532 return *
static_cast<const uint16_t*
>(m_content->m_data);
534 return *
static_cast<const uint32_t*
>(m_content->m_data);
536 return *
static_cast<const uint64_t*
>(m_content->m_data);
538 throw Type_error{
"Unknown size of unsigned integer datatype"};
541 switch (scalar_type->buffersize()) {
543 return *
static_cast<const int8_t*
>(m_content->m_data);
545 return *
static_cast<const int16_t*
>(m_content->m_data);
547 return *
static_cast<const int32_t*
>(m_content->m_data);
549 return *
static_cast<const int64_t*
>(m_content->m_data);
551 throw Type_error{
"Unknown size of integer datatype"};
554 switch (type().buffersize()) {
556 return *
static_cast<const float*
>(m_content->m_data);
559 return *
static_cast<const double*
>(m_content->m_data);
562 throw Type_error{
"Unknown size of float datatype"};
565 throw Type_error{
"Unknown datatype to get value"};
568 throw Type_error{
"Expected scalar, found invalid type instead: {}", type().debug_string()};
575 operator bool () const noexcept
584 if (m_content) unlink();
594 return do_copy(*
this);
605 if (is_null())
return nullptr;
608 while (!m_content->m_buffer->m_notifications.empty()) {
610 const Reference_base* key = m_content->m_buffer->m_notifications.begin()->first;
612 m_content->m_buffer->m_notifications.begin()->second(*
this);
614 m_content->m_buffer->m_notifications.erase(key);
617 void* result = m_content->m_data;
618 m_content->m_data =
nullptr;
619 m_content->m_buffer->m_delete = []() {};
632 if (!is_null()) m_content->m_buffer->m_notifications[
this] = notifier;
643 bool PDI_NO_EXPORT is_null()
const noexcept
645 if (!m_content)
return true;
646 if (!m_content->m_data) {
657 void PDI_NO_EXPORT unlink()
const noexcept
660 m_content->m_buffer->m_notifications.erase(
this);
661 if (R || W) --m_content->m_buffer->m_write_locks;
662 if (W) --m_content->m_buffer->m_read_locks;
663 --m_content->m_owners;
664 if (!m_content->m_owners)
delete m_content;
678 if (!content || !content->
m_data)
return;
683 if (R || W) ++m_content->m_buffer->m_write_locks;
684 if (W) ++m_content->m_buffer->m_read_locks;
693 template<
bool R,
bool W>
694 struct hash<
PDI::Ref_any<R,W>> {
703 #endif // PDI_REF_ANY_H_
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:523
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
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:285
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:219
Ref_any(Ref other, const Datatype::Accessor_base &accessor)
Creates a subreference from reference.
Definition: ref_any.h:342
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:249
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:232
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:603
A descriptor for a buffer in which references can point.
Definition: ref_any.h:88
~Ref_any()
Destructor.
Definition: ref_any.h:373
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:582
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:326
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:630
Ref_any(const Ref_any< OR, OW > &other) noexcept
Copies an existing reference with different privileges.
Definition: ref_any.h:298
Ref_any(Ref other, const std::vector< std::unique_ptr< Datatype::Accessor_base >> &accessors)
Creates a subreference from reference.
Definition: ref_any.h:359
Ref_any(Ref_any &&other) noexcept
Moves an existing reference.
Definition: ref_any.h:307
Referenced_data * m_content
Pointer on the data content, can be null if the ref is null.
Definition: ref_any.h:214
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:592
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:202