Relax HHWheelTimer::destroy assertion to accommodate SharedPtr
authorAlan Frindell <afrind@fb.com>
Tue, 9 Feb 2016 17:44:21 +0000 (09:44 -0800)
committerfacebook-github-bot-4 <folly-bot@fb.com>
Tue, 9 Feb 2016 18:20:27 +0000 (10:20 -0800)
commit5e5cf95a1602ea0edafbc2f04a9ae03ec611007f
treefe0e494caf9656b38b7c3492d23ebf12b9540260
parent785485183fec26c5902cb035ff17bbe5f3fe6513
Relax HHWheelTimer::destroy assertion to accommodate SharedPtr

Summary:
HHWheelTimer's auto-pointers are kind of funny.  You can do something like this:

```
HHWheelTimer::UniquePtr p = ...;
// create a SharedPtr from UniquePtr
HHWheelTimer::SharedPtr s(p);
// create another SharedPtr from raw ptr
HHWheelTimer::SharedPtr s(p.get());
// No problem.

If you do this:

HHWheelTimer::SharedPtr p = ....;
// this leaks
```

Why?  Because SharedPtr is only have of std::shared_ptr.  It's the refcounting half.  But when the last SharedPtr goes out of scope, it **does not** invoke HHWheelTimer::destroy().

So code like this is possible/expected:

```
MySweetObj::MySweetObj(HHWheelTimer::SharedPtr s) {
  s_ = s;
  s_.scheduleTimeout(a, b);
}

{
  HHWheelTimer::UniquePtr p = ...;

  obj = MySweetObj(p)

  // But what if I decide to kill p:
  p.reset();
}
```

Since MySweetObj takes a SharedPtr and holds it, it can reasonbly expect that it can schedule timeouts on it, and the HHWheelTimer will not be deleted until it releases the SharedPtr.  This is true, but the above code would hit the assert that count_ == 0.

Instead, relase the check that count_ == 0 only if there are no extra outstanding SharedPtrs.

Reviewed By: viswanathgs, chadparry

Differential Revision: D2908729

fb-gh-sync-id: 9abd4a7d692fe952c5514dbb8d85dfbad95a3cac
shipit-source-id: 9abd4a7d692fe952c5514dbb8d85dfbad95a3cac
folly/io/async/HHWheelTimer.cpp
folly/io/async/HHWheelTimer.h
folly/io/async/test/HHWheelTimerTest.cpp