Add runtime functions to "pin" a native Swift object.

Pinning an object prevents it from being deallocated,
just like retaining it, but only one client can own the
pin at once.  Sensible "sharing" of the pin can occur
if attempts are perfectly nested.  It is efficient to
simultaneously query the pin state of an object in
conjunction with its strong reference count.

This combination of traits makes pinning suitable for
use in tracking whether a data structure backed by
an object is undergoing a non-structural modification:

- A structural change would require unique ownership
  of the object, but two non-structural changes (to
  different parts of the object) can occur at once
  without harm.  So a non-structural change can check
  for either uniqueness or a pin and then, if necessary,
  assert the pin for the duration of the change.
  Meanwhile, this act of asserting the pin prevents
  simultaneous structural changes.

- A very simple code-generation discipline leads to
  changes being perfectly nested as long as they're
  all performed by a single thread (or synchronously).
  Asynchrony can introduce imperfect nesting, but it's
  easy to write that off as a race condition and hence
  undefined behavior.

See Accessors.rst for more on both of these points.

Swift SVN r23761
This commit is contained in:
John McCall
2014-12-06 09:46:01 +00:00
parent 147fb8790a
commit 3f46b30ca4
5 changed files with 160 additions and 23 deletions

View File

@@ -302,6 +302,26 @@ void swift::swift_weakRelease(HeapObject *object) {
}
}
HeapObject *swift::swift_tryPin(HeapObject *object) {
if (!object) return nullptr;
// Try to set the flag. If this succeeds, the caller will be
// responsible for clearing it.
if (object->refCount.tryIncrementAndPin()) {
return object;
}
// If setting the flag failed, it's because it was already set.
// Return nil so that the object will be deallocated later.
return nullptr;
}
void swift::swift_unpin(HeapObject *object) {
if (object && object->refCount.decrementAndUnpinShouldDeallocate()) {
_swift_release_dealloc(object);
}
}
HeapObject *swift::swift_tryRetain(HeapObject *object) {
return _swift_tryRetain(object);
}