Skip to content

[libc++] Refactor the tests for mutex, recursive mutex and their timed counterparts #104852

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads

// <mutex>

// class mutex;

// mutex& operator=(const mutex&) = delete;

#include <mutex>
#include <type_traits>

int main(int, char**)
{
std::mutex m0;
std::mutex m1;
m1 = m0;

return 0;
}
static_assert(!std::is_copy_assignable<std::mutex>::value, "");
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads

// <mutex>

// class mutex;

// mutex(const mutex&) = delete;

#include <mutex>
#include <type_traits>

int main(int, char**)
{
std::mutex m0;
std::mutex m1(m0);

return 0;
}
static_assert(!std::is_copy_constructible<std::mutex>::value, "");
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,28 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

// UNSUPPORTED: no-threads

// <mutex>

// class mutex;

// mutex();
// mutex() noexcept;

#include <mutex>
#include <cassert>
#include <type_traits>

#include "test_macros.h"
static_assert(std::is_nothrow_default_constructible<std::mutex>::value, "");

int main(int, char**) {
// The mutex is unlocked after default construction
{
std::mutex m;
assert(m.try_lock());
m.unlock();
}

int main(int, char**)
{
static_assert(std::is_nothrow_default_constructible<std::mutex>::value, "");
std::mutex m;
((void)m);
return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,77 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

// UNSUPPORTED: c++03
// UNSUPPORTED: no-threads
// ALLOW_RETRIES: 2

// <mutex>

// class mutex;

// void lock();

#include <cassert>
#include <chrono>
#include <cstdlib>
#include <mutex>
#include <atomic>
#include <cassert>
#include <thread>
#include <vector>

#include "make_test_thread.h"
#include "test_macros.h"

std::mutex m;

typedef std::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef std::chrono::milliseconds ms;
typedef std::chrono::nanoseconds ns;

void f()
{
time_point t0 = Clock::now();
int main(int, char**) {
// Lock a mutex that is not locked yet. This should succeed.
{
std::mutex m;
m.lock();
time_point t1 = Clock::now();
m.unlock();
ns d = t1 - t0 - ms(250);
assert(d < ms(50)); // within 50ms
}
}

int main(int, char**)
{
// Lock a mutex that is already locked. This should block until it is unlocked.
{
std::atomic<bool> ready(false);
std::mutex m;
m.lock();
std::thread t = support::make_test_thread(f);
std::this_thread::sleep_for(ms(250));
std::atomic<bool> is_locked_from_main(true);

std::thread t = support::make_test_thread([&] {
ready = true;
m.lock();
assert(!is_locked_from_main);
m.unlock();
});

while (!ready)
/* spin */;

// We would rather signal this after we unlock, but that would create a race condition.
// We instead signal it before we unlock, which means that it's technically possible for
// the thread to take the lock while main is still holding it yet for the test to still pass.
is_locked_from_main = false;
m.unlock();

t.join();
}

// Make sure that at most one thread can acquire the mutex concurrently.
{
std::atomic<int> counter(0);
std::mutex mutex;

std::vector<std::thread> threads;
for (int i = 0; i != 10; ++i) {
threads.push_back(support::make_test_thread([&] {
mutex.lock();
counter++;
assert(counter == 1);
counter--;
mutex.unlock();
}));
}

for (auto& t : threads)
t.join();
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,54 +5,46 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

// UNSUPPORTED: c++03
// UNSUPPORTED: no-threads
// ALLOW_RETRIES: 2

// <mutex>

// class mutex;

// bool try_lock();

#include <cassert>
#include <chrono>
#include <cstdlib>
#include <mutex>
#include <cassert>
#include <thread>

#include "make_test_thread.h"
#include "test_macros.h"

std::mutex m;

typedef std::chrono::system_clock Clock;
typedef Clock::time_point time_point;
typedef Clock::duration duration;
typedef std::chrono::milliseconds ms;
typedef std::chrono::nanoseconds ns;

void f()
{
time_point t0 = Clock::now();
assert(!m.try_lock());
assert(!m.try_lock());
assert(!m.try_lock());
while(!m.try_lock())
;
time_point t1 = Clock::now();

int main(int, char**) {
// Try to lock a mutex that is not locked yet. This should succeed.
{
std::mutex m;
bool succeeded = m.try_lock();
assert(succeeded);
m.unlock();
ns d = t1 - t0 - ms(250);
assert(d < ms(200)); // within 200ms
}
}

int main(int, char**)
{
// Try to lock a mutex that is already locked. This should fail.
{
std::mutex m;
m.lock();
std::thread t = support::make_test_thread(f);
std::this_thread::sleep_for(ms(250));
m.unlock();

std::thread t = support::make_test_thread([&] {
for (int i = 0; i != 10; ++i) {
bool succeeded = m.try_lock();
assert(!succeeded);
}
});
t.join();

m.unlock();
}

return 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,15 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads

// <mutex>

// class recursive_mutex;

// recursive_mutex& operator=(const recursive_mutex&) = delete;

#include <mutex>
#include <type_traits>

int main(int, char**)
{
std::recursive_mutex m0;
std::recursive_mutex m1;
m1 = m0;

return 0;
}
static_assert(!std::is_copy_assignable<std::recursive_mutex>::value, "");
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,15 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads

// <mutex>

// class recursive_mutex;

// recursive_mutex(const recursive_mutex&) = delete;

#include <mutex>
#include <type_traits>

int main(int, char**)
{
std::recursive_mutex m0;
std::recursive_mutex m1(m0);

return 0;
}
static_assert(!std::is_copy_constructible<std::recursive_mutex>::value, "");
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

// UNSUPPORTED: no-threads

// <mutex>
Expand All @@ -15,12 +15,16 @@
// recursive_mutex();

#include <mutex>
#include <cassert>
#include <type_traits>

#include "test_macros.h"

int main(int, char**)
{
int main(int, char**) {
// The mutex is unlocked after default construction
{
std::recursive_mutex m;
assert(m.try_lock());
m.unlock();
}

return 0;
}
Loading
Loading