Fix ShutdownLock logic
Fix ShutdownLock logic

Summary:
This fixes a potential deadlock if we try to obtain a ShutdownLock while
another thread already initiated the shutdown.
The new logic is:
1. Atomically set shutdownStarted_ to true (this prevents new readers from obtaining the lock)
2. Wait for all readers to drain (via obtaining a write lock)
3. Run func()

Test Plan: unit tests

Reviewed By: andrii@fb.com

Subscribers: alikhtarov

FB internal diff: D1740713

Tasks: 5819935

reddit/mcrouter,facebook/mcrouter,synecdoche/mcrouter,apinski-cavium/mcrouter,easyfmxu/mcrouter,glensc/mcrouter,reddit/mcrouter,nvaller/mcrouter,is00hcw/mcrouter,facebook/mcrouter,easyfmxu/mcrouter,zhlong73/mcrouter,evertrue/mcrouter,tempbottle/mcrouter,synecdoche/mcrouter,evertrue/mcrouter,seem-sky/mcrouter,yqzhang/mcrouter,glensc/mcrouter,facebook/mcrouter,evertrue/mcrouter,leitao/mcrouter,glensc/mcrouter,reddit/mcrouter,nvaller/mcrouter,easyfmxu/mcrouter,leitao/mcrouter,yqzhang/mcrouter,apinski-cavium/mcrouter,tempbottle/mcrouter,yqzhang/mcrouter,nvaller/mcrouter,is00hcw/mcrouter,zhlong73/mcrouter,leitao/mcrouter,zhlong73/mcrouter,is00hcw/mcrouter,facebook/mcrouter,apinski-cavium/mcrouter,leitao/mcrouter,easyfmxu/mcrouter,zhlong73/mcrouter,synecdoche/mcrouter,seem-sky/mcrouter,yqzhang/mcrouter,evertrue/mcrouter,nvaller/mcrouter,tempbottle/mcrouter,is00hcw/mcrouter,seem-sky/mcrouter,seem-sky/mcrouter,tempbottle/mcrouter,apinski-cavium/mcrouter,glensc/mcrouter,synecdoche/mcrouter,reddit/mcrouter