brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.1 KiB · bc6c301 Raw
134 lines · cpp
1//===----------------------------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// UNSUPPORTED: no-threads10 11// This test occasionally fails on Android.12// UNSUPPORTED: LIBCXX-ANDROID-FIXME13 14// <condition_variable>15 16// class condition_variable;17 18// void notify_one();19 20 21// NOTE: `notify_one` is just a wrapper around pthread_cond_signal, but22// POSIX does not guarantee that one and only one thread will be woken:23//24// https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_signal.html25//26// Quote:27//     Multiple Awakenings by Condition Signal28//     On a multi-processor, it may be impossible for an implementation of29//     pthread_cond_signal() to avoid the unblocking of more than one thread30//     blocked on a condition variable. For example...31 32 33 34// NOTE: In previous versions of this test, `notify_one` was called WITHOUT35// holding the lock but POSIX says (in the aforementioned URL) that:36//     ...if predictable scheduling behavior is required, then that mutex shall37//     be locked by the thread calling pthread_cond_broadcast() or38//     pthread_cond_signal().39 40 41#include <condition_variable>42#include <atomic>43#include <mutex>44#include <thread>45#include <cassert>46 47#include "make_test_thread.h"48#include "test_macros.h"49 50 51std::condition_variable cv;52std::mutex mut;53 54std::atomic_int test1(0);55std::atomic_int test2(0);56std::atomic_int ready(2);57std::atomic_int which(0);58 59void f1()60{61  std::unique_lock<std::mutex> lk(mut);62  assert(test1 == 0);63  --ready;64  while (test1 == 0)65    cv.wait(lk);66  which = 1;67  assert(test1 == 1);68  test1 = 2;69}70 71void f2()72{73  std::unique_lock<std::mutex> lk(mut);74  assert(test2 == 0);75  --ready;76  while (test2 == 0)77    cv.wait(lk);78  which = 2;79  assert(test2 == 1);80  test2 = 2;81}82 83int main(int, char**)84{85  std::thread t1 = support::make_test_thread(f1);86  std::thread t2 = support::make_test_thread(f2);87  {88    while (ready > 0)89      std::this_thread::yield();90    // At this point:91    // 1) Both f1 and f2 have entered their condition variable wait.92    // 2) Either f1 or f2 has the mutex locked and is about to wait.93    std::unique_lock<std::mutex> lk(mut);94    test1 = 1;95    test2 = 1;96    ready = 1;97    cv.notify_one();98  }99  {100    while (which == 0)101      std::this_thread::yield();102    std::unique_lock<std::mutex> lk(mut);103    if (test1 == 2) {104      assert(test2 == 1);105      t1.join();106      test1 = 0;107    } else {108      assert(test1 == 1);109      assert(test2 == 2);110      t2.join();111      test2 = 0;112    }113    which = 0;114    cv.notify_one();115  }116  {117    while (which == 0)118      std::this_thread::yield();119    std::unique_lock<std::mutex> lk(mut);120    if (test1 == 2) {121      assert(test2 == 0);122      t1.join();123      test1 = 0;124    } else {125      assert(test1 == 0);126      assert(test2 == 2);127      t2.join();128      test2 = 0;129    }130  }131 132  return 0;133}134