#pragma once #include namespace c10 { struct C10_API Storage { public: Storage() {} Storage(c10::intrusive_ptr ptr) : storage_impl_(std::move(ptr)) {} // Allocates memory buffer using given allocator and creates a storage with it Storage( caffe2::TypeMeta data_type, size_t size, Allocator* allocator, bool resizable) : storage_impl_(c10::make_intrusive( data_type, size, allocator, resizable)) {} // Creates storage with pre-allocated memory buffer. Allocator is given for // potential future reallocations, however it can be nullptr if the storage // is non-resizable Storage( caffe2::TypeMeta data_type, int64_t numel, at::DataPtr data_ptr, at::Allocator* allocator, bool resizable) : storage_impl_(c10::make_intrusive( data_type, numel, std::move(data_ptr), allocator, resizable)) {} // Legacy constructor for partially initialized (dtype or memory) storages // that can be temporarily created with Caffe2 APIs. See the note on top of // TensorImpl.h for details. static Storage create_legacy(at::Device device, caffe2::TypeMeta data_type) { auto allocator = GetAllocator(device.type()); return Storage(c10::make_intrusive( data_type, 0, allocator->allocate(0), // materialize a non-default Device. allocator, true)); } template inline bool IsType() const { return storage_impl_->IsType(); } template T* data() const { return storage_impl_->data(); } template T* unsafe_data() const { return storage_impl_->unsafe_data(); } size_t elementSize() const { return storage_impl_->itemsize(); } inline size_t itemsize() const { return storage_impl_->itemsize(); } ptrdiff_t size() const { return storage_impl_->numel(); } int64_t numel() const { return storage_impl_->numel(); } // TODO: remove later void set_numel(int64_t numel) const { storage_impl_.get()->set_numel(numel); } bool resizable() const { return storage_impl_->resizable(); } size_t capacity() const { return storage_impl_->capacity(); } // get() use here is to get const-correctness void* data() const { return storage_impl_.get()->data(); } const caffe2::TypeMeta& dtype() const { return storage_impl_->dtype(); } at::DataPtr& data_ptr() { return storage_impl_->data_ptr(); } const at::DataPtr& data_ptr() const { return storage_impl_->data_ptr(); } // Returns the previous data_ptr at::DataPtr set_data_ptr(at::DataPtr&& data_ptr) const { return storage_impl_.get()->set_data_ptr(std::move(data_ptr)); }; void set_dtype(const caffe2::TypeMeta& data_type) const { storage_impl_.get()->set_dtype(data_type); } DeviceType device_type() const { return storage_impl_->device_type(); } at::Allocator* allocator() const { return storage_impl_.get()->allocator(); } at::Device device() const { return storage_impl_->device(); } StorageImpl* unsafeReleaseStorageImpl() { return storage_impl_.release(); } StorageImpl* unsafeGetStorageImpl() const noexcept { return storage_impl_.get(); } operator bool() const { return storage_impl_; } size_t use_count() const { return storage_impl_.use_count(); } inline bool unique() const { return storage_impl_.unique(); } bool is_alias_of(const Storage& other) const { return storage_impl_ == other.storage_impl_; } void UniqueStorageShareExternalPointer( void* src, const caffe2::TypeMeta& data_type, size_t capacity, DeleterFnPtr d = nullptr) { if (!storage_impl_.unique()) { AT_ERROR( "UniqueStorageShareExternalPointer can only be called when use_count == 1"); } storage_impl_->UniqueStorageShareExternalPointer( src, data_type, capacity, d); } void UniqueStorageShareExternalPointer( at::DataPtr&& data_ptr, const caffe2::TypeMeta& data_type, size_t capacity) { if (!storage_impl_.unique()) { AT_ERROR( "UniqueStorageShareExternalPointer can only be called when use_count == 1"); } storage_impl_->UniqueStorageShareExternalPointer( std::move(data_ptr), data_type, capacity); } protected: c10::intrusive_ptr storage_impl_; }; } // namespace c10