// Copyright 2012 Google Inc. All Rights Reserved. // Author: rays@google.com (Ray Smith) /////////////////////////////////////////////////////////////////////// // File: doubleptr.h // Description: Double-ended pointer that keeps pointing correctly even // when reallocated or copied. // Author: Ray Smith // Created: Wed Mar 14 12:22:57 PDT 2012 // // (C) Copyright 2012, Google Inc. // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // /////////////////////////////////////////////////////////////////////// #ifndef TESSERACT_CCUTIL_DOUBLEPTR_H_ #define TESSERACT_CCUTIL_DOUBLEPTR_H_ #include "errcode.h" namespace tesseract { // A smart pointer class that implements a double-ended pointer. Each end // points to the other end. The copy constructor and operator= have MOVE // semantics, meaning that the relationship with the other end moves to the // destination of the copy, leaving the source unattached. // For this reason both the copy constructor and the operator= take a non-const // reference argument, and the const reference versions cannot be used. // DoublePtr is useful to incorporate into structures that are part of a // collection such as GenericVector or STL containers, where reallocs can // relocate the members. DoublePtr is also useful in a GenericHeap, where it // can correctly maintain the pointer to an element of the heap despite it // getting moved around on the heap. class DoublePtr { public: DoublePtr() : other_end_(nullptr) {} // Copy constructor steals the partner off src and is therefore a non // const reference arg. // Copying a const DoublePtr generates a compiler error. DoublePtr(const DoublePtr& src) { other_end_ = src.other_end_; if (other_end_ != nullptr) { other_end_->other_end_ = this; ((DoublePtr&)src).other_end_ = nullptr; } } // Operator= steals the partner off src, and therefore needs src to be a non- // const reference. // Assigning from a const DoublePtr generates a compiler error. void operator=(const DoublePtr& src) { Disconnect(); other_end_ = src.other_end_; if (other_end_ != nullptr) { other_end_->other_end_ = this; ((DoublePtr&)src).other_end_ = nullptr; } } // Connects this and other, discarding any existing connections. void Connect(DoublePtr* other) { other->Disconnect(); Disconnect(); other->other_end_ = this; other_end_ = other; } // Disconnects this and other, making OtherEnd() return nullptr for both. void Disconnect() { if (other_end_ != nullptr) { other_end_->other_end_ = nullptr; other_end_ = nullptr; } } // Returns the pointer to the other end of the double pointer. DoublePtr* OtherEnd() const { return other_end_; } private: // Pointer to the other end of the link. It is always true that either // other_end_ == nullptr or other_end_->other_end_ == this. DoublePtr* other_end_; }; } // namespace tesseract. #endif // THIRD_PARTY_TESSERACT_CCUTIL_DOUBLEPTR_H_