PSA: Introducing base::RetainedRef for scoped_refptrs in base::Bind

85 views
Skip to first unread message

Vladimir Levin

unread,
Mar 22, 2016, 7:14:45 PM3/22/16
to Chromium-dev, Nico Weber, Taiju Tsuiki
Hi,

TL;DR

If you're passing a scoped_refptr to base::Bind, and the bound function expects a raw non-owning pointer, then you will need to wrap the scoped_refptr in base::RetainedRef.

void DoStuff(Foo* foo) {}

scoped_refptr<Foo> foo;
base::Bind(&DoStuff, foo);  // ERROR!
base::Bind(&DoStuff, base::RetainedRef(foo));  // OK

Details

As we starting working towards making scoped_refptr constructor explicit (crbug.com/589048), we found that a large portion of implicit scoped_refptr construction was happening in base::Bind

That is, base::Bind would always unwrap scoped_refptrs into the underlying raw pointer and pass that to the bound function. However, if the bound function expected a scoped_refptr, then one would be created implicitly. 

In order to avoid this, base::Bind will no longer unwrap scoped_refptrs (as of https://codereview.chromium.org/1816713002/). The only case where this breaks existing code is when a scoped_refptr was being passed, but the function expected a raw non-owning pointer.

Enter base::RetainedRef. This retains a reference to the passed pointer (much like scoped_refptr would). The only difference is that this pointer will be unwrapped and passed as a raw pointer to the bound function.

To summarize in code,

void WantsScopedRefptr(scoped_refptr<Foo> foo) {}
void WantsRawPointer(Foo* foo) {}

scoped_refptr<Foo> refptr;
Foo* rawptr;

// OK: passed scoped_refptr, expects scoped_refptr
base::Bind(&WantsScopedRefptr, refptr);

// ERROR: passing a raw pointer of a ref counted object.
base::Bind(&WantsScopedRefptr, rawptr);

// ERROR: Can't convert refptr to a raw pointer.
base::Bind(&WantsRawPointer, refptr);

// OK: refptr will be unwrapped
base::Bind(&WantsRawPointer, base::RetainedRef(refptr));

Thanks,
Vlad




Reply all
Reply to author
Forward
0 new messages