owned¶
owned (along with shared
) manage the
deallocation of a class instance. owned
is meant to be used when
only one reference to an object needs to manage that object's storage.
Using owned¶
To use owned
, use the owned keyword when allocating a class
instance, as shown in this example:
class MyClass { }
var myOwnedObject = new owned MyClass();
When myOwnedObject
goes out of scope, the class instance
it refers to will be deleted.
Copy initializing from myOwnedObject
or assigning it to another
owned
will leave myOwnedObject
storing a nil value
and transfer the owned class instance to the other value.
var otherOwnedObject = myOwnedObject;
// now myOwnedObject stores nil
// the value it stored earlier has moved to otherOwnedObject
myOwnedObject = otherOwnedObject;
// this assignment moves the value from the right-hand-side
// to the left-hand-side, leaving the right-hand-side empty.
// after the assignment, otherOwnedObject stores nil
// and myOwnedObject stores a value that will be deleted
// when myOwnedObject goes out of scope.
It is possible to transfer the ownership to another owned variable before that happens.
owned forms part of a type and can be used in type expressions:
var emptyOwnedObject: owned MyClass;
Borrowing from owned¶
The owned.borrow
method returns the pointer managed by the
owned
. This pointer is only valid as long as the owned
is storing that pointer.
The compiler includes a component called the lifetime checker that can, in many cases, check that a borrow does not refer to an object that could be deleted before the borrow. For example:
proc test() {
var a: owned MyClass = new owned MyClass();
// the instance referred to by a is deleted at end of scope
var c: borrowed MyClass = a.borrow();
// c "borrows" to the instance managed by a
return c; // lifetime checker error! returning borrow from local variable
// a is deleted here
}
Coercions for owned¶
The compiler includes support for introducing automatic coercions
from owned
to the contained class type. This is equivalent
to calling the owned.borrow
method. For example:
proc f(arg:MyClass) {
writeln(arg);
}
var myOwned = new owned MyClass();
f(myOwned); // compiler coerces to MyClass via borrow()
Additionally, the compiler includes support for coercing a value
of type owned T
to owned U
when T
is a subclass of U
.
For example:
class Person { }
class Student : Person { }
var myStudent = new owned Student();
var myPerson:owned Person = myStudent;
// relies on coercion from owned Student to owned Person
// moves the instance from myStudent to myPerson, leaving
// myStudent containing nil.
owned Intents and Instantiation¶
The default intent for owned
currently depends on whether
or not the formal argument was declared with a type.
If the formal argument has a declared type, the default intent is in, meaning that ownership will occur.
var global: owned MyClass;
proc saveit(arg: owned MyClass) {
global = arg; // OK! Transfers ownership from 'arg' to 'global'
// now that instance will be deleted at end of program
}
proc test0() {
var x = new owned MyClass();
saveit(x);
// now x stores `nil` since ownership was transfer to the argument
}
If the formal argument had no type (i.e. it is generic) and used const or default intent, the argument will not cause ownership transfer and the function will be instantiated with the borrow type if an owned actual is supplied. For example:
proc f(x) {
writeln("in f, x.type is ", x.type:string);
}
proc test1() {
writeln("in test1");
var x = new owned MyClass();
f(x); // f gets a borrow
writeln("back in test1");
writeln(x); // so x is not 'nil' at this point
}
Note
It is expected that this rule will change in the future with more experience with this language design.
-
record
owned
¶ owned
manages the deletion of a class instance assuming that thisowned
is the only thing responsible for managing the lifetime of the class instance.-
proc
init
(p: unmanaged) Initialize a
owned
with a class instance. When thisowned
goes out of scope, it will delete whatever class instance it is storing.It is an error to directly delete the class instance while it is managed by a
owned
.Arguments: p -- the class instance to manage. Must be of unmanaged class type.
-
proc
init
(p: ?T)
-
proc
init=
(ref src: owned)¶ Copy-initializer. Creates a new
owned
that takes over ownership from src. src will refer to nil after this call.
-
proc
deinit
()¶ The deinitializer for
owned
will destroy the class instance it manages when theowned
goes out of scope.
-
proc ref clear()
Empty this
owned
so that it stores nil. Deletes the previously managed object, if any.
-
proc ref retain(newPtr: unmanaged t)
Change the instance managed by this class to newPtr. If this record was already managing a non-nil instance, that instance will be deleted.
Here t refers to the object type managed by this
owned
.
-
proc ref release(): unmanaged t
Empty this
owned
so that it manages nil. Returns the instance previously managed by thisowned
.Here t refers to the object type managed by this
owned
.
-
proc
borrow
()¶ Return the object managed by this
owned
without impacting its lifetime at all. It is an error to use the value returned by this function after theowned
goes out of scope or deletes the contained class instance for another reason, such as with = or :proc`retain`. In some cases such errors are caught at compile-time.
-
proc
-
proc
=
(ref lhs: owned, ref rhs: owned)¶ Assign one
owned
to another. Deletes the object managed bylhs
, if any. Transfers ownership of the object managed byrhs
tolhs
, leavinglhs
storing nil.
-
type
Owned
= owned¶ This type allows code using the pre-1.18 Owned record to continue to compile. It will be removed in a future release.