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