d2628ad5cd41509409b64083198f4867747dee98
[platform/upstream/dldt.git] / inference-engine / include / ie_blob.h
1 // Copyright (C) 2018-2019 Intel Corporation
2 // SPDX-License-Identifier: Apache-2.0
3 //
4
5 /**
6  * @brief A header file for Blob and generic TBlob<>
7  * @file ie_blob.h
8  */
9 #pragma once
10
11 #include <memory>
12 #include <vector>
13 #include <string>
14 #include <numeric>
15 #include <cstring>
16 #include <utility>
17 #include <functional>
18 #include <map>
19 #include <type_traits>
20
21 #include "ie_common.h"
22 #include "details/ie_exception.hpp"
23 #include "details/ie_blob_iterator.hpp"
24 #include "ie_allocator.hpp"
25 #include "ie_locked_memory.hpp"
26 #include "ie_precision.hpp"
27 #include "ie_layouts.h"
28 #include "details/ie_pre_allocator.hpp"
29
30 namespace InferenceEngine {
31 /**
32  * @brief This class represents a universal container in the Inference Engine
33  * @note Each Blob implementation must be derived from this Blob class directly or indirectly
34  */
35 class Blob {
36 public:
37     /**
38      * @brief A smart pointer containing Blob object
39      */
40     using Ptr = std::shared_ptr<Blob>;
41
42     /**
43      * @brief A smart pointer to the const Blob object
44      */
45     using CPtr = std::shared_ptr<const Blob>;
46
47     /**
48      * @deprecated Use Blob::getTensorDesc and InferenceEngine::TensorDesc::getPrecision to get the precision
49      * @brief Returns the tensor precision of the current Blob object
50      */
51     INFERENCE_ENGINE_DEPRECATED
52     Precision type() const noexcept {
53         return tensorDesc.getPrecision();
54     }
55
56     /**
57      * @deprecated Use Blob::getTensorDesc and InferenceEngine::TensorDesc::getPrecision to get the precision
58      * @brief Returns the tensor precision of the current Blob object
59      */
60     INFERENCE_ENGINE_DEPRECATED
61     Precision precision() const noexcept {
62         return tensorDesc.getPrecision();
63     }
64
65     /**
66      * @deprecated Use Blob::getTensorDesc and InferenceEngine::TensorDesc::getLayout to get the current layout
67      * @brief Returns the tensor layout of the current Blob object
68      */
69     INFERENCE_ENGINE_DEPRECATED
70     Layout layout() const noexcept {
71         return tensorDesc.getLayout();
72     }
73
74     /**
75      * @brief Creates a TBlob<> object from a Data node
76      * @param Data reference to a smart pointer of the Data node
77      * @return Smart pointer to TBlob<> with the relevant C type to the precision of the data node
78      */
79     static Ptr CreateFromData(const DataPtr &data);
80
81     /**
82      * @brief Blob virtual destructor
83      */
84     virtual ~Blob()  = default;
85
86     /**
87      * @brief Checks if the Blob object can be cast to the type T*
88      * @tparam T Type to be checked. Must represent a class derived from the Blob
89      * @return true if this object can be dynamically cast to the type T*. Otherwise, false
90      */
91     template<typename T,
92              typename std::enable_if<
93                 !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
94              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
95     bool is() noexcept {
96         return dynamic_cast<T*>(this) != nullptr;
97     }
98
99     /**
100      * @brief Checks if the Blob object can be cast to the type const T*
101      * @tparam T Type to be checked. Must represent a class derived from the Blob
102      * @return true if this object can be dynamically cast to the type const T*. Otherwise, false
103      */
104     template<typename T,
105              typename std::enable_if<
106                 !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
107              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
108     bool is() const noexcept {
109         return dynamic_cast<const T*>(this) != nullptr;
110     }
111
112     /**
113      * @brief Casts this Blob object to the type T*. Use InferenceEngine::as() to operate with
114      * shared Blob objects instead of raw pointers
115      * @tparam T Type to cast to. Must represent a class derived from the Blob
116      * @return Raw pointer to the object of the type T or nullptr on error
117      */
118     template<typename T,
119              typename std::enable_if<
120                 !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
121              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
122     T* as() noexcept {
123         return dynamic_cast<T*>(this);
124     }
125
126     /**
127      * @brief Casts this Blob object to the type const T*. Use InferenceEngine::as() to operate with
128      * shared Blob objects instead of raw pointers
129      * @tparam T Type to cast to. Must represent a class derived from the Blob
130      * @return Raw pointer to the object of the type const T or nullptr on error
131      */
132     template<typename T,
133              typename std::enable_if<
134                 !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
135              typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
136     const T* as() const noexcept {
137         return dynamic_cast<const T*>(this);
138     }
139
140     /**
141      * @brief Constructor. Creates an empty Blob object with the specified precision.
142      * @param tensorDesc Defines the layout and dims of the blob
143      */
144     explicit Blob(const TensorDesc &tensorDesc): tensorDesc(tensorDesc) {}
145
146     /**
147      * @deprecated Use Blob::Blob(const TensorDesc &).
148      * @brief Constructor. Creates an empty Blob object with the specified precision.
149      * @param p Precision type
150      */
151     INFERENCE_ENGINE_DEPRECATED
152     explicit Blob(Precision p) : Blob(TensorDesc(p, NCHW)) {}
153
154     /**
155      * @deprecated Use Blob::Blob(const TensorDesc &).
156      * @brief The constructor creates an empty Blob object with the specified precision and layout.
157      * @param p Precision type
158      * @param l Layout
159      */
160     INFERENCE_ENGINE_DEPRECATED
161     Blob(Precision p, Layout l) : Blob(TensorDesc(p, l)) {}
162
163     /**
164      * @deprecated Use Blob::Blob(const TensorDesc &).
165      * @brief The constructor creates an empty Blob object with the specified precision and dimensions.
166      * @param p Tensor precision type
167      * @param dims Tensor dimensions vector
168      */
169     INFERENCE_ENGINE_DEPRECATED
170     Blob(Precision p, const SizeVector &dims)
171             : Blob({ p, SizeVector(dims.rbegin(), dims.rend()), TensorDesc::getLayoutByDims(dims) }) {}
172
173     /**
174      * @deprecated Use Blob::Blob(const TensorDesc &).
175      * @brief The constructor creates an empty Blob object with the specified precision, layout and dimensions.
176      * @param p tensor precision type
177      * @param l tensor layout
178      * @param dims Tensor dimensions vector with reversed order
179      */
180     INFERENCE_ENGINE_DEPRECATED
181     Blob(Precision p, Layout l, const SizeVector &dims)
182             : Blob(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l)) {}
183
184     /**
185      * @deprecated The method works with reversed dimensions. Create a new blob if you want to change a size.
186      * @brief Changes Tensor size to the specified dimensions. If it was allocated, the previous data is deallocated and lost.
187      * @param dims New dimensions to set
188      * @param layout New layout to set
189      * @return Total number of elements (a product of all the dimensions)
190      */
191     INFERENCE_ENGINE_DEPRECATED
192     size_t Resize(const SizeVector &dims, Layout layout = Layout::ANY) noexcept {
193         try {
194             bool bret = deallocate();
195
196             if (layout != Layout::ANY) {
197                 tensorDesc = TensorDesc(tensorDesc.getPrecision(), SizeVector(dims.rbegin(), dims.rend()), layout);
198             } else {
199                 tensorDesc.setDims(SizeVector(dims.rbegin(), dims.rend()));
200             }
201             if (!bret) {
202                 allocate();
203             }
204             return product(tensorDesc.getDims());
205         } catch (...) {
206             return 0;
207         }
208     }
209
210     /**
211      * @deprecated The method works with reversed dimensions. Use Blob::getTensorDesc and InferenceEngine::TensorDesc::reshape.
212      * @brief Changes tensor size to the specified dimensions without changing memory. The total size remains unchanged as well as the memory layout.
213      * @param dims New dimensions to set
214      * @param layout New layout to set
215      * @return The total number of elements (a product of all the dims)
216      */
217     INFERENCE_ENGINE_DEPRECATED
218     size_t Reshape(const SizeVector &dims, Layout layout = Layout::ANY) noexcept {
219         try {
220             if (product(tensorDesc.getDims()) != product(dims)) {
221                 return 0;
222             }
223
224             if (layout != Layout::ANY) {
225                 tensorDesc = TensorDesc(tensorDesc.getPrecision(), SizeVector(dims.rbegin(), dims.rend()), layout);
226             } else {
227                 tensorDesc.setDims(SizeVector(dims.rbegin(), dims.rend()));
228             }
229             return product(tensorDesc.getDims());
230         } catch (...) {
231             return 0;
232         }
233     }
234
235     /**
236      * @deprecated Use Blob::getTensorDesc and InferenceEngine::TensorDesc::getDims.
237      * @brief Returns the tensor dimensions vector with reversed order.
238      */
239     INFERENCE_ENGINE_DEPRECATED
240     const SizeVector dims() const noexcept {
241         return SizeVector(tensorDesc.getDims().rbegin(), tensorDesc.getDims().rend());
242     }
243
244     /**
245      * @brief Returns the tensor description
246      */
247     virtual const TensorDesc &getTensorDesc() const noexcept {
248         return tensorDesc;
249     }
250
251     /**
252      * @brief Returns the tensor description
253      */
254     virtual TensorDesc &getTensorDesc() noexcept {
255         return tensorDesc;
256     }
257
258     /**
259      * @brief By default, returns the total number of elements (a product of all the dims or 1 for scalar)
260      *
261      * Return value and its interpretation heavily depend on the blob type
262      */
263     virtual size_t size() const noexcept {
264         if (tensorDesc.getLayout() == Layout::SCALAR)
265             return 1;
266         return product(tensorDesc.getDims());
267     }
268
269     /**
270      * @brief Returns the size of the current Blob in bytes.
271      */
272     virtual size_t byteSize() const noexcept {
273         return size() * element_size();
274     }
275
276     /**
277      * @brief Returns the number of bytes per element. The overall Blob capacity is size() * element_size().
278      * Abstract method.
279      */
280     virtual size_t element_size() const noexcept = 0;
281
282     /**
283      * @brief Allocates memory to store the data.
284      * Abstract method.
285      */
286     virtual void allocate() noexcept = 0;
287
288     /**
289      * @brief Releases previously allocated data.
290      * Abstract method.
291      */
292     virtual bool deallocate() noexcept = 0;
293
294     /**
295      * @brief Gets access to the allocated memory.
296      * Abstract method.
297      * @return A LockedMemory object
298      */
299     virtual LockedMemory<void> buffer() noexcept = 0;
300
301     /**
302      * @brief Gets read-only access to the allocated memory.
303      * Abstract method.
304      * @return A LockedMemory object
305      */
306     virtual LockedMemory<const void> cbuffer() const noexcept = 0;
307
308 protected:
309     /**
310      * @brief The tensor descriptor of the given blob.
311      */
312     TensorDesc tensorDesc;
313
314     /**
315      * @brief Multiplies the dimension vector's values.
316      * @param dims Reference to a vector with dimension values of type size_t
317      * @return Result of multiplication
318      */
319     static size_t product(const SizeVector &dims) noexcept {
320         if (dims.empty())
321             return 0;
322         return std::accumulate(std::begin(dims), std::end(dims), (size_t) 1, std::multiplies<size_t>());
323     }
324
325     /**
326      * @brief Gets an allocator for allocator-based blobs
327      * @return The allocator for allocator-based blobs or nullptr if there is none
328      */
329     virtual const std::shared_ptr<IAllocator> &getAllocator() const noexcept  = 0;
330
331     /**
332      * @brief Gets a handle to allocated memory
333      * @return The handle to allocated memory for allocator-based blobs or nullptr if there is none
334      */
335     virtual void *getHandle() const noexcept  = 0;
336
337     template<typename> friend
338     class TBlobProxy;
339 };
340
341 /**
342  * @brief Helper cast function to work with shared Blob objects
343  * @return shared_ptr to the type T. Returned shared_ptr shares ownership of the object with the
344  *         input Blob::Ptr
345  */
346 template<typename T,
347          typename std::enable_if<
348             !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
349          typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
350 std::shared_ptr<T> as(const Blob::Ptr& blob) noexcept {
351     return std::dynamic_pointer_cast<T>(blob);
352 }
353
354 /**
355  * @brief Helper cast function to work with shared Blob objects
356  * @return shared_ptr to the type const T. Returned shared_ptr shares ownership of the object with
357  *         the input Blob::Ptr
358  */
359 template<typename T,
360          typename std::enable_if<
361             !std::is_pointer<T>::value && !std::is_reference<T>::value, int>::type = 0,
362          typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
363 std::shared_ptr<const T> as(const Blob::CPtr& blob) noexcept {
364     return std::dynamic_pointer_cast<const T>(blob);
365 }
366
367 /**
368  * @brief This class implements a container object that represents a tensor in memory (host and
369  * remote/accelerated)
370  * @note Any Blob implementation that represents a concept of a tensor in memory (for example,
371  * TBlob) must be a subclass of MemoryBlob instead of Blob
372  */
373 class MemoryBlob : public Blob {
374 public:
375     /**
376      * @brief A smart pointer to the MemoryBlob object
377      */
378     using Ptr = std::shared_ptr<MemoryBlob>;
379
380     /**
381      * @brief A smart pointer to the const MemoryBlob object
382      */
383     using CPtr = std::shared_ptr<const MemoryBlob>;
384
385     /**
386      * @brief MemoryBlob virtual destructor
387      */
388     virtual ~MemoryBlob()  = default;
389
390     /**
391      * @brief Constructor. Creates an empty MemoryBlob object with the specified precision.
392      * @param tensorDesc Defines the layout and dims of the blob
393      */
394     explicit MemoryBlob(const TensorDesc& tensorDesc): Blob(tensorDesc) {}
395
396     /**
397      * @brief Returns the tensor description
398      */
399     const TensorDesc &getTensorDesc() const noexcept override {
400         return tensorDesc;
401     }
402
403     /**
404      * @brief Returns the tensor description
405      */
406     TensorDesc &getTensorDesc() noexcept override {
407         return tensorDesc;
408     }
409
410     /**
411      * @brief Returns the total number of elements, which is a product of all the dimensions
412      */
413     size_t size() const noexcept override {
414         if (tensorDesc.getLayout() == Layout::SCALAR)
415             return 1;
416         return product(tensorDesc.getDims());
417     }
418
419     /**
420      * @brief Returns the size of the current Blob in bytes
421      */
422     size_t byteSize() const noexcept override {
423         return size() * element_size();
424     }
425
426     /**
427      * @brief Returns the number of bytes per element. The overall MemoryBlob capacity is size() * element_size().
428      * Abstract method.
429      */
430     size_t element_size() const noexcept override = 0;
431
432     /**
433      * @brief Allocates memory to store the data.
434      * Abstract method.
435      */
436     void allocate() noexcept override = 0;
437
438     /**
439      * @brief Releases previously allocated data.
440      * Abstract method.
441      */
442     bool deallocate() noexcept override = 0;
443
444     /**
445      * @brief Gets access to the allocated memory.
446      * Abstract method.
447      * @return A LockedMemory object
448      */
449     LockedMemory<void> buffer() noexcept override = 0;
450
451     /**
452      * @brief Gets read-only access to the allocated memory.
453      * Abstract method.
454      * @return A LockedMemory object
455      */
456     LockedMemory<const void> cbuffer() const noexcept override = 0;
457
458 protected:
459     /**
460     * @brief Gets the allocator for allocator-based blobs.
461     * @return The allocator for allocator-based blobs or if there is none then a nullptr.
462     */
463     const std::shared_ptr<IAllocator> &getAllocator() const noexcept override  = 0;
464
465     /**
466     * @brief Gets the handle to allocated memory.
467     * @return The handle to allocated memory for allocator-based blobs or if there is none then a nullptr.
468     */
469     void *getHandle() const noexcept override = 0;
470
471     template<typename> friend
472     class TBlobProxy;
473 };
474
475 /**
476  * @brief This is a convenient type for working with a map containing pairs(string, pointer to a Blob instance).
477  */
478 using BlobMap = std::map<std::string, Blob::Ptr>;
479
480 /**
481  * @brief Represents real host memory allocated for a Tensor/Blob per C type.
482  */
483 template<typename T,
484         typename = std::enable_if<std::is_pod<T>::value>>
485 class TBlob : public MemoryBlob {
486     template<typename, typename> friend
487     class TBlob;
488
489
490 public:
491     /**
492      * @brief Smart Pointer to this TBlob object.
493      */
494     using  Ptr = std::shared_ptr<TBlob<T>>;
495
496     /**
497      * @brief Creates a TBlob object with the specified dimensions and layout but does not allocate the memory.
498      * Use the allocate() method to allocate memory.
499      * @param tensorDesc Tensor description
500      */
501     explicit TBlob(const TensorDesc& tensorDesc): MemoryBlob(tensorDesc) {}
502
503     /**
504      * @brief The constructor creates a TBlob object with the specified dimensions and layout
505      * on the pre-allocated memory. The allocate() call is not required.
506      * @param tensorDesc Tensor description
507      * @param ptr Pointer to the pre-allocated memory
508      * @param data_size Length of the pre-allocated array. If not set, size is assumed equal
509      * to the dot product of dims.
510      */
511     TBlob(const TensorDesc& tensorDesc, T* ptr, size_t data_size = 0): MemoryBlob(tensorDesc) {
512         if (data_size == 0) {
513             data_size = size();
514         }
515
516         if (data_size != 0 && ptr == nullptr) {
517             THROW_IE_EXCEPTION << "Using Blob on external nullptr memory";
518         }
519
520         _allocator = details::make_pre_allocator(ptr, data_size);
521         // blob on attached memory is always allocated, so we are not forcing the user to call allocate()
522         allocate();
523     }
524
525     /**
526      * @brief Creates a TBlob object with the specified dimensions, layout and custom memory allocator but does not allocate the memory.
527      * @param p Precision
528      * @param l Layout
529      * @param dims Tensor dimensions
530      * @param alloc Allocator to be used
531      */
532     TBlob(const TensorDesc& tensorDesc, const std::shared_ptr<IAllocator>& alloc)
533             : MemoryBlob(tensorDesc), _allocator(alloc) {
534     }
535
536     /**
537      * @deprecated Use TBlob::TBlob(const TensorDesc&).
538      * @brief Creates a TBlob object with the specified precision and type, but does not allocate the memory.
539      * Use the allocate() method to allocate memory.
540      * @param p Precision
541      * @param l Layout
542      */
543     INFERENCE_ENGINE_DEPRECATED
544     explicit TBlob(Precision p, Layout l) : MemoryBlob(TensorDesc(p, l)) {}
545
546     /**
547      * @deprecated Use TBlob::TBlob(const TensorDesc&).
548      * @brief Creates a TBlob object with the specified dimensions but does not allocate the memory. Use the allocate() method to allocate memory.
549      * @param p Precision
550      * @param l Layout
551      * @param dims Tensor dimensions
552      */
553     INFERENCE_ENGINE_DEPRECATED
554     TBlob(Precision p, Layout l, const SizeVector& dims)
555        : MemoryBlob(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l)) {
556     }
557
558     /**
559      * @deprecated Use TBlob::TBlob(const TensorDesc&).
560      * @brief The constructor creates a TBlob object with the specified dimensions on the pre-allocated memory. Therefore, the allocate() call is not required.
561      * @details The TBlob object doesn't own memory that is pointed to by the ptr. Therefore, it doesn't free the memory after the TBlob object is destroyed.
562      * Also certain operations might fail:
563      *  After the blob is constructed with this pointer its size is stored in the TBlob instance.
564      *  If the resize() operation happens which requires more memory, then the call to allocate() fails.
565      * @param p Precision
566      * @param dims Tensor dimensions
567      * @param ptr Pointer to the pre-allocated memory
568      * @param data_size Length of the pre-allocated array. If not set, size is assumed equal to dot product of dims.
569      */
570     INFERENCE_ENGINE_DEPRECATED
571     TBlob(Precision p, Layout l, const SizeVector& dims, T* ptr, size_t data_size = 0) :
572         MemoryBlob(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l)) {
573         if (data_size == 0) {
574             data_size = size();
575         }
576         if (data_size != 0 && ptr == nullptr) {
577             THROW_IE_EXCEPTION << "Using Blob on external nullptr memory";
578         }
579         _allocator = details::make_pre_allocator(ptr, data_size);
580         // blob on attached memory is always allocated, so we are not forcing user to call allocate
581         allocate();
582     }
583
584     /**
585      * @deprecated Use TBlob::TBlob(const TensorDesc&).
586      * @brief Constructor. Creates a TBlob object with the specified precision, layout, dimensions and custom memory allocator.
587      * @param p Precision
588      * @param l Layout
589      * @param dims Tensor dimensions
590      * @param alloc Allocator to be used
591      */
592     INFERENCE_ENGINE_DEPRECATED
593     TBlob(Precision p, Layout l, const SizeVector &dims, std::shared_ptr<IAllocator> alloc)
594             : MemoryBlob(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l)), _allocator(alloc) {
595     }
596
597     /**
598      * @brief The copy constructor data is reallocated and copied from the source to the target blob.
599      * @param blob Source blob
600      */
601     TBlob(const TBlob<T> &blob) : MemoryBlob(blob.getTensorDesc()) {
602         copyFrom(blob);
603     }
604
605     /**
606      * @brief A move constructor.
607      * @param blob rvalue to make a move from
608      */
609     TBlob(TBlob<T> &&blob) : MemoryBlob(blob.getTensorDesc()) {
610         moveFrom(blob);
611     }
612
613     /**
614      * @brief Copy operator for the TBlob object.
615      * @param blob object reference to copy from
616      * @return Newly copied object
617      */
618     TBlob &operator=(const TBlob &blob) {
619         copyFrom(blob);
620         return *this;
621     }
622
623     /**
624      *@brief Virtual destructor.
625      */
626     virtual ~TBlob() {
627         free();
628     }
629
630     /**
631      * @brief Gets the size of the given type.
632      * @return Size of the type
633      */
634     size_t element_size() const noexcept override {
635         return sizeof(T);
636     }
637
638     /**
639      * @brief Creates an new empty rvalue LockedMemory object.
640      * @return rvalue for the empty locked object of type T
641      */
642     virtual LockedMemory<T> data() noexcept {
643         return std::move(lockme<T>());
644     }
645
646     /**
647      * @brief Creates a new empty rvalue read-only LockedMemory object.
648      * @return rvalue for the empty locked const object of type T.
649      */
650     virtual LockedMemory<const T> readOnly() const noexcept {
651         return std::move(lockme<const T>());
652     }
653
654     /**
655       * @deprecated Deprecated to avoid memcpy() calls. Use TBlob::buffer to get raw pointer and set data
656       * @brief Copies data from the given vector to the blob.
657       * @param that Vector of values to copy to the blob
658       */
659     INFERENCE_ENGINE_DEPRECATED
660     void set(const std::vector<T> &that)  {
661         if (tensorDesc.getDims().size() != 0 && that.size() != product(tensorDesc.getDims()))
662             THROW_IE_EXCEPTION << "Size mismatch between dims and vector";
663         if (tensorDesc.getDims().size() == 0) {
664             tensorDesc.setDims({static_cast<unsigned int>(that.size())});
665         }
666         // minimisation of reallocations
667         if (_handle == nullptr) {
668             allocate();
669         }
670         auto memptr = data();
671         memcpy(memptr, that.data(), byteSize());
672     }
673
674     /**
675      * @brief Allocates or reallocates memory
676      */
677     void allocate() noexcept override {
678         if (_handle != nullptr) {
679             getAllocator()->free(_handle);
680         }
681         _handle = getAllocator()->alloc(byteSize());
682     }
683
684     /**
685      * @brief Frees all allocated data
686      */
687     bool deallocate() noexcept override {
688         return free();
689     }
690
691     /**
692      * @brief Creates a new LockedMemory instance holding void pointer.
693      * @return LockedMemory instance holding void pointer
694      */
695     LockedMemory<void> buffer() noexcept override {
696         return std::move(lockme<void>());
697     }
698
699     /**
700      * @brief Creates a new LockedMemory instance holding constant void pointer.
701      * @return LockedMemory instance holding constant void pointer
702      */
703     LockedMemory<const void> cbuffer() const noexcept override {
704         return std::move(lockme<const void>());
705     }
706
707     /**
708      * @brief Gets BlobIterator for the data.
709      * Enables a ranged loop support for the TBlob object.
710      * @return BlobIterator object of type T
711      */
712     details::BlobIterator<T> begin() {
713         return details::BlobIterator<T>(data());
714     }
715
716     /**
717      * @brief Gets BlobIterator for the end of data.
718      * Enables a ranged loop support for the TBlob object.
719      * @return BlobIterator object of type T representing end of the data
720      */
721     details::BlobIterator<T> end() {
722         return details::BlobIterator<T>(data(), size());
723     }
724
725     /**
726      * @brief Gets a const BlobIterator for the read-only data.
727      * Enables a ranged loop support for the TBlob object.
728      * @return BlobIterator object of type const T
729      */
730     details::BlobIterator<const T> begin() const {
731         return details::BlobIterator<const T>(readOnly());
732     }
733
734     /**
735     * @brief Gets a const BlobIterator for the end of read-only data.
736     * Enables a ranged loop support for the TBlob object.
737     * @return BlobIterator object of type const T representing end of data
738     */
739     details::BlobIterator<const T> end() const {
740         return details::BlobIterator<const T>(readOnly(), size());
741     }
742
743
744 protected:
745     /**
746      * @brief Local instance of IAllocator to manipulate memory.
747      */
748     mutable std::shared_ptr<IAllocator> _allocator;
749
750     /**
751      * @brief A handle for the stored memory returned from _allocator.alloc().
752      */
753     void *_handle = nullptr;
754
755     /**
756      * @brief Copies dimensions and data from the TBlob object.
757      * @param blob object reference to copy from
758      */
759     void copyFrom(const TBlob<T> &blob) {
760         tensorDesc = blob.tensorDesc;
761         this->allocate();
762         auto memptr = data();
763         memcpy(memptr, blob.readOnly(), byteSize());
764     }
765
766     /**
767      * @brief Swaps memory handlers between the current blob and the given one.
768      * @tparam U Type of the blob to move from
769      * @param blob TBlob instance to move from
770      */
771     template<class U>
772     void moveFrom(TBlob<U> &blob) {
773         tensorDesc = blob.tensorDesc;
774         this->_allocator = std::move(blob._allocator);
775         std::swap(this->_handle, blob._handle);
776     }
777
778     /**
779      * @brief Frees handler and cleans up the stored data.
780      */
781     virtual bool free() {
782         bool bCanRelease = true;
783         if (_handle == nullptr) return bCanRelease;
784
785         bCanRelease = getAllocator()->free(_handle);
786         _handle = nullptr;
787         return bCanRelease;
788     }
789
790     /**
791      * @brief Creates a LockedMemory instance.
792      * @tparam S Type of the LockedMemory to be created
793      * @return A created instance of LockedMemory
794      */
795     template<class S>
796     LockedMemory<S> lockme() const {
797         return LockedMemory<S>(_allocator.get(), _handle, 0);
798     }
799
800     /**
801      * @brief Gets an allocator or creates a default one.
802      * @return IAllocator instance
803      */
804     const std::shared_ptr<IAllocator> &getAllocator() const noexcept override {
805         // in case when constructor without allocator was used
806         if (!_allocator) {
807             _allocator = shared_from_irelease(CreateDefaultAllocator());
808         }
809
810         return _allocator;
811     }
812
813     /**
814      * @brief Returns handle to the stored data.
815      */
816     void *getHandle() const noexcept override {
817         return _handle;
818     }
819 };
820
821 /**
822  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
823  * @brief Creates a blob with given precision and dimensions.
824  * @tparam Type Type of the shared pointer to be created
825  * @param p Given precision
826  * @param dims Given dimensions
827  * @return A shared pointer to the created blob
828  */
829 template<class Type>
830 INFERENCE_ENGINE_DEPRECATED
831 inline typename TBlob<Type>::Ptr make_shared_blob(Precision p, Layout l, const SizeVector &dims) {
832     if (!p.hasStorageType<Type>())
833         THROW_IE_EXCEPTION << "Cannot make shared blob! "
834                            << "The blob type cannot be used to store objects of current precision";
835     return std::make_shared<TBlob<Type>>(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l));
836 }
837
838 /**
839  * @deprecated Use the make_shared_blob signature which accepts TensorDesc
840  * @brief Creates a blob with the NCHW layout, given precision, and given dimensions.
841  * @tparam Type Type of the shared pointer to be created
842  * @param p Given precision
843  * @param dims Given dimensions
844  * @return A shared pointer to the created blob
845  */
846 template<class Type>
847 INFERENCE_ENGINE_DEPRECATED
848 inline typename TBlob<Type>::Ptr make_shared_blob(Precision p, const SizeVector &dims) {
849     if (!p.hasStorageType<Type>())
850         THROW_IE_EXCEPTION << "Cannot make shared blob! "
851                            << "The blob type cannot be used to store objects of current precision";
852     return make_shared_blob<Type>(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), TensorDesc::getLayoutByDims(dims)));
853 }
854
855 /**
856  * @deprecated Use the make_shared_blob signature which accepts TensorDesc
857  * @brief Creates a blob with the given precision.
858  * @tparam Type Type of the shared pointer to be created
859  * @param p Given precision
860  * @param arg Shared pointer to IAllocator to use in the blob
861  * @return A shared pointer to the blob created
862  */
863 template<typename Type, class TArg>
864 INFERENCE_ENGINE_DEPRECATED
865 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(Precision p, Layout l, const TArg &arg) {
866     if (!p.hasStorageType<Type>())
867         THROW_IE_EXCEPTION << "Cannot make shared blob! "
868                            << "The blob type cannot be used to store objects of current precision";
869     return std::make_shared<InferenceEngine::TBlob<Type>>(TensorDesc(p, SizeVector(arg.rbegin(), arg.rend()), l));
870 }
871
872 /**
873  * @deprecated Use the make_shared_blob signature which accepts TensorDesc
874  * @brief Creates a blob with the NCHW layout and given tensor precision.
875  * @tparam Type Type of the shared pointer to be created
876  * @param p Given precision
877  * @param arg Shared pointer to IAllocator to use in the blob
878  * @return A shared pointer to the blob created
879  */
880 template<typename Type, class TArg>
881 INFERENCE_ENGINE_DEPRECATED
882 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(Precision p, const TArg &arg) {
883     if (!p.hasStorageType<Type>())
884         THROW_IE_EXCEPTION << "Cannot make shared blob! "
885                            << "The blob type cannot be used to store objects of current precision";
886     return make_shared_blob<Type>(TensorDesc(p, SizeVector(arg.rbegin(), arg.rend()), TensorDesc::getLayoutByDims(arg)));
887 }
888
889 /**
890  * @brief Creates a blob with the given tensor descriptor.
891  * @tparam Type Type of the shared pointer to be created
892  * @param tensorDesc Tensor descriptor for Blob creation
893  * @return A shared pointer to the newly created blob of the given type
894  */
895 template<typename Type>
896 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc) {
897     if (!tensorDesc.getPrecision().hasStorageType<Type>())
898         THROW_IE_EXCEPTION << "Cannot make shared blob! "
899                            << "The blob type cannot be used to store objects of current precision";
900     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc);
901 }
902
903 /**
904  * @brief Creates a blob with the given tensor descriptor from the pointer to the pre-allocated memory.
905  * @tparam Type Type of the shared pointer to be created
906  * @param tensorDesc TensorDesc for Blob creation
907  * @param ptr Pointer to the pre-allocated memory
908  * @param size Length of the pre-allocated array
909  * @return A shared pointer to the newly created blob of the given type
910  */
911 template<typename Type>
912 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc, Type * ptr, size_t size = 0) {
913     if (!tensorDesc.getPrecision().hasStorageType<Type>())
914         THROW_IE_EXCEPTION << "Cannot make shared blob! "
915                            << "The blob type cannot be used to store objects of current precision";
916     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, ptr, size);
917 }
918
919 /**
920  * @brief Creates a blob with the given tensor descriptor and allocator.
921  * @tparam Type Type of the shared pointer to be created
922  * @param tensorDesc Tensor descriptor for Blob creation
923  * @param alloc Shared pointer to IAllocator to use in the blob
924  * @return A shared pointer to the newly created blob of the given type
925  */
926 template<typename Type>
927 inline typename InferenceEngine::TBlob<Type>::Ptr make_shared_blob(const TensorDesc& tensorDesc, const std::shared_ptr<InferenceEngine::IAllocator>& alloc) {
928     if (!tensorDesc.getPrecision().hasStorageType<Type>())
929         THROW_IE_EXCEPTION << "Cannot make shared blob! "
930                            << "The blob type cannot be used to store objects of current precision";
931     return std::make_shared<InferenceEngine::TBlob<Type>>(tensorDesc, alloc);
932 }
933
934 /**
935  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
936  * @brief Gets a shared pointer for the new TBlob instance.
937  * The created instance is based on move semantics from the given TBlob instance.
938  * @tparam TypeTo Type of the shared pointer to be created
939  * @param arg rvalue for the blob to move from
940  * @return A shared pointer to the newly created blob of the given type
941  */
942 template<typename TypeTo>
943 INFERENCE_ENGINE_DEPRECATED
944 inline typename InferenceEngine::TBlob<TypeTo>::Ptr make_shared_blob(TBlob<TypeTo> &&arg) {
945     return std::make_shared<InferenceEngine::TBlob<TypeTo>>(std::move(arg));
946 }
947
948 /**
949  * @brief Creates a copy of given TBlob instance.
950  * @tparam TypeTo Type of the shared pointer to be created
951  * @param arg given pointer to blob
952  * @return A shared pointer to the newly created blob of the given type
953  */
954 template<typename TypeTo>
955 inline typename InferenceEngine::TBlob<TypeTo>::Ptr make_shared_blob(const TBlob<TypeTo> &arg) {
956     return std::make_shared<InferenceEngine::TBlob<TypeTo>>(arg);
957 }
958
959 /**
960  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
961  * @brief Creates a blob with the given precision.
962  * @tparam TypeTo Type of the shared pointer to be created
963  * @param p Given precision
964  * @return A shared pointer to the blob created
965  */
966 template<typename TypeTo>
967 INFERENCE_ENGINE_DEPRECATED
968 inline typename InferenceEngine::TBlob<TypeTo>::Ptr make_shared_blob(Precision p, Layout l = NCHW) {
969     if (!p.hasStorageType<TypeTo>())
970         THROW_IE_EXCEPTION << "Cannot make shared blob! "
971                            << "The blob type cannot be used to store objects of current precision";
972     return std::make_shared<TBlob<TypeTo>>(TensorDesc(p, l));
973 }
974
975 /**
976  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
977  * @brief Creates a blob with the given precision, layout and dimensions from the vector of values.
978  * @tparam TypeTo Type of the shared pointer to be created
979  * @param p Given precision
980  * @param l Given Layout
981  * @param dims Given dimensions
982  * @param arg Vector of values
983  * @return A shared pointer to the blob created
984  */
985 template<typename TypeTo>
986 INFERENCE_ENGINE_DEPRECATED
987 inline typename TBlob<TypeTo>::Ptr make_shared_blob(Precision p, Layout l, SizeVector dims, const std::vector<TypeTo> &arg) {
988     if (!p.hasStorageType<TypeTo>())
989         THROW_IE_EXCEPTION << "Cannot make shared blob! "
990                            << "The blob type cannot be used to store objects of current precision";
991     auto blob = std::make_shared<TBlob<TypeTo>>(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l));
992     blob->set(arg);
993     return blob;
994 }
995
996 /**
997  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
998  * @brief Creates a blob with the given precision from the vector of values.
999  * @tparam TypeTo Type of the shared pointer to be created
1000  * @param p Given precision
1001  * @param l Layout
1002  * @param arg Vector of values
1003  * @return A shared pointer to the blob created
1004  */
1005 template<typename TypeTo>
1006 INFERENCE_ENGINE_DEPRECATED
1007 inline typename TBlob<TypeTo>::Ptr make_shared_blob(Precision p, Layout l, const std::vector<TypeTo> &arg) {
1008     if (!p.hasStorageType<TypeTo>())
1009         THROW_IE_EXCEPTION << "Cannot make shared blob! "
1010                            << "The blob type cannot be used to store objects of current precision";
1011     auto blob = std::make_shared<TBlob<TypeTo>>(TensorDesc(p, l));
1012     blob->set(arg);
1013     return blob;
1014 }
1015
1016 /**
1017  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
1018  * @brief Creates a blob with the NCHW layout and the given precision from the vector of values.
1019  * @tparam TypeTo Type of the shared pointer to be created
1020  * @param p Given precision
1021  * @param arg Vector of values
1022  * @return A shared pointer to the blob created
1023  */
1024 template<typename TypeTo>
1025 INFERENCE_ENGINE_DEPRECATED
1026 inline typename TBlob<TypeTo>::Ptr make_shared_blob(Precision p, const std::vector<TypeTo> &arg) {
1027     if (!p.hasStorageType<TypeTo>())
1028         THROW_IE_EXCEPTION << "Cannot make shared blob! "
1029                            << "The blob type cannot be used to store objects of current precision";
1030     return make_shared_blob<TypeTo>(TensorDesc(p, SizeVector(arg.rbegin(), arg.rend()), TensorDesc::getLayoutByDims(arg)));
1031 }
1032
1033 /**
1034  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
1035  * @brief Creates a blob with the given precision from the pointer to the pre-allocated memory.
1036  * @param p Given precision
1037  * @param l Layout
1038  * @param dims Given dimensions
1039  * @param ptr Pointer to the pre-allocated memory
1040  * @param size Length of the pre-allocated array
1041  * @return A shared pointer to the blob created
1042  */
1043 template <typename TypeTo>
1044 INFERENCE_ENGINE_DEPRECATED
1045 inline typename TBlob<TypeTo>::Ptr make_shared_blob(Precision p, Layout l, const SizeVector &dims, TypeTo * ptr, size_t size = 0) {
1046     if (!p.hasStorageType<TypeTo>())
1047         THROW_IE_EXCEPTION << "Cannot make shared blob! "
1048                            << "The blob type cannot be used to store objects of current precision";
1049     auto blob = std::make_shared<TBlob<TypeTo>>(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), l), ptr, size);
1050     return blob;
1051 }
1052
1053 /**
1054  * @deprecated Use InferenceEngine::make_shared_blob(const TensorDesc&)
1055  * @brief Creates a blob with the NCHW layout and the given precision from the pointer to the pre-allocated memory
1056  * @param p Given precision
1057  * @param dims Given dimensions
1058  * @param ptr Pointer to the pre-allocated memory
1059  * @param size Length of the pre-allocated array
1060  * @return A shared pointer to the blob created
1061  */
1062 template <typename TypeTo>
1063 INFERENCE_ENGINE_DEPRECATED
1064 inline typename TBlob<TypeTo>::Ptr make_shared_blob(Precision p, const SizeVector &dims, TypeTo * ptr, size_t size = 0) {
1065     if (!p.hasStorageType<TypeTo>())
1066         THROW_IE_EXCEPTION << "Cannot make shared blob! "
1067                            << "The blob type cannot be used to store objects of current precision";
1068     return make_shared_blob<TypeTo>(TensorDesc(p, SizeVector(dims.rbegin(), dims.rend()), TensorDesc::getLayoutByDims(dims)), ptr, size);
1069 }
1070
1071 /**
1072  * @brief Creates a Blob object of the specified type
1073  * @param args Constructor arguments for the Blob object
1074  * @return A shared pointer to the newly created Blob object
1075  */
1076 template<typename T, typename ...Args,
1077          typename std::enable_if<std::is_base_of<Blob, T>::value, int>::type = 0>
1078 std::shared_ptr<T> make_shared_blob(Args&& ...args) {
1079     return std::make_shared<T>(std::forward<Args>(args)...);
1080 }
1081
1082 /**
1083  * @brief This structure describes ROI data.
1084  */
1085 struct ROI {
1086     size_t id;     // ID of a ROI
1087     size_t posX;   // W upper left coordinate of ROI
1088     size_t posY;   // H upper left coordinate of ROI
1089     size_t sizeX;  // W size of ROI
1090     size_t sizeY;  // H size of ROI
1091 };
1092
1093 /**
1094  * @brief Creates a blob describing given ROI object based on the given blob with pre-allocated memory.
1095  * @param inputBlob original blob with pre-allocated memory.
1096  * @param roi A ROI object inside of the original blob.
1097  * @return A shared pointer to the newly created blob.
1098  */
1099 INFERENCE_ENGINE_API_CPP(Blob::Ptr) make_shared_blob(const Blob::Ptr &inputBlob, const ROI &roi);
1100
1101 }  // namespace InferenceEngine