1 /*========================== begin_copyright_notice ============================
2
3 Copyright (C) 2017-2021 Intel Corporation
4
5 SPDX-License-Identifier: MIT
6
7 ============================= end_copyright_notice ===========================*/
8
9 #pragma once
10
11 #include <type_traits>
12
13 #include "cif/common/id.h"
14 #include "cif/common/cif.h"
15 #include "cif/common/cif_main.h"
16
17 #include "cif/macros/enable.h"
18
19 namespace CIF {
20
21 namespace Builtins {
22 /// Custom allocator function
23 using AllocatorT = void *(CIF_CALLING_CONV *)(size_t size);
24
25 /// Custom allocator function
26 using ReallocatorT = void *(CIF_CALLING_CONV *)(void *oldMemory, size_t oldSize, size_t newSize);
27
28 /// Custom deallocator function
29 using DeallocatorT = void (CIF_CALLING_CONV *)(void *memory);
30
31 /// Builtin interface that can be used as generic buffer
32 CIF_DECLARE_COMMON_INTERFACE(Buffer, "CIF_BUFFER");
33
34 /// v #1
35 CIF_DEFINE_INTERFACE_VER(Buffer, 1){
36 CIF_INHERIT_CONSTRUCTOR();
37
38 /// Get address to underlying buffer with ElementT as pointer element type
39 template<typename ElementT>
GetMemoryWriteable()40 ElementT *GetMemoryWriteable(){
41 return reinterpret_cast<ElementT*>(GetMemoryRawWriteable());
42 }
43
44 /// Get address to underlying const buffer with ElementT as pointer element type
45 template<typename ElementT>
GetMemory()46 const ElementT *GetMemory() const{
47 return reinterpret_cast<const ElementT*>(GetMemoryRaw());
48 }
49
50 /// Get size in units of ElementT (ElementT == void version)
51 template<typename ElementT>
GetSize()52 const typename std::enable_if<std::is_void<ElementT>::value, size_t>::type GetSize() const{
53 return GetSizeRaw();
54 }
55
56 /// Get size in units of ElementT (ElementT != void version)
57 template<typename ElementT>
GetSize()58 const typename std::enable_if<false == std::is_void<ElementT>::value, size_t>::type GetSize() const{
59 return GetSizeRaw() / sizeof(ElementT);
60 }
61
62 /// Copies given element to the end of the buffer
63 /// Note : If (packed == false), then this function will automatically align current underlying buffer
64 /// pointer to alignof(ElementT)
65 template<typename ElementT>
66 bool PushBackRawCopy(const ElementT &newEl, bool packed = true){
67 static_assert(std::is_pod<ElementT>::value, "Supporting only POD types");
68 if(packed == false){
69 size_t alignment = alignof(ElementT);
70 bool success = AlignUp(static_cast<uint32_t>(alignment));
71 if(success == false){
72 return false;
73 }
74 }
75
76 return PushBackRawBytes(&newEl, sizeof(ElementT));
77 }
78
79 /// Sets custom allocator and deallocator functions to be used by this buffer interface
80 /// Note : will reallocate using new allocators only when additional space will be needed
81 /// Note : reallocator is optional and can be nullptr
82 virtual void SetAllocator(AllocatorT allocator, DeallocatorT deallocator, ReallocatorT reallocator);
83
84 /// Sets underlying buffer storage and its deallocator
85 /// Note : will destroy current underlying buffer (if any)
86 /// Note : if size of given memory becomes too small, will fallback to allocating new memory
87 virtual void SetUnderlyingStorage(void *memory, size_t size, DeallocatorT deallocator);
88
89 /// Sets underlying constant buffer storage and its deallocator
90 /// Note : will destroy current underlying buffer (if any)
91 /// Note : will allocate new memory if this const memory will be accessed in non-const manners
92 /// Note : since given pointer is treated as const, memory pointed ty by it will never be freed
93 /// by this buffer instance
94 virtual void SetUnderlyingStorage(const void *memory, size_t size);
95
96 /// Detaches and returns current allocation leaving this buffer's underlying buffer empty
97 virtual void *DetachAllocation();
98
99 /// Returns const raw access to underlying buffer
100 virtual const void *GetMemoryRaw() const;
101
102 /// Returns writeable access to underlyng buffer
103 /// Note : for constant buffer this will cause reallocation (copy!) to writeable memory
104 virtual void *GetMemoryRawWriteable();
105
106 /// Returns size in bytes of underlying buffer
107 virtual size_t GetSizeRaw() const;
108
109 /// Returns capacity in bytes of underlying buffer
110 virtual size_t GetCapacityRaw() const;
111
112 /// Resizes (may reallocate) underlying buffer's size
113 virtual bool Resize(size_t newSize);
114
115 /// Resizes (may reallocate) the underlying buffer's capacity
116 virtual bool Reserve(size_t newCapacity);
117
118 /// Sets the size to 0
119 virtual void Clear();
120
121 /// Sets the size to 0 and deallocates underlying buffer
122 virtual void Deallocate();
123
124 /// Aligns up current size to meet required alignment
125 virtual bool AlignUp(uint32_t alignment);
126
127 /// Pushes new raw element to buffer
128 virtual bool PushBackRawBytes(const void *newData, size_t size);
129
130 /// Can be true if SetUnderlyingStorage(const void *, size_t) was used, please refer to SetUnderlyingStorage
131 virtual bool IsConst() const;
132 };
133
134 CIF_GENERATE_VERSIONS_LIST(Buffer);
135 CIF_MARK_LATEST_VERSION(BufferLatest, Buffer);
136 using BufferSimple = Buffer<1>; /// tag the most common version
137
138 template<typename BufferInterface = BufferLatest>
CreateConstBuffer(CIF::CIFMain * provider,const void * data,size_t size)139 CIF::RAII::UPtr_t<BufferInterface> CreateConstBuffer(CIF::CIFMain *provider, const void *data, size_t size){
140 if(provider == nullptr){
141 return CIF::RAII::UPtr<BufferInterface>(nullptr);
142 }
143 auto buff = provider->CreateBuiltin<BufferInterface>();
144 if(buff == nullptr){
145 return CIF::RAII::UPtr<BufferInterface>(nullptr);
146 }
147 if((data != nullptr) && (size != 0)){
148 buff->SetUnderlyingStorage(data, size);
149 }
150 return buff;
151 }
152
153 template<typename BufferInterface = BufferLatest>
CreateWriteableBuffer(CIF::CIFMain * provider,const void * initialData,size_t initialSize)154 CIF::RAII::UPtr_t<BufferInterface> CreateWriteableBuffer(CIF::CIFMain *provider, const void *initialData, size_t initialSize){
155 auto *buff = CreateConstBuffer<BufferInterface>(provider, initialData, initialSize);
156 if(buff == nullptr){
157 return CIF::RAII::UPtr<BufferInterface>(nullptr);
158 }
159 auto writeableMem = buff->GetMemoryRawWriteable();
160 if(writeableMem == nullptr){
161 // failed to allocate new memory in writeable memory
162 return CIF::RAII::UPtr<BufferInterface>(nullptr);
163 }
164 return buff;
165 }
166
167 template<typename BufferInterface = BufferLatest>
CreateBufferFromPtr(CIF::CIFMain * provider,void * ptr,size_t size,DeallocatorT ptrDeallocator)168 CIF::RAII::UPtr_t<BufferInterface> CreateBufferFromPtr(CIF::CIFMain *provider, void *ptr, size_t size, DeallocatorT ptrDeallocator){
169 auto *buff = CreateConstBuffer<BufferInterface>(provider, nullptr, 0);
170 if(buff == nullptr){
171 return CIF::RAII::UPtr<BufferInterface>(nullptr);
172 }
173
174 buff->SetUnderlyingStorage(ptr, size, ptrDeallocator);
175
176 return buff;
177 }
178
179 }
180
181 }
182
183 #include "cif/macros/disable.h"
184