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