1. 12 Sep, 2017 7 commits
    • Alberto Schiabel's avatar
      Update String.h · 17fd438a
      Alberto Schiabel authored
      Summary:
      Fixed typo in doc comment related to `void toLowerAscii(char* str, size_t length)`.
      This fixes the annoying xCode's warning `Parameter 'len' not found in the function declaration`.
      Closes https://github.com/facebook/folly/pull/670
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5815034
      
      Pulled By: Orvid
      
      fbshipit-source-id: 9580cd0bbd4924d4ed461a5435f525316e5c285a
      17fd438a
    • Christopher Dykes's avatar
      Don't use std::void_t · d4bba1e7
      Christopher Dykes authored
      Summary: I was wrong, MSVC's implementation has the same bug as everything else.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5810646
      
      fbshipit-source-id: 9caabbbc2115f57b7e836bb85c9b108588c94ad9
      d4bba1e7
    • Martin Martin's avatar
      const -> constexpr in folly::small_vector · d3555e67
      Martin Martin authored
      Summary: const -> constexpr in folly::small_vector
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5814264
      
      fbshipit-source-id: 4631bb7f3f04906636e5a188d4aa0d33ad796a3c
      d3555e67
    • Philip Jameson's avatar
      Remove unneeded parts of build script · 053c0a86
      Philip Jameson authored
      Summary: Remove an unneeded autoconf flag, as it causes the build to fail on missing boost-context
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5815646
      
      fbshipit-source-id: cb6544593de9fbf8248506b09c56412b4635b30c
      053c0a86
    • Martin Martin's avatar
      clang-format folly::small_vector. No functional change. · 6f7b20b8
      Martin Martin authored
      Summary: clang-format folly::small_vector.  No functional change.
      
      Reviewed By: Orvid
      
      Differential Revision: D5808357
      
      fbshipit-source-id: d2ee831e25c60778c699214b875635c22854832d
      6f7b20b8
    • Jon Maltiel Swenson's avatar
      Make RequestContext provider overridable in order to save cost of setContext()... · 943afd98
      Jon Maltiel Swenson authored
      Make RequestContext provider overridable in order to save cost of setContext() on each fiber context switch
      
      Summary:
      Each fiber context switch currently involves the cost of saving/restoring `RequestContext`.  Certain
      fibers-based applications such as mcrouter don't use `RequestContext` at all, so updating the current
      thread-global `RequestContext` on each fiber context switch is unnecessary overhead.  Avoid this cost
      by allowing `FiberManager` to override the `RequestContext` provider at the start and end of each fiber drain
      loop.
      
      Reviewed By: andriigrynenko
      
      Differential Revision: D5787837
      
      fbshipit-source-id: ea9041ce228063c8701165366fd1e34132868d22
      943afd98
    • Christopher Dykes's avatar
      Fix CMake build · 14b06383
      Christopher Dykes authored
      Summary: Spookyhash got moved a long time ago, and a duplicate test name was added with the migration of executors from wangle to folly.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5811321
      
      fbshipit-source-id: 789b4d3187a2e1e21c6cf8297f733bb4dffdbd60
      14b06383
  2. 11 Sep, 2017 2 commits
    • Phil Willoughby's avatar
      Dead shift in ConcurrentHashMapSegment · d25d17e7
      Phil Willoughby authored
      Summary: Original problem detected by compiling with `-Werror,-Wunused-value`. On further inspection the only place which uses this detail class ensures that the `max_size` parameter is a power of two already, so we can discard the logic to manipulate `max_size` and put a `CHECK` clause in its place to guard against future changes to the caller that break this assumption.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5799110
      
      fbshipit-source-id: d21ed9ff196d54ef91e38254df8b1b88bbf29275
      d25d17e7
    • Anirudh Ramachandran's avatar
      Move SSL_CTX sessionContext initialization into main SSL_CTX initialization path · 001275d1
      Anirudh Ramachandran authored
      Summary: This field was only previously set if setupSessionCache was called on the wangle::ServerSSLContext
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5776057
      
      fbshipit-source-id: ecdbe83816fee2ecbe7ea1b26a67b682a571309a
      001275d1
  3. 10 Sep, 2017 2 commits
    • Giuseppe Ottaviano's avatar
      Add convenience std::string overload for toLowerAscii · d84e6482
      Giuseppe Ottaviano authored
      Summary:
      `toLowerAscii` is surprisingly hard to use with `std::string` because (until C++17) `data()` returns a `const char*`. In addition, it is not widely known that `s[0]` is legal even if the string is empty. This can lead to a variety of suboptimal code, from explicitly checking emptiness, to casting away the `const` (which causes UB).
      
      Let's just have a simple overload for it.
      
      Reviewed By: pixelb, philippv, yfeldblum
      
      Differential Revision: D5801970
      
      fbshipit-source-id: 407e2e9e66147a0662a5e09c75921255adff0702
      d84e6482
    • Giuseppe Ottaviano's avatar
      Fix typo in async/README.md · cb471a45
      Giuseppe Ottaviano authored
      Reviewed By: yfeldblum
      
      Differential Revision: D5802013
      
      fbshipit-source-id: 472b09da2be7234157a7886018004e2f4ed4f279
      cb471a45
  4. 08 Sep, 2017 3 commits
    • Benjamin Jaeger's avatar
      Optional.h - make == operators constexprs · 4b351b61
      Benjamin Jaeger authored
      Summary: This more closely matches std optional and allows folly Optional to be a drop in replacement.
      
      Reviewed By: aary, yfeldblum
      
      Differential Revision: D5775541
      
      fbshipit-source-id: f754c006429fa3c5a866b6b5ffdfd8883ec2dd4f
      4b351b61
    • Eric Niebler's avatar
      support using co_await with folly::Optional when it is available · d6217b2f
      Eric Niebler authored
      Summary:
      Coroutines can be used to simulate the monadic "do" notion of Haskell. Use coroutines to enable monadic composition with folly::Optional.
      
      ```
      Optional<int> f() {
        return 7;
      }
      Optional<int> g(int) {
        return folly::none;
      }
      
      void MonadicOptional() {
        Optional<int> r = []() -> Optional<int> {
          int x = co_await f();
          assert(x == 7);
          int y = co_await g(x);
          assert(false); // not executed
          co_return y;
        }();
        assert(!r.hasValue());
      }
      ```
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5763371
      
      fbshipit-source-id: 9babc682244f38da7006d0b3a8444fd4efec1747
      d6217b2f
    • Michael Bolin's avatar
      Grammar fix: s/it's/its/ · e74c15ff
      Michael Bolin authored
      Summary:
      I noticed this while reading the docs.
      
      (Note: this ignores all push blocking failures!)
      
      Reviewed By: lbrandy
      
      Differential Revision: D5795548
      
      fbshipit-source-id: 9ec5aa13a8913f217b3118e72714d02dc4a9407f
      e74c15ff
  5. 07 Sep, 2017 1 commit
    • Kenny Yu's avatar
      Fix data race in folly/executors/Codel.cpp exposed by TSAN · 88903796
      Kenny Yu authored
      Summary:
      I found a data race with TSAN while attempting to run a sanitizer version of my service:
      
      ```
      WARNING: ThreadSanitizer: data race (pid=266)
        Read of size 8 at 0x7b58000c0c08 by thread T370:
          @ folly::Codel::overloaded(std::chrono::duration<long, std::ratio<1l, 1000000000l> >) at ./folly/executors/Codel.cpp:44
          @ apache::thrift::concurrency::ThreadManager::ImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::Worker<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::run() at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:119
          @ apache::thrift::concurrency::PthreadThread::threadMain(void*) at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:200
          @ __tsan_thread_start_func at crtstuff.c:?
      
        Previous write of size 8 at 0x7b58000c0c08 by thread T371:
          @ folly::Codel::overloaded(std::chrono::duration<long, std::ratio<1l, 1000000000l> >) at ./folly/executors/Codel.cpp:62
          @ apache::thrift::concurrency::ThreadManager::ImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::Worker<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::run() at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:119
          @ apache::thrift::concurrency::PthreadThread::threadMain(void*) at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:200
          @ __tsan_thread_start_func at crtstuff.c:?
      
        Location is heap block of size 744 at 0x7b58000c0c00 allocated by thread T314:
          @ operator new(unsigned long) at ??:?
          @ PriorityImplT at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:826
          @ void __gnu_cxx::new_allocator<apache::thrift::concurrency::PriorityThreadManager::PriorityImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > > >::construct<apache::thrift::concurrency::PriorityThreadManager::PriorityImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >, std::array<std::pair<std::shared_ptr<apache::thrift::concurrency::ThreadFactory>, unsigned long>, 5ul>&, bool&, unsigned long&>(apache::thrift::concurrency::PriorityThreadManager::PriorityImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >*, std::array<std::pair<std::shared_ptr<apache::thrift::concurrency::ThreadFactory>, unsigned long>, 5ul>&, bool&, unsigned long&)
          @ std::shared_ptr<apache::thrift::concurrency::PriorityThreadManager> apache::thrift::concurrency::PriorityThreadManager::newPriorityThreadManager<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >(std::array<unsigned long, 5ul> const&, bool, unsigned long) at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:1090
          @ std::shared_ptr<apache::thrift::concurrency::PriorityThreadManager> apache::thrift::concurrency::PriorityThreadManager::newPriorityThreadManager<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >(unsigned long, bool, unsigned long) at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:1100
          @ apache::thrift::ThriftServer::serve() at ./thrift/lib/cpp2/server/ThriftServer.cpp:475
          @ apache::thrift::server::TServer::run() at ./thrift/lib/cpp/server/TServer.h:186
          @ apache::thrift::concurrency::PthreadThread::threadMain(void*) at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:200
          @ __tsan_thread_start_func at crtstuff.c:?
      
        Thread T370 (tid=638, running) created by thread T314 at:
          @ pthread_create at ??:?
          @ apache::thrift::concurrency::PthreadThread::start() at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:108
          @ apache::thrift::concurrency::ThreadManager::ImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::addWorker(unsigned long) at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:185
          @ apache::thrift::concurrency::PriorityThreadManager::PriorityImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::start() at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:840
          @ apache::thrift::ThriftServer::setup() at ./thrift/lib/cpp2/server/ThriftServer.cpp:347
          @ apache::thrift::ThriftServer::serve() at ./thrift/lib/cpp2/server/ThriftServer.cpp:475
          @ apache::thrift::server::TServer::run() at ./thrift/lib/cpp/server/TServer.h:186
          @ apache::thrift::concurrency::PthreadThread::threadMain(void*) at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:200
          @ __tsan_thread_start_func at crtstuff.c:?
      
        Thread T371 (tid=639, running) created by thread T314 at:
          @ pthread_create at ??:?
          @ apache::thrift::concurrency::PthreadThread::start() at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:108
          @ apache::thrift::concurrency::ThreadManager::ImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::addWorker(unsigned long) at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:185
          @ apache::thrift::concurrency::PriorityThreadManager::PriorityImplT<folly::LifoSemImpl<std::atomic, folly::Baton<std::atomic, true, true> > >::start() at ./thrift/lib/cpp/concurrency/ThreadManager.tcc:840
          @ apache::thrift::ThriftServer::setup() at ./thrift/lib/cpp2/server/ThriftServer.cpp:347
          @ apache::thrift::ThriftServer::serve() at ./thrift/lib/cpp2/server/ThriftServer.cpp:475
          @ apache::thrift::server::TServer::run() at ./thrift/lib/cpp/server/TServer.h:186
          @ apache::thrift::concurrency::PthreadThread::threadMain(void*) at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:200
          @ __tsan_thread_start_func at crtstuff.c:?
      
        Thread T314 (tid=582, running) created by main thread at:
          @ pthread_create at ??:?
          @ apache::thrift::concurrency::PthreadThread::start() at ./thrift/lib/cpp/concurrency/PosixThreadFactory.cpp:108
          ...
      ```
      
      Looks like there is a data race in how `codelMinDelay_` is used. I couldn't get `std::atomic` to compile with `std::chrono::nanoseconds`,
      so I used `std::atomic<uint64_t>` and converted between `uint64_t` and time types appropriately.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5759588
      
      fbshipit-source-id: 8213f3789808265ddfe5ab122f0f86490d0ea6ea
      88903796
  6. 06 Sep, 2017 1 commit
    • James Sedgwick's avatar
      move wangle/concurrent to folly/executors · af4a3352
      James Sedgwick authored
      Summary:
      For the initial cutover, just pull the copies in folly into the wangle namespace
      The main problem with that approach is that forward declarations of wangle components no longer work, so I fixed those manually
      
      ALSO, IMPORTANT: This is a great, once in a lifetime opportunity to rename/restructure these components. I have a few ideas that I'll noodle and share eventually, e.g. changing LifoSemMPMCQueue so it's just descriptive and not an enumeration of implementation details. Please chip in with yr ideas!
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5694213
      
      fbshipit-source-id: 4fc0ea9359d1216191676fc9729fb53a3f06339f
      af4a3352
  7. 05 Sep, 2017 1 commit
    • Stella Lau's avatar
      Compress empty strings with underlying compressor · 049fb12e
      Stella Lau authored
      Summary:
      - Current behavior compresses empty strings to empty strings. This is undesirable as decompression using underlying decompressor (side-stepping the codec) will fail. This change passes empty strings to the underlying compressor
      - Decompressing empty string -> empty string was kept for backwards compatibility
      - Fix `getUncompressedLength` for zlib
      
      Reviewed By: terrelln, yfeldblum
      
      Differential Revision: D5740034
      
      fbshipit-source-id: 5a747ea4963dad872103209aa4410197f6c605db
      049fb12e
  8. 02 Sep, 2017 1 commit
    • Yedidya Feldblum's avatar
      Fix constexpr_min after D5739715 · 4fd5e900
      Yedidya Feldblum authored
      Summary:
      [Folly] Fix `constexpr_min` after {D5739715} (facebook/folly@6d7c6d55f0f4b7b75607608ef9037db58083368f).
      
      Add new unit-tests for `constexpr_min` and `constexpr_max` to avoid silly mistakes like this in the future.
      
      It was defined recursively in terms of `constexpr_max` rather than, as intended, in terns of `constexpr_min`. HT Mandar12.
      
      Reviewed By: Orvid
      
      Differential Revision: D5761831
      
      fbshipit-source-id: 2dad5833e05679232b3c529d33325a0205c2e4e4
      4fd5e900
  9. 01 Sep, 2017 2 commits
    • Igor Sugak's avatar
      increase stack size when TSAN is enabled · 555494f0
      Igor Sugak authored
      Reviewed By: meyering
      
      Differential Revision: D5757469
      
      fbshipit-source-id: ad70c47251993c79a502d30f312534e28c9241d4
      555494f0
    • Kyle Nekritz's avatar
      Deflake some AsyncSSLSocket tests. · bb9a2237
      Kyle Nekritz authored
      Summary: Fulfilling starts destroying the evb in another thread which races with the socket closing on the evb.
      
      Reviewed By: siyengar, ngoyal
      
      Differential Revision: D5755271
      
      fbshipit-source-id: ace37eee63e684c97ca0fe503293eee83514e0ac
      bb9a2237
  10. 31 Aug, 2017 3 commits
    • Aravind Anbudurai's avatar
      Add a comment on File.h · e540cbee
      Aravind Anbudurai authored
      Summary: title
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5751299
      
      fbshipit-source-id: d3967c2499da9a2c98c2862b9bdc9994c12edc76
      e540cbee
    • Yedidya Feldblum's avatar
      Extract non-portability constexpr math functions to new header · 6d7c6d55
      Yedidya Feldblum authored
      Summary:
      [Folly] Extract non-portability `constexpr` math functions to new header.
      
      This new header, `folly/ConstexprMath.h`, is specifically for compile-time-computable math functions. We start with `min`, `max`, `abs`, and `log2`.
      
      Included substantive changes:
      * Add new tests for `constexpr_strlen`, which remains in the portability header.
      * Make `constexpr_min` and `constexpr_max` variadic.
      * Make `constexpr_log2` tail-recursive, remove `const_log2` in `FixedString.h`, and move the related comment.
      
      Reviewed By: Orvid
      
      Differential Revision: D5739715
      
      fbshipit-source-id: 29d3cc846ce98bb4bdddcc8b0fa80e4d32075fe0
      6d7c6d55
    • Philip Jameson's avatar
      Don't use symbolizer on OSX · 4717bdad
      Philip Jameson authored
      Summary:
      When trying to build with targets files on OSX, I couldn't use the symbolizer because it needs StackTrace, which requires libunwind and elf. This makes it so that we only build on linux for now. This also makes it so that we set FOLLY_USE_SYMBOLIZER in autoconf, since that wasn't set before.
      
      Does a few things surrounding usage of the symbolizer library:
      - Introduce FOLLY_USE_SYMBOLIZER in folly-config.h and USE_SYMBOLIZER as an AM definition
      -- Filter some code out of init and some other random libs that optionally need the symbolizer
      - Fix libdwarf detection. Previously on a fresh ubuntu container, we didn't find libdwarf/dwarf.h, so we stopped trying before looking at dwarf.h
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5644352
      
      fbshipit-source-id: f0a3580c41122e5e8fdfd17a9fdbb0921be21401
      4717bdad
  11. 30 Aug, 2017 6 commits
    • Michael Lee's avatar
      Include `<array>` for test · faa5f598
      Michael Lee authored
      Summary: <array> is sometimes necessary for using `std::array`. Fix up
      
      Reviewed By: aary
      
      Differential Revision: D5740866
      
      fbshipit-source-id: 13bafadd26fdd0f2eff3513115b43811682e7cda
      faa5f598
    • Aaryaman Sagar's avatar
      Conditionally compiled for_each with constexpr · f45b792f
      Aaryaman Sagar authored
      Summary:
      Code was breaking in versions of C++ where constexpr functions are
      required to have one line bodies
      
      Reviewed By: yfeldblum, mzlee
      
      Differential Revision: D5739062
      
      fbshipit-source-id: 6c509f1daf77751d33ce9c173a0d7f1d3bd2a006
      f45b792f
    • Maged Michael's avatar
      Dynamic MPMCQueue: Eliminate cases of enqueue indefinite blocking and failure... · 9ce176b1
      Maged Michael authored
      Dynamic MPMCQueue: Eliminate cases of enqueue indefinite blocking and failure in the extensible version that impossible under the default pre-allocated version
      
      Summary:
      Currently under the extensible version (Dynamic == true), some enqueue operations may block indefinitely or fail (return false) even though such outcomes are impossible under the default (Dynamic == false) pre-allocated version.
      
      This diff eliminates such cases by changing the algorithms for the extensible version. Some of the high-level changes:
      - The offset formula for an expansion guarantees that no enqueue operation left behind in a closed array does not have an existing dequeue operation that unblocks it. The old formula was 1 + max(head, tail). The new formula is max(head, current offset) + current capacity.
      - Conditional operations validate state after the success of CAS.
      
      Reviewed By: djwatson
      
      Differential Revision: D5701013
      
      fbshipit-source-id: 4917c5b35b7e2a2fddfd2e11fb5aeb478502137c
      9ce176b1
    • Yedidya Feldblum's avatar
      constexpr_log2 · f7ec2efe
      Yedidya Feldblum authored
      Summary:
      [Folly] `constexpr_log2`.
      
      Useful for anything that needs to compute log2 at compile time.
      
      Reviewed By: eduardo-elizondo
      
      Differential Revision: D5734727
      
      fbshipit-source-id: 8eab7991eea2104570eecd8e84ede6160bb0b549
      f7ec2efe
    • Yedidya Feldblum's avatar
      Shrink MicroSpinLock.h transitive includes and inline methods · 70137200
      Yedidya Feldblum authored
      Summary: [Folly] Shrink `MicroSpinLock.h` transitive includes and inline methods.
      
      Reviewed By: meyering
      
      Differential Revision: D5732693
      
      fbshipit-source-id: 386816f0d97c145ff8a4180d41c8a682694aa6cb
      70137200
    • Xiao Shi's avatar
      rm old comment on HHWheelTimer::UniquePtr · 985a7f47
      Xiao Shi authored
      Summary: This comment is outdated.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5730049
      
      fbshipit-source-id: f6088c4354210fafb019656cdf8246abf90fbc06
      985a7f47
  12. 29 Aug, 2017 7 commits
  13. 28 Aug, 2017 3 commits
    • Christopher Dykes's avatar
      Enable auto-deps in all of Folly · 2ccbaf9e
      Christopher Dykes authored
      Summary: This enables the last of the magic internally.
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5719795
      
      fbshipit-source-id: fb59a0d7873e9a9f3b73f556b42b647091ca7e67
      2ccbaf9e
    • Yedidya Feldblum's avatar
      Shrink MicroSpinLock.h transitive includes and inline methods · 053fb025
      Yedidya Feldblum authored
      Summary: [Folly] Shrink `MicroSpinLock.h` transitive includes and inline methods.
      
      Reviewed By: Orvid
      
      Differential Revision: D5714883
      
      fbshipit-source-id: 1744685ff9fa8d3620aef2545c8fe3ebc481df06
      053fb025
    • Patryk Zaryjewski's avatar
      Make cancelling and rescheduling of functions O(1) · 951a822c
      Patryk Zaryjewski authored
      Summary: Currently FunctionScheduler calls that cancel/restart timer for a function of particular id are O(n). By introducing hashmap that translate id to pointer of particular RepeatFunc, we make it O(1).
      
      Reviewed By: simpkins
      
      Differential Revision: D5668557
      
      fbshipit-source-id: e5e8bf9bd75b6d5d42f0bfa398d476703e5801fa
      951a822c
  14. 25 Aug, 2017 1 commit
    • Aaryaman Sagar's avatar
      gcc 6.2 was not accepting the current definition of void_t · db9fd491
      Aaryaman Sagar authored
      Summary:
      The current definition of void_t was leading to errors because unused
      template parameters are ignored and SFINAE SFIAEs
      
      Reviewed By: yfeldblum
      
      Differential Revision: D5700825
      
      fbshipit-source-id: d23336070c217e8594980d6db710cb417b014236
      db9fd491