sapling/eden/fs/inodes/InodePtr.cpp
Adam Simpkins b4527fe5bb simplify InodePtr classes
Summary:
This simplifies the InodePtrImpl class by removing support for pointer-to-const
Inode objects.  We don't currently use pointer-to-const Inode objects, and I
don't really anticipate that we will ever need this.

The primary motivating factor behind this diff is a recent change in clang that
breaks the existing code: clang PR31606 prevents children classes from
inheriting template constructor instantiations from their parent which take a
reference to the parent class type as the only argument.

While this could have been fixed by explicitly defining the necessary
constructors in the child class (or simply by overriding newPtrLocked() and
newPtrFromExisting() to return the subclass type), dropping support for
pointer-to-const allows us to simplify the code and resolve this issue.

Reviewed By: wez

Differential Revision: D4825526

fbshipit-source-id: 999de352788b13818b7f23788bb34686e193cd5d
2017-04-06 13:20:01 -07:00

142 lines
4.0 KiB
C++

/*
* Copyright (c) 2016-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*
*/
#include "eden/fs/inodes/InodePtr.h"
#include "eden/fs/inodes/InodePtr-defs.h"
#include <type_traits>
#include "eden/fs/inodes/FileInode.h"
#include "eden/fs/inodes/InodeBase.h"
#include "eden/fs/inodes/InodeError.h"
#include "eden/fs/inodes/TreeInode.h"
namespace facebook {
namespace eden {
template <typename SubclassRawPtrType>
SubclassRawPtrType InodePtr::asSubclass() const {
if (this->value_ == nullptr) {
return nullptr;
}
auto* subclassPtr = dynamic_cast<SubclassRawPtrType>(this->value_);
if (subclassPtr == nullptr) {
throw InodeError(
std::remove_pointer<SubclassRawPtrType>::type::WRONG_TYPE_ERRNO, *this);
}
return subclassPtr;
}
template <typename SubclassPtrType>
SubclassPtrType InodePtr::asSubclassPtr() const {
if (this->value_ == nullptr) {
return SubclassPtrType{};
}
auto* subclassPtr =
dynamic_cast<typename SubclassPtrType::InodeType*>(this->value_);
if (subclassPtr == nullptr) {
throw InodeError(SubclassPtrType::InodeType::WRONG_TYPE_ERRNO, *this);
}
return SubclassPtrType{subclassPtr, SubclassPtrType::NORMAL_INCREMENT};
}
template <typename SubclassPtrType>
SubclassPtrType InodePtr::asSubclassPtrOrNull() const& {
return SubclassPtrType{
dynamic_cast<typename SubclassPtrType::InodeType*>(this->value_),
SubclassPtrType::NORMAL_INCREMENT};
}
template <typename SubclassPtrType>
SubclassPtrType InodePtr::extractSubclassPtr() {
if (this->value_ == nullptr) {
return SubclassPtrType{};
}
auto* subclassPtr =
dynamic_cast<typename SubclassPtrType::InodeType*>(this->value_);
if (subclassPtr == nullptr) {
throw InodeError(SubclassPtrType::InodeType::WRONG_TYPE_ERRNO, *this);
}
this->value_ = nullptr;
return SubclassPtrType{subclassPtr, SubclassPtrType::NO_INCREMENT};
}
template <typename SubclassPtrType>
SubclassPtrType InodePtr::extractSubclassPtrOrNull() {
if (this->value_ == nullptr) {
return SubclassPtrType{};
}
auto* subclassPtr =
dynamic_cast<typename SubclassPtrType::InodeType*>(this->value_);
if (subclassPtr == nullptr) {
return SubclassPtrType{};
}
this->value_ = nullptr;
return SubclassPtrType{subclassPtr, SubclassPtrType::NO_INCREMENT};
}
FileInode* InodePtr::asFile() const {
return asSubclass<FileInode*>();
}
FileInodePtr InodePtr::asFilePtr() const& {
return asSubclassPtr<FileInodePtr>();
}
FileInodePtr InodePtr::asFilePtr()&& {
return extractSubclassPtr<FileInodePtr>();
}
FileInode* InodePtr::asFileOrNull() const {
return dynamic_cast<FileInode*>(this->value_);
}
FileInodePtr InodePtr::asFilePtrOrNull() const& {
return FileInodePtr{dynamic_cast<FileInode*>(this->value_),
FileInodePtr::NORMAL_INCREMENT};
}
FileInodePtr InodePtr::asFilePtrOrNull()&& {
return extractSubclassPtrOrNull<FileInodePtr>();
}
TreeInode* InodePtr::asTree() const {
return asSubclass<TreeInode*>();
}
TreeInodePtr InodePtr::asTreePtr() const& {
return asSubclassPtr<TreeInodePtr>();
}
TreeInodePtr InodePtr::asTreePtr()&& {
return extractSubclassPtr<TreeInodePtr>();
}
TreeInode* InodePtr::asTreeOrNull() const {
return dynamic_cast<TreeInode*>(this->value_);
}
TreeInodePtr InodePtr::asTreePtrOrNull() const& {
return TreeInodePtr{dynamic_cast<TreeInode*>(this->value_),
TreeInodePtr::NORMAL_INCREMENT};
}
TreeInodePtr InodePtr::asTreePtrOrNull()&& {
return extractSubclassPtrOrNull<TreeInodePtr>();
}
// Explicitly instantiate InodePtrImpl for all inode class types
template class InodePtrImpl<FileInode>;
template class InodePtrImpl<TreeInode>;
template FileInodePtr InodePtr::asSubclassPtrOrNull<FileInodePtr>() const&;
template TreeInodePtr InodePtr::asSubclassPtrOrNull<TreeInodePtr>() const&;
}
}