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
1092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant#include "cxxabi.h"
1192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
1292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant#include <cassert>
135dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky#include <thread>
1492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
155dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Ensure that we initialize each variable once and only once.
1692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantnamespace test1 {
1792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    static int run_count = 0;
1892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    int increment() {
1992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        ++run_count;
2092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        return 0;
2192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
2292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void helper() {
2392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int a = increment();
2492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
2592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void test() {
2692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int a = increment();
2792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 1);
2892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        static int b = increment();
2992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 2);
3092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
3192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 3);
3292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
3392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 3);
3492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
3592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
3692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
375dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// When initialization fails, ensure that we try to initialize it again next
385dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// time.
3992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantnamespace test2 {
4092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    static int run_count = 0;
4192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    int increment() {
4292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        ++run_count;
4392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        throw 0;
4492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
4592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void helper() {
4692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        try {
4792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant            static int a = increment();
4892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant            assert(0);
4992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        } catch (...) {}
5092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
5192827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    void test() {
5292827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
5392827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 1);
5492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        helper();
5592827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant        assert(run_count == 2);
5692827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    }
5792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
5892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant
595dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Check that we can initialize a second value while initializing a first.
605dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test3 {
615dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int zero() {
625dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
635dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
645dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
655dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int one() {
665dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int b = zero();
675dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
685dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
695dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
705dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
715dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
725dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
735dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
745dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
755dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// A simple thread test of two threads racing to initialize a variable. This
765dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// isn't guaranteed to catch any particular threading problems.
775dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test4 {
785dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    static int run_count = 0;
795dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int increment() {
805dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        ++run_count;
8125f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        return 0;
825dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
835dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
845dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void helper() {
855dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = increment();
865dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
875dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
885dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
895dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        std::thread t1(helper), t2(helper);
905dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t1.join();
915dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t2.join();
9225f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        assert(run_count == 1);
935dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
945dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
955dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
965dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// Check that we don't re-initialize a static variable even when it's
975dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky// encountered from two different threads.
985dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewyckynamespace test5 {
995dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    static int run_count = 0;
1005dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int zero() {
1015dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        ++run_count;
1025dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        return 0;
1035dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1045dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1055dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    int one() {
1065dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int b = zero();
10725f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        return 0;
1085dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1095dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1105dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void another_helper() {
1115dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
1125dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1135dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1145dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void helper() {
1155dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        static int a = one();
11625f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        std::thread t(another_helper);
11725f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        t.join();
1185dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1195dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
1205dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    void test() {
1215dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        std::thread t(helper);
1225dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky        t.join();
12325f180797ba296e6cd3aa45e1fef9321b828301aHoward Hinnant        assert(run_count == 1);
1245dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    }
1255dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky}
1265dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky
12792827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnantint main()
12892827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant{
12992827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    test1::test();
13092827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant    test2::test();
1315dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test3::test();
1325dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test4::test();
1335dfef8de38c88d0bbccdb0b0f86a696f6d53dba8Nick Lewycky    test5::test();
13492827189cbb1e63dfebf0a46aac4372c3089ff11Howard Hinnant}
135