[LLVMdev] New type of smart pointer for LLVM
Anton Yartsev
anton.yartsev at gmail.com
Wed Oct 1 15:14:04 PDT 2014
Ping!
Suggested is a wrapper over a raw pointer that is intended for freeing
wrapped memory at the end of wrappers lifetime if ownership of a raw
pointer was not taken away during the lifetime of the wrapper.
The main difference from unique_ptr is an ability to access the wrapped
pointer after the ownership is transferred.
To make the ownership clearer the wrapper is designed for local-scope
usage only.
The main goal of the wrapper is to eliminate leaks like those in
TGParser.cpp -r215176
<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?r1=215176&r2=215175&pathrev=215176&diff_format=f>.
With the wrapper the fixes applied at r215176
<http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/TableGen/TGParser.cpp?r1=215176&r2=215175&pathrev=215176&diff_format=f>
could be refactored in the more easy and safe way.
Attached is a proposed interface/implementation.
Any ideas, suggestions? Is it OK to move forward with the solution?
> Hello everyone,
>
> I bring to discussion the necessity/design of a new type of smart
> pointer. r215176 and r217791 rise the problem, D5443
> <http://reviews.llvm.org/D5443> is devoted to the solution.
> r215176 applies several temporary ugly fixes of memory leaks in
> TGParser.cpp which would be great to be refactored using smart
> pointers. D5443 <http://reviews.llvm.org/D5443> demonstrates how the
> solution with a certain type of smart pointer would look like (see
> changes in TGParser::ParseDef(), TGParser::InstantiateMulticlassDef()
> and TGParser::ParseSimpleValue()).
>
> Briefly:
> consider a leaky example:
> {
> T* p = new T;
> if (condition1) {
> f(p); // takes ownership of p
> }
> p->SomeMethod();
>
> if (condition2) {
> return nullptr; // Leak!
> }
>
> g(p); // don't take ownership of p
> return p;
> }
>
> The preferred solution would look like:
> {
> smart_ptr<T> p(new T);
> if (condition1) {
> f(p.StopOwn()); // takes ownership of p
> }
> p->SomeMethod();
>
> if (condition2) {
> return nullptr; //
> }
>
> g(p.Get()); // don't take ownership of p
> return p.StopOwn();
> }
>
> Neither unique_ptr nor shared_ptr can be used in the place of
> smart_ptr as unique_ptr sets the raw pointer to nullptr after
> release() (StopOwn() in the example above) whereas shared_ptr is
> unable to release.
>
> Attached is a scratch that illustrates how the minimal
> API/implementation of a desired smart pointer sufficient for
> refactoring would look like. Any ideas and suggestions are appreciated.
>
> --
> Anton
--
Anton
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141002/a4a5bd1c/attachment.html>
-------------- next part --------------
//===-- CondOwnershipPtr.h - Smart ptr with conditional release -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//===----------------------------------------------------------------------===//
#ifndef LLVM_ADT_CONDOWNERSHIPPTR_H
#define LLVM_ADT_CONDOWNERSHIPPTR_H
#include <memory>
namespace llvm {
template<class T>
class CondOwnershipPtr {
T* Ptr;
bool Own;
void Delete() {
if (Ptr && Own)
delete Ptr;
}
CondOwnershipPtr(const CondOwnershipPtr&); // Prevent from misuse.
CondOwnershipPtr& operator=(const CondOwnershipPtr&); // Prevent from misuse.
public:
CondOwnershipPtr() : Ptr(nullptr), Own(false) {}
explicit CondOwnershipPtr(T* p) : Ptr(p) { Own = Ptr && true; }
~CondOwnershipPtr() {
Delete();
}
T* Get() const {
return Ptr;
}
T* StopOwn() const {
Own = false;
return Ptr;
}
typename std::unique_ptr<T> MakeUnique() {
assert((!Ptr || Own) && "Ownership was transferred.");
return std::unique_ptr<T>(StopOwn());
}
void Reset(T* P = nullptr) {
if (P != Ptr) {
Delete();
Ptr = P;
Own = Ptr && true;
}
}
bool Owns() const {
return Ptr && Own;
}
operator bool() const {
return Ptr != nullptr;
}
T& operator*() const {
return *Ptr;
}
T* operator->() const {
return Ptr;
}
};
} // end namespace llvm
#endif
More information about the llvm-dev
mailing list