192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//===----------------------------- test_guard.cpp -------------------------===//
292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//
392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//                     The LLVM Compiler Infrastructure
492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//
592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant// This file is dual licensed under the MIT and the University of Illinois Open
692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant// Source Licenses. See LICENSE.TXT for details.
792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//
892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant//===----------------------------------------------------------------------===//
992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
10e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#include "../src/config.h"
1192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant#include "cxxabi.h"
1292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
1392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant#include <cassert>
14e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert
15e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#if !LIBCXXABI_HAS_NO_THREADS
165dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky#include <thread>
17e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#endif
1892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
195dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Ensure that we initialize each variable once and only once.
2092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantnamespace test1 {
2192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    static int run_count = 0;
2292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    int increment() {
2392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        ++run_count;
2492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        return 0;
2592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
2692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void helper() {
2792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int a = increment();
2892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
2992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void test() {
3092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int a = increment();
3192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 1);
3292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int b = increment();
3392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 2);
3492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
3592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 3);
3692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
3792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 3);
3892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
3992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
4092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
415dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// When initialization fails, ensure that we try to initialize it again next
425dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// time.
4392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantnamespace test2 {
4492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    static int run_count = 0;
4592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    int increment() {
4692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        ++run_count;
4792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        throw 0;
4892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
4992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void helper() {
5092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        try {
5192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant            static int a = increment();
5292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant            assert(0);
5392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        } catch (...) {}
5492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
5592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void test() {
5692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
5792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 1);
5892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
5992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 2);
6092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
6192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
6292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
635dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Check that we can initialize a second value while initializing a first.
645dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test3 {
655dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int zero() {
665dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
675dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
685dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
695dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int one() {
705dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int b = zero();
715dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
725dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
735dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
745dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
755dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
765dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
775dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
785dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
79e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#if !LIBCXXABI_HAS_NO_THREADS
805dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// A simple thread test of two threads racing to initialize a variable. This
815dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// isn't guaranteed to catch any particular threading problems.
825dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test4 {
835dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    static int run_count = 0;
845dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int increment() {
855dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        ++run_count;
8625f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        return 0;
875dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
885dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
895dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void helper() {
905dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = increment();
915dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
925dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
935dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
945dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        std::thread t1(helper), t2(helper);
955dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t1.join();
965dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t2.join();
9725f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        assert(run_count == 1);
985dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
995dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
1005dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1015dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Check that we don't re-initialize a static variable even when it's
1025dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// encountered from two different threads.
1035dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test5 {
1045dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    static int run_count = 0;
1055dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int zero() {
1065dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        ++run_count;
1075dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
1085dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1095dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1105dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int one() {
1115dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int b = zero();
11225f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        return 0;
1135dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1145dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1155dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void another_helper() {
1165dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
1175dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1185dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1195dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void helper() {
1205dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
12125f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        std::thread t(another_helper);
12225f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        t.join();
1235dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1245dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1255dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
1265dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        std::thread t(helper);
1275dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t.join();
12825f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        assert(run_count == 1);
1295dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1305dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
131e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#endif /* LIBCXXABI_HAS_NO_THREADS */
1325dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
13392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantint main()
13492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant{
13592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    test1::test();
13692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    test2::test();
1375dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test3::test();
138e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#if !LIBCXXABI_HAS_NO_THREADS
1395dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test4::test();
1405dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test5::test();
141e571c0cb34dbc3799349cf2166fb422ff9d2c08dDan Albert#endif
14292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
143