TearableTest.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. /*
  2. * Copyright 2018-present Facebook, Inc.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. #include <folly/synchronization/Tearable.h>
  17. #include <atomic>
  18. #include <thread>
  19. #include <folly/portability/GTest.h>
  20. using namespace folly;
  21. namespace {
  22. struct Data {
  23. Data(unsigned char value) {
  24. setValue(value);
  25. }
  26. void setValue(unsigned char value) {
  27. for (auto& item : contents) {
  28. item = value;
  29. }
  30. }
  31. void checkValue(unsigned char value) {
  32. for (auto& item : contents) {
  33. ASSERT_EQ(value, item);
  34. }
  35. }
  36. void checkValue2(unsigned char value1, unsigned char value2) {
  37. for (auto& item : contents) {
  38. ASSERT_TRUE(item == value1 || item == value2);
  39. }
  40. }
  41. // Note the odd size -- this will hopefully expose layout bugs under
  42. // sanitizers.
  43. unsigned char contents[99];
  44. };
  45. static_assert(is_trivially_copyable<Data>::value, "not trivially-copyable");
  46. TEST(TearableTest, BasicOperations) {
  47. Tearable<Data> tearable;
  48. Data src(0);
  49. Data dst(1);
  50. for (char c = 0; c < 10; ++c) {
  51. src.setValue(c);
  52. tearable.store(src);
  53. tearable.load(dst);
  54. dst.checkValue(c);
  55. }
  56. }
  57. TEST(TearableTest, Races) {
  58. std::atomic<bool> stop(false);
  59. Tearable<Data> tearable(Data(1));
  60. std::thread write1([&]() {
  61. Data data0(1);
  62. while (!stop.load(std::memory_order_relaxed)) {
  63. tearable.store(data0);
  64. }
  65. });
  66. std::thread write2([&]() {
  67. Data data1(2);
  68. while (!stop.load(std::memory_order_relaxed)) {
  69. tearable.store(data1);
  70. }
  71. });
  72. Data val(0);
  73. for (int i = 0; i < 100 * 1000; ++i) {
  74. tearable.load(val);
  75. val.checkValue2(1, 2);
  76. }
  77. stop.store(true, std::memory_order_relaxed);
  78. write1.join();
  79. write2.join();
  80. }
  81. } // namespace