mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
137 lines
4.5 KiB
C++
137 lines
4.5 KiB
C++
// Copyright 2013 The Flutter Authors. All rights reserved.
|
|
// Use of this source code is governed by a BSD-style license that can be
|
|
// found in the LICENSE file.
|
|
|
|
// Provides a base class for reference-counted classes.
|
|
|
|
#ifndef FLUTTER_FML_MEMORY_REF_COUNTED_H_
|
|
#define FLUTTER_FML_MEMORY_REF_COUNTED_H_
|
|
|
|
#include "flutter/fml/macros.h"
|
|
#include "flutter/fml/memory/ref_counted_internal.h"
|
|
#include "flutter/fml/memory/ref_ptr.h"
|
|
|
|
namespace fml {
|
|
|
|
// A base class for (thread-safe) reference-counted classes. Use like:
|
|
//
|
|
// class Foo : public RefCountedThreadSafe<Foo> {
|
|
// ...
|
|
// };
|
|
//
|
|
// |~Foo()| *may* be made private (e.g., to avoid accidental deletion of objects
|
|
// while there are still references to them), |Foo| should friend
|
|
// |RefCountedThreadSafe<Foo>|; use |FML_FRIEND_REF_COUNTED_THREAD_SAFE()|
|
|
// for this:
|
|
//
|
|
// class Foo : public RefCountedThreadSafe<Foo> {
|
|
// ...
|
|
// private:
|
|
// FML_FRIEND_REF_COUNTED_THREAD_SAFE(Foo);
|
|
// ~Foo();
|
|
// ...
|
|
// };
|
|
//
|
|
// Similarly, |Foo(...)| may be made private. In this case, there should either
|
|
// be a static factory method performing the requisite adoption:
|
|
//
|
|
// class Foo : public RefCountedThreadSafe<Foo> {
|
|
// ...
|
|
// public:
|
|
// inline static RefPtr<Foo> Create() { return AdoptRef(new Foo()); }
|
|
// ...
|
|
// private:
|
|
// Foo();
|
|
// ...
|
|
// };
|
|
//
|
|
// Or, to allow |MakeRefCounted()| to be used, use
|
|
// |FML_FRIEND_MAKE_REF_COUNTED()|:
|
|
//
|
|
// class Foo : public RefCountedThreadSafe<Foo> {
|
|
// ...
|
|
// private:
|
|
// FML_FRIEND_MAKE_REF_COUNTED(Foo);
|
|
// Foo();
|
|
// Foo(const Bar& bar, bool maybe);
|
|
// ...
|
|
// };
|
|
//
|
|
// For now, we only have thread-safe reference counting, since that's all we
|
|
// need. It's easy enough to add thread-unsafe versions if necessary.
|
|
template <typename T>
|
|
class RefCountedThreadSafe : public internal::RefCountedThreadSafeBase {
|
|
public:
|
|
// Adds a reference to this object.
|
|
// Inherited from the internal superclass:
|
|
// void AddRef() const;
|
|
|
|
// Releases a reference to this object. This will destroy this object once the
|
|
// last reference is released.
|
|
void Release() const {
|
|
if (internal::RefCountedThreadSafeBase::Release())
|
|
delete static_cast<const T*>(this);
|
|
}
|
|
|
|
// Returns true if there is exactly one reference to this object. Use of this
|
|
// is subtle, and should usually be avoided. To assert that there is only one
|
|
// reference (typically held by the calling thread, possibly in a local
|
|
// variable), use |AssertHasOneRef()| instead. However, a use is:
|
|
//
|
|
// if (foo->HasOneRef()) {
|
|
// // Do something "fast", since |foo| is the only reference and no other
|
|
// // thread can get another reference.
|
|
// ...
|
|
// } else {
|
|
// // Do something slower, but still valid even if there were only one
|
|
// // reference.
|
|
// ...
|
|
// }
|
|
//
|
|
// Inherited from the internal superclass:
|
|
// bool HasOneRef();
|
|
|
|
// Asserts that there is exactly one reference to this object; does nothing in
|
|
// Release builds (when |NDEBUG| is defined).
|
|
// Inherited from the internal superclass:
|
|
// void AssertHasOneRef();
|
|
|
|
protected:
|
|
// Constructor. Note that the object is constructed with a reference count of
|
|
// 1, and then must be adopted (see |AdoptRef()| in ref_ptr.h).
|
|
RefCountedThreadSafe() {}
|
|
|
|
// Destructor. Note that this object should only be destroyed via |Release()|
|
|
// (see above), or something that calls |Release()| (see, e.g., |RefPtr<>| in
|
|
// ref_ptr.h).
|
|
~RefCountedThreadSafe() {}
|
|
|
|
private:
|
|
#ifndef NDEBUG
|
|
template <typename U>
|
|
friend RefPtr<U> AdoptRef(U*);
|
|
// Marks the initial reference (assumed on construction) as adopted. This is
|
|
// only required for Debug builds (when |NDEBUG| is not defined).
|
|
// TODO(vtl): Should this really be private? This makes manual ref-counting
|
|
// and also writing one's own ref pointer class impossible.
|
|
void Adopt() { internal::RefCountedThreadSafeBase::Adopt(); }
|
|
#endif
|
|
|
|
FML_DISALLOW_COPY_AND_ASSIGN(RefCountedThreadSafe);
|
|
};
|
|
|
|
// If you subclass |RefCountedThreadSafe| and want to keep your destructor
|
|
// private, use this. (See the example above |RefCountedThreadSafe|.)
|
|
#define FML_FRIEND_REF_COUNTED_THREAD_SAFE(T) \
|
|
friend class ::fml::RefCountedThreadSafe<T>
|
|
|
|
// If you want to keep your constructor(s) private and still want to use
|
|
// |MakeRefCounted<T>()|, use this. (See the example above
|
|
// |RefCountedThreadSafe|.)
|
|
#define FML_FRIEND_MAKE_REF_COUNTED(T) \
|
|
friend class ::fml::internal::MakeRefCountedHelper<T>
|
|
|
|
} // namespace fml
|
|
|
|
#endif // FLUTTER_FML_MEMORY_REF_COUNTED_H_
|