2018-05-01 21:50:34 +02:00
|
|
|
// Copyright (c) 2018, NVIDIA CORPORATION. All rights reserved.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
|
2018-06-18 20:03:43 +02:00
|
|
|
#ifndef FORTRAN_COMMON_REFERENCE_COUNTED_H_
|
|
|
|
#define FORTRAN_COMMON_REFERENCE_COUNTED_H_
|
2018-04-17 19:28:25 +02:00
|
|
|
|
2018-05-31 18:44:27 +02:00
|
|
|
// A class template of smart pointers to objects with their own
|
2018-04-17 19:28:25 +02:00
|
|
|
// reference counting object lifetimes that's lighter weight
|
|
|
|
// than std::shared_ptr<>. Not thread-safe.
|
|
|
|
|
2018-06-18 20:03:43 +02:00
|
|
|
namespace Fortran::common {
|
2018-04-17 19:28:25 +02:00
|
|
|
|
2018-07-27 23:58:14 +02:00
|
|
|
// A base class for reference-counted objects. Must be public.
|
2018-04-17 19:28:25 +02:00
|
|
|
template<typename A> class ReferenceCounted {
|
|
|
|
public:
|
|
|
|
ReferenceCounted() {}
|
|
|
|
void TakeReference() { ++references_; }
|
|
|
|
void DropReference() {
|
|
|
|
if (--references_ == 0) {
|
2018-04-17 23:45:43 +02:00
|
|
|
delete static_cast<A *>(this);
|
2018-04-17 19:28:25 +02:00
|
|
|
}
|
|
|
|
}
|
2018-04-17 23:45:43 +02:00
|
|
|
|
2018-04-17 19:28:25 +02:00
|
|
|
private:
|
|
|
|
int references_{0};
|
|
|
|
};
|
|
|
|
|
2018-06-18 20:03:43 +02:00
|
|
|
// A reference to a reference-counted object.
|
2018-04-17 19:28:25 +02:00
|
|
|
template<typename A> class CountedReference {
|
|
|
|
public:
|
|
|
|
using type = A;
|
|
|
|
CountedReference() {}
|
|
|
|
CountedReference(type *m) : p_{m} { Take(); }
|
|
|
|
CountedReference(const CountedReference &c) : p_{c.p_} { Take(); }
|
|
|
|
CountedReference(CountedReference &&c) : p_{c.p_} { c.p_ = nullptr; }
|
|
|
|
CountedReference &operator=(const CountedReference &c) {
|
2018-04-17 20:16:05 +02:00
|
|
|
c.Take();
|
2018-04-17 19:28:25 +02:00
|
|
|
Drop();
|
|
|
|
p_ = c.p_;
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
CountedReference &operator=(CountedReference &&c) {
|
2018-04-17 20:16:05 +02:00
|
|
|
A *p{c.p_};
|
2018-04-17 19:28:25 +02:00
|
|
|
c.p_ = nullptr;
|
2018-04-17 20:16:05 +02:00
|
|
|
Drop();
|
|
|
|
p_ = p;
|
2018-04-17 19:28:25 +02:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
~CountedReference() { Drop(); }
|
|
|
|
operator bool() const { return p_ != nullptr; }
|
|
|
|
type *get() const { return p_; }
|
|
|
|
type &operator*() const { return *p_; }
|
|
|
|
type *operator->() const { return p_; }
|
|
|
|
|
|
|
|
private:
|
2018-04-17 20:16:05 +02:00
|
|
|
void Take() const {
|
2018-04-17 19:28:25 +02:00
|
|
|
if (p_) {
|
|
|
|
p_->TakeReference();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void Drop() {
|
|
|
|
if (p_) {
|
|
|
|
p_->DropReference();
|
|
|
|
p_ = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type *p_{nullptr};
|
|
|
|
};
|
2018-10-25 14:55:23 +02:00
|
|
|
}
|
2018-06-18 20:03:43 +02:00
|
|
|
#endif // FORTRAN_COMMON_REFERENCE_COUNTED_H_
|