Function IntrusivePtr.exchange

Stores the non shared IntrusivePtr pointer ptr in the shared(IntrusivePtr) pointed to by this and returns the value formerly pointed-to by this, atomically or with mutex.

IntrusivePtr exchange(MemoryOrder order = MemoryOrder.seq, This) (
  typeof(null)
) scope
if (isMutable!This);

IntrusivePtr exchange(MemoryOrder order = MemoryOrder.seq, Rhs, This) (
  scope Rhs ptr
) scope
if (isIntrusivePtr!Rhs && !is(Rhs == shared) && isMoveConstructable!(Rhs, This) && isMutable!This);

Examples

static struct Foo{
    ControlBlock!(int, int) c;
    int i;

    this(int i)pure nothrow @safe @nogc{
        this.i = i;
    }
}

//lvalue exchange
{
    shared x = IntrusivePtr!(shared Foo).make(123);
    auto y = IntrusivePtr!(shared Foo).make(42);

    auto z = x.exchange(y);

    assert(x.load.get.i == 42);
    assert(y.get.i == 42);
    assert(z.get.i == 123);
}

//rvalue exchange
{
    shared x = IntrusivePtr!(shared Foo).make(123);
    auto y = IntrusivePtr!(shared Foo).make(42);

    import core.lifetime : move;
    auto z = x.exchange(move(y));

    assert(x.load.get.i == 42);
    assert(y == null);
    assert(z.get.i == 123);
}

//null exchange (same as move)
{
    shared x = IntrusivePtr!(shared Foo).make(123);

    auto z = x.exchange(null);

    assert(x.load == null);
    assert(z.get.i == 123);
}

//swap:
{
    shared x = IntrusivePtr!(shared Foo).make(123);
    auto y = IntrusivePtr!(shared Foo).make(42);

    //opAssign is same as store
    import core.lifetime : move;
    y = x.exchange(move(y));

    assert(x.load.get.i == 42);
    assert(y.get.i == 123);
}