ãã®ããŒãžã¯C++20ã«æ¡çšãããèšèªæ©èœã®å€æŽã解説ããŠããŸãã
ã®ã¡ã®C++èŠæ Œã§ããã«å€æŽãããå Žåãããããé¢é£é ç®ãåç §ããŠãã ããã
æŠèŠ
C++20ãããvolatileã®æ¬æ¥ã®åœ¹å²ã«ç
§ãããŠäžæ£ç¢ºããããã¯èª€è§£ãæãçšæ³ãç¡æå³ãªçšæ³ã«ã€ããŠéæšå¥šãšãããããã«ãªãã
éæšå¥šãšãªãã®ã¯æ¬¡ã®ãã®
volatileå€ã«å¯Ÿããè€åä»£å ¥æŒç®åïŒç®è¡åã»ãã€ã³ã¿åã®ã¿ïŒ- C++23ã§éæšå¥šåè§£é€
volatileå€ã«å¯Ÿããã€ã³ã¯ãªã¡ã³ãïŒãã¯ãªã¡ã³ãæŒç®åïŒç®è¡åã»ãã€ã³ã¿åã®ã¿ïŒ- éã«
volatileå€ãããå Žåã®é£éããä»£å ¥æŒç®åïŒéã¯ã©ã¹åã®ã¿ïŒ - 颿°åŒæ°ã®ãããã¬ãã«
volatile修食 - 颿°æ»ãå€åã®ãããã¬ãã«
volatile修食 - æ§é åæçžå®£èšã®
volatile修食 std::tuple, std::varianté¢é£ã®ã¯ã©ã¹ãã³ãã¬ãŒãã®volatileç¹æ®å- ããã¯ããªãŒã§ã¯ãªã
std::atomicç¹æ®åã®volatileã¡ã³ã颿°
éæšå¥šãšãããã ãã§åé€ãããŠã¯ããªãããããããã³ã³ãã€ã©ã¯ãããã®çšæ³ã«ã€ããŠèŠåãçºããããã«ãªãããã®ãããªçšæ³ã¯ãã°ã®åå ãšãªãå±éºã§ããããå¯èœãªéã䜿çšãé¿ããã¹ãã§ããã
volatile
volatileãªå€æ°ïŒã¡ã¢ãªé åïŒãžã®1床ã®ã¢ã¯ã»ã¹ã¯æ£ç¢ºã«1床ã ãè¡ãããå¿
èŠãããã0åã«ã2å以äžã«ããªã£ãŠã¯ãªããªãããããŠãvolatileé åãžã®ã¢ã¯ã»ã¹ã¯ãã®é åºãã³ãŒãäžã®é åºãšäžèŽããå¿
èŠãããã
volatileã®å¹æïŒä¿èšŒïŒã¯åçŽã«ã¯ããã ãã§ããã
ãã ããvolatileã¯ãã®ãããªã¡ã¢ãªã¢ã¯ã»ã¹ãåå²ãããªãäºã¯ä¿èšŒããŠããªããvolatileã¡ã¢ãªé åã®åã
ã®ãã€ãã«å¯ŸããŠã¯æ£ç¢ºã«1床ã®ã¢ã¯ã»ã¹ãä¿èšŒãããããvolatileé åå
šäœãèŠããšãã«ã¢ã¯ã»ã¹ã1床ã ãã«ãªããšã¯éããªãã
ãããŠãévolatileé åãšvolatileé åãžã®ã¢ã¯ã»ã¹ã®éã®çžå¯Ÿçãªé åºãååŸããªãäºãŸã§ä¿èšŒããŠããªããããªãã¡ãvolatile倿°ãžã®ã¢ã¯ã»ã¹ãšéåžžã®å€æ°ãžã®ã¢ã¯ã»ã¹ã¯é çªãå
¥ãæ¿ããããã
ãŸããvolatileã¯ãã«ãã¹ã¬ããããã°ã©ã ã®å®è¡é ãèŠå®ããC++ã¡ã¢ãªã¢ãã«ãšã¯çŽæ¥çãªé¢ä¿æ§ãæãããvolatileé åãžã®ã¢ã¯ã»ã¹é åºãšã¯C++ã¡ã¢ãªã¢ãã«ã«ããã芳枬å¯èœãªé åºãæå³ããªããããã»ããµã¯C++ã³ãŒãäžã§ã®é åºã§èªã¿åã£ãvolatileé åãžã®ã¢ã¯ã»ã¹åœä»€ããã¢ãŠããªããªãŒããŒã§çºè¡ã»å®è¡ããããšãã§ãããC++ã¡ã¢ãªã¢ãã«ã«ãããŠåäœãä¿èšŒãããŠããåææ©æ§ãçšããªãå Žåãããã³ã¢ã«ãããåœä»€ã®å®è¡é ã¯ãä»ã®ã³ã¢ïŒãããã¯ããã»ããµã®å€éšïŒããã¯ç°ãªã£ãé åºã§å®è¡ããããã®ããã«èŠ³æž¬ããããã
volatileã¯äž»ãšããŠãããã°ã©ã ã®å®è¡ç°å¢ã®ããŒããŠã§ã¢ãªã©ã®ããã°ã©ã å€éšã®ç°å¢ãšã®éä¿¡ææ®µã®äžã€ãšããŠå©çšãããã¹ã¬ããéã®ãããšããªã©ããã°ã©ã å
éšã§ã®éä¿¡ã®ææ®µãšããŠã¯é©ããªãããã®ãããªvolatileã®æ£ããçšæ³ã«ããã¡ã¢ãªã®èªã¿æžãã¯ãä»ã®ã©ã®ææ®µãããç§»æ€æ§ãããæ©èœçã«ãåªããŠãããèšèªæ©èœãšããŠæçšãªãã®ã§ããã
ã³ã¢èšèªã«ãããéæšå¥šå
è€åä»£å ¥æŒç®åãã€ã³ã¯ãªã¡ã³ãæŒç®å
è€å代å
¥æŒç®åãšã¯*= /= %= += -= >>= <<= &= ^= |=ã®10åã®æŒç®åã®ããšã§ãããæäœãšãã®çµæã®ä»£å
¥ããŸãšããŠè¡ããããªæŒç®åã®ããšã§ããã
è€å代å
¥æŒç®åããã³ã€ã³ã¯ãªã¡ã³ãæŒç®å++ãšãã¯ãªã¡ã³ãæŒç®å--ã¯ããèªã¿åºã - æŽæ°ïŒåŠçïŒ - æžã蟌ã¿ããšãã3ã€ã®æäœã1æã§è¡ããïŒç°¡çŽ åã®ããã以éã¯++/--ããŸãšããŠã€ã³ã¯ãªã¡ã³ãæŒç®åãšè¡šèšãããïŒ
volatile int a = 0;
int b = 10;
a += b;
// ããã¯ä»¥äžãšç䟡
// int tmp = a;
// a = tmp + b;
++a;
// int tmp = a;
// a = tmp + 1;
a--;
// int tmp = a;
// a = tmp - 1;
è€å代å
¥æŒç®åã®å·ŠèŸºã«ããvolatile倿°ãããã³ã€ã³ã¯ãªã¡ã³ãæŒç®åã®volatileãªãã©ã³ãã«ã¯2åã®ã¢ã¯ã»ã¹ïŒèªã¿èŸŒã¿ãšæžã蟌ã¿1åã¥ã€ïŒãçºçãããããã®ã¢ã¯ã»ã¹ã¯è€å代å
¥æŒç®åãã€ã³ã¯ãªã¡ã³ãæŒç®åã®èŠãç®ãäžè¬çãªçè§£ãšã¯å¿
ãããäžèŽããªãã
volatile倿°ã«ãããŠã¯ãã®ã¢ã¯ã»ã¹ïŒèªã¿æžãïŒãéèŠã§ãããã³ãŒãäžã§ã®1åã®ã¢ã¯ã»ã¹ã¯å®è¡æã«ã1åã ãã¢ã¯ã»ã¹ãããå¿
èŠããããããããè€å代å
¥æŒç®åããã³ã€ã³ã¯ãªã¡ã³ãæŒç®åã®ã¢ã¯ã»ã¹åæ°ã¯å€ãã®ããã°ã©ãã«ãšã£ãŠææ§ã§ãããã誀解ãããŠããã
åŸã£ãŠãç®è¡åã»ãã€ã³ã¿åã®volatile倿°ã«å¯Ÿããçµã¿èŸŒã¿ã®è€å代å
¥æŒç®åããã³ã€ã³ã¯ãªã¡ã³ãæŒç®åã®äœ¿çšã¯ãã°ã®å
ã§ããã®ã§ãéæšå¥šãšãããã
ãã®å Žåããããã®è€åçãªæŒç®åãçšãããæç€ºçã«ãèªã¿åºã - æŽæ° - æžã蟌ã¿ããåããŠæžãããšã§volatile倿°ãžã®ã¢ã¯ã»ã¹ãã³ãŒãäžã§ãæç¢ºã«ããäºãæšå¥šãããã
ãã ããè€åä»£å ¥æŒç®åã«ã€ããŠã¯C++23ã§éæšå¥šåãè§£é€ãããã
é£éããä»£å ¥æŒç®å
ä»£å ¥æŒç®åã®äžéšã®çšæ³ã«ã¯ãè€åä»£å ¥æŒç®åã»ã€ã³ã¯ãªã¡ã³ãæŒç®åãšåæ§ã®åé¡ãããã
volatile int a, b, c;
a = b = c = 10;
// ãã®ãããªé åºã§ã¢ã¯ã»ã¹ãçºçãã
// c = 10;
// b = c;
// a = b;
ãã®ãããªé£ãªã£ãä»£å ¥æŒç®åã®çšæ³ã«ãããŠã¯ãã©ã®å€æ°ã«ã©ããªé çªã§äœåã¢ã¯ã»ã¹ãããã®ããéåžžã«åããã¥ãããªãã
volatile倿°ã«ãããŠã¯ãã®ã¢ã¯ã»ã¹ïŒèªã¿æžãïŒãéèŠã§ãããã³ãŒãäžã§ã®1åã®ã¢ã¯ã»ã¹ã¯å®è¡æã«ã1åã ãã¢ã¯ã»ã¹ããããã€ãã®é çªãååŸããŠã¯ãªããªãããããã代å
¥æŒç®åãé£éãããå Žåããã®ã¢ã¯ã»ã¹åæ°ããã³é åºã¯éåžžã«èªèãã¥ãããªãã
åŸã£ãŠãéã¯ã©ã¹åã®volatile倿°ã«å¯Ÿãããã®ãããªä»£å
¥æŒç®åã®äœ¿çšã¯ãã°ã®å
ã§ããã®ã§ãéæšå¥šãšãããã
ãã ããéæšå¥šãšãªãã®ã¯ä»£å
¥æŒç®åã®äž¡ç«¯ã®ãªãã©ã³ã以å€ã«volatile倿°ã衚ããã±ãŒã¹ã§ããã
volatile int v1, v2, v3;
v1 = v2 = v3 = 10; // NGïŒéæšå¥šïŒ
int n;
v1 = n = 10; // OK
v1 = n = v3 = 10; // NGïŒéæšå¥šïŒ
v3 = 10; // OK
v1 = v3; // OK
v1 = n = v3; // OK
颿°åŒæ°ãšæ»ãå€å
颿°åŒæ°ãvolatile修食ããããšã¯ãã·ã°ãã«ãsetjmp/longjmpã«ãã£ãŠå€éšãã倿ŽãããŠããå¯èœæ§ã瀺åããããã«æå¹ã§ãããåŒæ°ã®constä¿®é£Ÿåæ§ã«é¢æ°å®çŸ©å
ã§ã¯æç¢ºãªæå³ãæã€ã
äžæ¹åŒã³åºãåŽããèŠããšãåç
§ã»ãã€ã³ã¿ã§ã¯ãªãvolatileåŒæ°ã®æå³ã¯äžæçã§ãããåç
§ã»ãã€ã³ã¿ã§ã¯ãªã颿°åŒæ°ãvolatile修食ãããŠããå Žåããã®é¢æ°ã¯ã·ã°ãã«ãã³ãã©ãsetjmp/longjmpãšå
±ã«äœ¿çšãããã¯ãã§ãããåŒã³åºãåŽã«ããã®ãããªå®è£
詳现ã®äžéšãæŒæŽ©ããŠããŸãã
ãŸããåŒåºèŠçŽã«ãã£ãŠã¯äžéšã®åŒæ°ãé
眮ããã¬ãžã¹ã¿ãvolatileãšãªãäºãããããåŒåºèŠçŽã¯C++ã³ãŒãäžã§æå³ãæããããã®ãããªåŒã³åºãèŠçŽãããŒã¯ãããŠãã颿°ã¯évolatile颿°å®£èšãšåæ§ã«æ±ããããããããäžéšã®ã¬ãžã¹ã¿ãvolatileã§ããäºã¯ABIã«ãã£ãŠåŠçãããŠããã
ãã®ããã«ã颿°åŒæ°ã®volatileä¿®é£Ÿã¯æçšã§ã¯ãªãããéæšå¥šãšãããã颿°ã®åŒæ°ãvolatileãšãããå Žåã颿°å
ã§volatileããŒã«ã«å€æ°ã«åŒæ°ãã³ããŒããäºãæšå¥šããããäžéšã®å®è£
ã§ã¯ããã®ãããªã³ããŒã¯çç¥ããããªãŒããŒããããšã¯ãªããªãã
void f1(volatile int n); // NGïŒéæšå¥šïŒ
void f2(volatile int* p); // OK
void f3(volatile int& r); // OK
void f4(int volatile * p); // OK
void f5(int volatile & r); // OK
void f6(int * volatile p); // NGïŒéæšå¥šïŒ
ãŸããåç
§ã»ãã€ã³ã¿ã§ã¯ãªã颿°æ»ãå€åã®volatile修食ã¯å®å
šã«æå³ãæããªãã
äŸãã°ãããŒã«ã«volatile倿°ãè¿ãå Žåããã®ã¢ã¯ã»ã¹ã¯é¢æ°ãªã¿ãŒã³æã«å€ãã³ããŒããããã«äžåºŠå®è¡ãããããã³ããŒããåŸã®å€ã¯ãã¯ãå
ã®volatileé åãšã¯å¥ã®ã¹ã¿ãã¯é åã«ãããvolatileã«ãããŠéèŠãªã®ã¯ç¹å®é åãžã®ã¢ã¯ã»ã¹ã§ãããæé»ã«ãã®ãããªã³ããŒãè¡ãããäºã¯ã»ãšãã©ã®å Žåã«ããã°ã©ãã®æå³ãšã¯ç°ãªãã
ããŒã«ã«ã®évolatile倿°ãvolatileãšããŠè¿ãããšã«ã¯æå³ããªããæ»ãå€ãvolatileé åã«é
眮ãããå Žåã颿°ã®åŒã³åºãåŽã§volatile倿°ã«åããã°ããã
ãããŠãæ»ãå€åã®volatile修食ã¯å®¹æã«ç¡èŠããäºãã§ããã
ãã®ããã«ãvolatileæ»ãå€åã¯ç¡æå³ã§ãããããéæšå¥šãšããããæ»ãå€ãvolatileãšããŠæ±ãããå Žåã¯ãæ»ãå€ãvolatile倿°ã«åããã°ããã
volatile int f1(); // NGïŒéæšå¥šïŒ
volatile int* f2(); // OK
volatile int& f3(); // OK
int volatile* f4(); // OK
int volatile& f5(); // OK
int* volatile f6(); // NGïŒéæšå¥šïŒ
ãã ãã颿°åŒæ°ã»æ»ãå€åãããã«ããŠãããã€ã³ã¿ã»åç
§ãžã®volatileä¿®é£Ÿã¯æç¢ºãªæå³ãæã¡æçšã§ããïŒå€ã§ã¯ãªããé åã«volatileãšããŒã¯ããŠããããïŒãåŸã£ãŠãéæšå¥šãšãããã®ã¯é¢æ°åŒæ°ã»æ»ãå€åãžã®ãããã¬ãã«volatile修食ã®ã¿ã§ãã£ãŠãvolatileãã€ã³ã¿ã»åç
§åã¯äŸç¶ãšããŠèš±å¯ãããã
æ§é åæçžå®£èš
æ§é åæçžå®£èšã«ãvolatile修食ãè¡ãäºãã§ããããããã§ã®CV修食ã¯å³èŸºã«ããåŒã®çµæã§ããæé»ã®ãªããžã§ã¯ãã«å¯ŸããŠäœçšããŠããã
å³èŸºã®åŒã®çµæãstd::tuple/std::pairçã®tuple-likeãªåã®ãªããžã§ã¯ãã§ããå Žåãæ§é åæçžã¯ãŸããã®çµæãªããžã§ã¯ããvolatile修食ããŠåããŠããããã®çµæãªããžã§ã¯ãã«å¯ŸããŠstd::getã§èŠçŽ ã®ååŸãè¡ããããããstd::getã«ã¯volatileãªãŒããŒããŒããæ¬ ããŠãããã³ã³ãã€ã«ãšã©ãŒãèµ·ããã
äžæ¹ãæ§é åæçžã®æ®ãã®ã±ãŒã¹ïŒé
åã»æ§é äœïŒã®å Žåã¯std::getãçšããªããããã®ãããªåé¡ã¯èµ·ãããªãã
auto f() -> std::tuple<int, int, double>;
volatile auto [a, b, c] = f(); // NG
// ããã§ã¯ä»¥äžã®æ§ãªäºãè¡ãããŠãã
// volatile auto tmp = f();
// std::tuple_element_t<0, decltype(tmp)> a = std::get<0>(tmp);
int array[3]{};
volatile auto [a, b, c] = array; // OK
// ããã§ã¯ä»¥äžã®æ§ãªäºãè¡ãããŠãã
// volatile int tmp[] = {array[0], array[1], array[2]};
// volatile int a = tmp[0];
static_assert(std::is_volatile_v<decltype(a)>); // OK
ãã®ãããªæåã®éäžè²«æ§ãåãå
¥ãããšããŠããæ§é åæçžã®è£ã§è¡ãããŠããäºãvolatileã«ã¯é©ããŠããªãã
æ§é åæçžã®volatile修食ã¯ãã®å³èŸºã«ããæé»ã®ãªããžã§ã¯ãã«å¯ŸããŠè¡ããããããã®äºã¯æ§æããã¯å®å
šã«é èœãããŠãããå³èŸºã®åŒã®çµæãªããžã§ã¯ããå Žåã«ãã£ãŠã³ããŒããããåç
§ã®ãŸãŸå©çšãããããšãæ±ããå€åãããããŸããæ§é åæçžå®£èšã«æå®ãã倿°åã¯ã³ã³ãã€ã©ã®æ±ããšããŠã¯å€æ°åã§ã¯ãªããå³èŸºã®æé»ã®ãªããžã§ã¯ãå
ã®å¯Ÿå¿ããèŠçŽ ã«ãã€ã³ããããååã§ãããªãããã®ãããªååã«å¯Ÿããvolatileã®å¹æã¯äžæçã§ãããæçžå
ã®èŠçŽ ã®åãvolatileã§ã¯ãªãå Žåã«ã¯æå³ããªããªãã
volatileã«ãããŠã¯ãã®é åãžã®ã¢ã¯ã»ã¹ãéèŠã§ããã1床ã®ã¢ã¯ã»ã¹ã¯æ£ç¢ºã«1床ã ãè¡ãããå¿
èŠãããããã®é åºã¯ååŸããŠã¯ãªããªããæ§é åæçžå®£èšã¯ãã®è£åŽã§å€ãã®äºãè¡ãããŠãããããã¯CVã»åç
§ä¿®é£Ÿãšå³èŸºã®åŒã®çµæåã«ãã£ãŠæ§ã
ã«å€åããããããã§ã©ã®ãªããžã§ã¯ããvolatileãšãªãã©ã®ãããªé çªã§ã¢ã¯ã»ã¹ãçºçããã®ãã¯éåžžã«äžæçã§ããã
åŸã£ãŠãæ§é åæçžå®£èšã®volatileä¿®é£Ÿãæ£ããæ±ãäºã¯éåžžã«å°é£ã§ãããããéæšå¥šãšãããã
æ§é åæçžããååãvolatileã§ããå¿
èŠãããå Žåã¯ãå解察象ã®å³èŸºã®çµæãªããžã§ã¯ãã®åèŠçŽ åããããããvolatile修食ããŠããäºãæšå¥šãããã
auto f() -> std::tuple<int, int, double>;
int array[3]{};
volatile auto [a, b, c] = f(); // NGïŒéæšå¥šïŒ
volatile auto [a, b, c] = array; // NGïŒéæšå¥šïŒ
auto g() -> std::tuple<volatile int*, volatile int*, volatile double&>;
auto [a, b, c] = g(); // OK
ãã®å Žåã§ããåèŠçŽ åã®ãããã¬ãã«volatileä¿®é£Ÿã¯æå³ããªããªãã
auto f() -> std::tuple<volatile int, volatile int, volatile double>;
auto [a, b, c] = f(); // OKãèŠçŽ ããšã³ããŒãããŠãããvolatile修食ã¯ç¡æå³
auto&& [a, b, c] = f(); // OKãäžæãªããžã§ã¯ãå
åèŠçŽ ãžã®ãã€ã³ããvolatile修食ã¯ç¡æå³
ã©ã€ãã©ãªã«ãããéæšå¥šå
ã¯ã©ã¹ãã³ãã¬ãŒãã®volatileãªç¹æ®å
æšæºã©ã€ãã©ãªã®ã¯ã©ã¹ãã³ãã¬ãŒãã«ã¯ãvolatileãªå¯Ÿè±¡ã«å¯Ÿããç¹æ®åãæäŸãããŠãããã®ãããã
numeric_limitsatomicé¢é£tuple_sizetuple_elementvariant_sizevariant_alternative
ãã®ãã¡ãnumeric_limitsã«é¢ããŠã¯æçšæ§ãæããã§ããã®ã§ãã®ãŸãŸã«ãããatomicé¢é£ã®ãã®ã¯ããšã§èª¬æããã
æ®ã£ãã®ã¯tupleãšvariantã«é¢é£ãããã®ã§ããããC++æšæºã¯tupleãšvariantãã©ã®ããã«å®è£
ãããããæå®ããŠãããããããã®åã®volatileãªããžã§ã¯ããžã®ã¢ã¯ã»ã¹ãã©ã®ããã«æ¯ãèãã®ãã¯äžéæã§ãããããã«ãã¡ã³ã颿°ã¯ç¹ã«volatile修食ããããã®ãçšæãããŠããããã§ã¯ãªããæšæºã©ã€ãã©ãªã®ãã®ã»ãã®ã¯ã©ã¹ãç¹ã«volatileãæèããŠã¯ããªãã
åŸã£ãŠãtupleãšvariantãã®ãã®ã¯volatileã§äœ¿çšãããããã«èšèšãããŠããããããã4ã€ã®ã¯ã©ã¹ãã³ãã¬ãŒãã®volatileç¹æ®åã¯CV修食ãç¶²çŸ
ããããã«çšæãããŠããã ãã§ãããããéæšå¥šãšãããã
std::atomicã®volatileã¡ã³ã颿°
volatileãªã¢ã¯ã»ã¹ã¯äžå¯åã§ã¯ãªããé åºä¿èšŒããªããåãã€ãã«æ£ç¢ºã«äžåºŠã ãã¢ã¯ã»ã¹ãããã³ã³ãã€ã©ã®æé©åã®å¯Ÿè±¡ãšãªããªãã
atomicãªã¢ã¯ã»ã¹ã¯äžå¯åã§ããïŒååæ§ãä¿èšŒããïŒãC++ã¡ã¢ãªã¢ãã«ã«ãã£ãŠãã®é åºãä¿èšŒãããã«ãŒãã«ãã£ãŠåŠçãããå¯èœæ§ãããïŒåãã€ãäžåºŠã ãã®ã¢ã¯ã»ã¹ã¯ä¿èšŒãããªãïŒãã³ã³ãã€ã©ã®æé©åã®å¯Ÿè±¡ãšãªãããã
volatile std::atomic<T>ã¯ãããã®æ§è³ªãçµã¿åããããã®ãšãªãäºãæåŸ
ããããããããªã£ãŠããªãã
ããã¯ããªãŒã§ã¯ãªãstd::atomicãvolatile修食ãããŠããå Žåããã®ã¢ã¯ã»ã¹ã®äžå¯åæ§ïŒååæ§ïŒãå¿
ãããä¿èšŒãããªããäŸãã°ãC++ããã°ã©ã äžã§ã¯mutexãªã©ã§ããã¯ããŠæ£ããatomicã«ã¢ã¯ã»ã¹ãããŠãããšããŠãããã®é åã«ã¢ã¯ã»ã¹ããããã°ã©ã å€éšã®èŠ³æž¬è
ããã¯ãã®ã¢ã¯ã»ã¹ã¯åå²ãããŠèŠãããã
ãŸããvolatileãã€atomicãªè€å代å
¥æäœãæ£ããè¡ãïŒäžå¯åã«ãåãã€ãã«æ£ç¢ºã«äžåºŠã ãã¢ã¯ã»ã¹ããïŒå®è£
ã¯éãããŠãããããã®ãããªå®è£
詳现ãæå®ããããšã¯C++æšæºã®ç¯å²å
ã§ã¯ãªãã
åŸã£ãŠãvolatile std::atomic<T>ã¯å¿
ãããäž¡æ¹ã®æ§è³ªãåããå®è£
ã«ãªã£ãŠãããããããä¿èšŒããäºãå°é£ã§ãããããstd::atomic<T>::is_always_lock_freeãtrueãšãªãç¹æ®åãé€ããŠstd::atomicã®volatileã¡ã³ã颿°ã¯éæšå¥šãšãããã
æ€èšãããã»ãã®éžæè¢
颿°åŒæ°ã»æ»ãå€åãžã®const修食
颿°åŒæ°ã»æ»ãå€åãžã®volatile修食ãéæšå¥šãšãããã®ãšã»ãŒåæ§ã®çç±ã«ãã£ãŠãconst修食ãéæšå¥šãšããäºãææ¡ãããŠããããåæãåããªãã£ãããéæšå¥šãšã¯ãªããªãã£ãã
ãããããééã£ãŠãããæå³ããªãã£ããšããŠããvolatileãšæ¯ã¹ãŠå¹
åºã䜿çšãããŠããããã«éæšå¥šãšããäºãå¿é¿ããããã®ãšæãããã
ã¡ã³ã颿°ã®volatile修食
ã¡ã³ã颿°ã®volatile修食ã¯é垞䜿çšãããããšã¯ãªããæšæºã©ã€ãã©ãªã«ãããŠããconstã¡ã³ã颿°ã¯æå³ãæã£ãŠçšæãããäºãããäžæ¹ã§ãvolatileã¡ã³ã颿°ãçšæãããããšã¯ã»ãšãã©ãªãã
ãŸããã¡ã³ã颿°ã®volatile修食ã¯ãžã§ããªãã¯ããã°ã©ãã³ã°ã«ãããŠã¯CV修食ã®ãã¿ãŒã³ç¶²çŸ
ã®ããã«è¿œå ã®è² æ
ããããããå
šãç¡èŠããããã®ã©ã¡ããã§ããã
ã¯ã©ã¹ã¯constãªæèã§ãããã§ãªãæèã§ã䜿çšå¯èœã§ãããconstã¡ã³ã颿°ã¯ããããã®å Žåã«åãããŠãã®æ¯ãèããå€åãããäºãã§ãããvolatileã®å ŽåãèããŠã¿ããšãããã¯åœãŠã¯ãŸããªãã
ããã¯ã©ã¹ãvolatileãªé åã«é
眮ãããããšãããã°ããã§ãªãå Žåãããããšããç¶æ³ã¯èãã¥ããããã®ãããªç¶æ³ã«ãã£ããšããŠãã¡ã³ã颿°ãã©ãææçŸ©ã«ç°ãªãã®ãã¯ããã«äžæçã§ããã
ããã«ãã³ã³ã¹ãã©ã¯ã¿ããã¹ãã©ã¯ã¿ã¯constãvolatile修食ãã§ããªããããã¯ã©ã¹ã®ãªããžã§ã¯ããžã®volatileæ§ãæå¹ã«ãªãã®ã¯æŽŸçå
ãå«ããŠã³ã³ã¹ãã©ã¯ã¿ã®åŒã³åºããå®äºããåŸãããšãªãïŒåæ§ã«ãvolatileæ§ã¯ãã¹ãã©ã¯ã¿ã®åŒã³åºãåãŸã§ããæå¹ã§ã¯ãªãïŒã
volatileã«ãããŠã¯ãã®é åãžã®ã¢ã¯ã»ã¹ãéèŠã§ããã1床ã®ã¢ã¯ã»ã¹ã¯æ£ç¢ºã«1床ã ãè¡ãããå¿
èŠãããããã®é åºã¯ååŸããŠã¯ãªããªããã¯ã©ã¹ã®ãªããžã§ã¯ããvolatileãªé åã«é
眮ããããšããvolatileã®ä¿èšŒãªãã§æ§ç¯ãç Žæ£ãããããšã¯ééã£ãŠãããã¯ã©ã¹ãªããžã§ã¯ããvolatileãªé åã«é
眮ãããå Žåã¯ããã®ã¡ã³ã倿°ãvolatile修食ããŠããäºãæãŸããã
ãã®ããã«ãã¡ã³ã颿°ã®volatile修食ã¯ç¡æå³ãªãã®ã§ããã䜿çšãããŠããªããããéæšå¥šãšããäºãææ¡ãããŠããã
ããããéæäœã®ãããªåçŽãªã¯ã©ã¹åã«ãããŠã¯ãã¯ã©ã¹ãªããžã§ã¯ãã®volatileé åãžã®é
眮ãšã¡ã³ã颿°ã®volatile修食ã¯äœ¿çšãããŠãããããã«å¯ŸåŠããããã«åœåã®ææ¡ã§ã¯ãã¡ã³ã颿°ã®volatile修食ã¯ããããªããã©ã¡ãããšãããstruct volatileãå°å
¥ããããªã©ã®åé¿æ¡ãææ¡ããŠããã
ãŸããstd::atomicã¯æå³ãæã£ãŠvolatile修食ãããã¡ã³ã颿°ãæäŸããŠãããããã¯æçšã§ããããããããéæšå¥šãšããŠããŸããã©ãããåé¡ãšãªã£ãã
çµå±ãåæã«è³ãããšã¯ã§ãããã¡ã³ã颿°ã®volatile修食ã¯çŸç¶ç¶æãšãªã£ãã
åè
éæšå¥šåã§è§ŠããããŠã¯ããªãããvolatile倿°ã䞊è¡åŠçã®å
±æå€æ°ãšããŠäœ¿çšããããšã¯åžžã«ééã£ãŠããã
äžé©åãªäœ¿çšã®äŸ
ææ¡ææžããäžé©åãšæãããvolatileã®çšäŸãããã€ãåŒçšãããäžã«ã¯ä»åã®éæšå¥šåã®å¯Ÿè±¡ãšãªã£ãŠããªããã®ãããã
struct foo {
int a : 4;
int b : 2;
};
volatile foo f;
// ã©ããªåœä»€ãçæãããfã®é åã®åãã€ãã«äœåã¢ã¯ã»ã¹ãããäžéæ
f.a = 3;
struct foo {
volatile int a : 4;
int b : 2;
};
foo f;
// f.aã®é åãžã®ã¢ã¯ã»ã¹ãçºçãããäžéæ
f.b = 1;
union foo {
char c;
int i;
};
volatile foo f;
// sizeof(int) [byte]ã®é åãžã¢ã¯ã»ã¹ããããsizeof(char) [byte]ã®é åãžã¢ã¯ã»ã¹ããã®ããäžéæ
f.c = 42;
volatile int i;
// iã®é åãžäœåã®ã¢ã¯ã»ã¹ãçºçãããäžéæ
// ããã¯ã©ã¡ããéæšå¥šå
i += 42; // C++23ã§éæšå¥šåè§£é€
++i;
volatile int i, j, k;
// iãžã®ä»£å
¥æã«jã®å€ãèªã¿åããäžéæïŒéæšå¥šåïŒ
i = j = k;
struct big { int arr[32]; };
volatile _Atomic struct big ba;
struct big b2;
// 誰ããèŠãŠãatomicã«ãªããšã¯éããªã
// ã»ãšãã©ã®ç°å¢ã§éæšå¥šå
ba = b2;
int what(volatile std::atomic<int> *atom) {
int expected = 42;
// ãã®æäœã§atomã®æãé åã«äœåã¢ã¯ã»ã¹ãçºçããã®ãäžéæïŒå Žåã«ãã£ãŠå€åããïŒ
atom->compare_exchange_strong(expected, 0xdead);
return expected;
}
// ãã®é¢æ°ãåŒã³åºããšããåŒã³åºãåŽã¯äœãæ°ã«ãã¹ããäžéæ
void what_does_the_caller_care(volatile int);
// ç¡æå³ïŒéæšå¥šåïŒ
volatile int nonsense(void);
struct retme { int i, j; };
// ç¡æå³ïŒéæšå¥šåïŒ
volatile struct retme silly(void);
struct device {
unsigned reg;
device() : reg(0xc0ffee) {}
~device() { reg = 0xdeadbeef; }
};
// åæåïŒã³ã³ã¹ãã©ã¯ã¿å
ïŒãç Žæ£ïŒãã¹ãã©ã¯ã¿å
ïŒã¯ãšãã«volatileã§ã¯ãªã
volatile device dev;
åç §
- P1152R0 Deprecating
volatile - P1152R1 Deprecating
volatile - P1152R2 Deprecating
volatile - P1152R4 Deprecating
volatile - P1831R0 Deprecating
volatile: library - P1831R1 Deprecating
volatile: library - P2327R1 De-deprecating volatile compound operations
- CWG Issue 2654. Un-deprecation of compound volatile assignments