diff --git a/src/Expr.cc b/src/Expr.cc index 0f3fd81470..754044530e 100644 --- a/src/Expr.cc +++ b/src/Expr.cc @@ -2828,7 +2828,7 @@ Val* IndexExpr::Fold(Val* v1, Val* v2) const void IndexExpr::Assign(Frame* f, Val* arg_v) { - IntrusivePtr v{arg_v, false}; + IntrusivePtr v{AdoptRef{}, arg_v}; if ( IsError() ) return; @@ -2849,7 +2849,7 @@ void IndexExpr::Assign(Frame* f, Val* arg_v) // Hold an extra reference to 'arg_v' in case the ownership transfer to // the table/vector goes wrong and we still want to obtain diagnostic info // from the original value after the assignment already unref'd. - IntrusivePtr v_extra{arg_v, true}; + IntrusivePtr v_extra{NewRef{}, arg_v}; switch ( v1->Type()->Tag() ) { case TYPE_VECTOR: diff --git a/src/IntrusivePtr.h b/src/IntrusivePtr.h index 3550b1fc46..767aae197c 100644 --- a/src/IntrusivePtr.h +++ b/src/IntrusivePtr.h @@ -5,6 +5,18 @@ #include #include +/** + * A tag class for the #IntrusivePtr constructor which means: adopt + * the reference from the caller. + */ +struct AdoptRef {}; + +/** + * A tag class for the #IntrusivePtr constructor which means: create a + * new reference to the object. + */ +struct NewRef {}; + /** * An intrusive, reference counting smart pointer implementation. Much like * @c std::shared_ptr, this smart pointer models shared ownership of an object @@ -54,13 +66,27 @@ public: /** * Constructs a new intrusive pointer for managing the lifetime of the object * pointed to by @c raw_ptr. + * + * This overload adopts the existing reference from the caller. + * * @param raw_ptr Pointer to the shared object. - * @param add_ref Denotes whether the reference count of the object shall be - * increased during construction. */ - IntrusivePtr(pointer raw_ptr, bool add_ref) noexcept + IntrusivePtr(AdoptRef, pointer raw_ptr) noexcept { - setPtr(raw_ptr, add_ref); + setPtr(raw_ptr, false); + } + + /** + * Constructs a new intrusive pointer for managing the lifetime of the object + * pointed to by @c raw_ptr. + * + * This overload adds a new reference. + * + * @param raw_ptr Pointer to the shared object. + */ + IntrusivePtr(NewRef, pointer raw_ptr) noexcept + { + setPtr(raw_ptr, true); } IntrusivePtr(IntrusivePtr&& other) noexcept : ptr_(other.release()) @@ -69,8 +95,8 @@ public: } IntrusivePtr(const IntrusivePtr& other) noexcept + : IntrusivePtr(NewRef{}, other.get()) { - setPtr(other.get(), true); } template >> @@ -157,7 +183,7 @@ template IntrusivePtr make_intrusive(Ts&&... args) { // Assumes that objects start with a reference count of 1! - return {new T(std::forward(args)...), false}; + return {AdoptRef{}, new T(std::forward(args)...)}; } // -- comparison to nullptr ---------------------------------------------------- diff --git a/src/Stmt.cc b/src/Stmt.cc index 539ab8a0a5..15400632d7 100644 --- a/src/Stmt.cc +++ b/src/Stmt.cc @@ -207,7 +207,7 @@ static IntrusivePtr lookup_enum_val(const char* module_name, const char int index = et->Lookup(module_name, name); assert(index >= 0); - IntrusivePtr rval{et->GetVal(index), false}; + IntrusivePtr rval{AdoptRef{}, et->GetVal(index)}; return rval; } diff --git a/src/Val.cc b/src/Val.cc index 4b065c99a2..1c11070d0c 100644 --- a/src/Val.cc +++ b/src/Val.cc @@ -1984,7 +1984,7 @@ void TableVal::CallChangeFunc(const Val* index, Val* old_value, OnChangeType tpe try { - IntrusivePtr thefunc{change_func->Eval(nullptr), false}; + IntrusivePtr thefunc{AdoptRef{}, change_func->Eval(nullptr)}; if ( ! thefunc ) { diff --git a/src/broker/Data.cc b/src/broker/Data.cc index 704afe2cd2..513d13bfd6 100644 --- a/src/broker/Data.cc +++ b/src/broker/Data.cc @@ -792,9 +792,9 @@ static bool data_type_check(const broker::data& d, BroType* t) IntrusivePtr bro_broker::data_to_val(broker::data d, BroType* type) { if ( type->Tag() == TYPE_ANY ) - return {bro_broker::make_data_val(move(d)), false}; + return {AdoptRef{}, bro_broker::make_data_val(move(d))}; - return {caf::visit(val_converter{type}, std::move(d)), false}; + return {AdoptRef{}, caf::visit(val_converter{type}, std::move(d))}; } broker::expected bro_broker::val_to_data(const Val* v) diff --git a/src/supervisor/Supervisor.cc b/src/supervisor/Supervisor.cc index 26ef5f4c10..b790eeead8 100644 --- a/src/supervisor/Supervisor.cc +++ b/src/supervisor/Supervisor.cc @@ -1024,7 +1024,7 @@ Supervisor::NodeConfig Supervisor::NodeConfig::FromRecord(const RecordVal* node) while ( (v = cluster_table->NextEntry(k, c)) ) { - IntrusivePtr key{cluster_table_val->RecoverIndex(k), false}; + IntrusivePtr key{AdoptRef{}, cluster_table_val->RecoverIndex(k)}; delete k; auto name = key->Index(0)->AsStringVal()->ToStdString(); auto rv = v->Value()->AsRecordVal(); @@ -1100,7 +1100,7 @@ std::string Supervisor::NodeConfig::ToJSON() const { auto re = std::make_unique("^_"); auto node_val = ToRecord(); - IntrusivePtr json_val{node_val->ToJSON(false, re.get()), false}; + IntrusivePtr json_val{AdoptRef{}, node_val->ToJSON(false, re.get())}; auto rval = json_val->ToStdString(); return rval; } diff --git a/src/zeek.bif b/src/zeek.bif index 8062a6e5d6..ffa5acee02 100644 --- a/src/zeek.bif +++ b/src/zeek.bif @@ -400,7 +400,7 @@ function terminate%(%): bool // is false). static bool prepare_environment(TableVal* tbl, bool set) { - IntrusivePtr idxs{tbl->ConvertToPureList(), false}; + IntrusivePtr idxs{AdoptRef{}, tbl->ConvertToPureList()}; for ( int i = 0; i < idxs->Length(); ++i ) {