#include <avr/cpufunc.h>
#include <util/atomic.h>
#include <stdint.h>

struct Barrier final {
  inline Barrier() {
    _MemoryBarrier();
  }
  inline ~Barrier() {
    _MemoryBarrier();
  }
};

void barrier(const auto f) {
  Barrier b;
  f();
}

struct DisableInterruptsRestore final {
  inline DisableInterruptsRestore() {
    cli();
  }
  inline ~DisableInterruptsRestore() {
    SREG = save;
  }
  private:
    uint8_t save{SREG};
};

void access(const auto f) {
  DisableInterruptsRestore di;
  barrier([&] {
    f();
  });
}

uint8_t g;
bool flag;

ISR(TCA1_CMP0_vect) {
  barrier([] {
    ++g;
    if (g > 100) flag = true;
  });
}

int main(void) {
  while (true) {
    access([]{
      if (flag) {
        flag = false;
      }
    });
  }
}

########################################################

00000304 <__ctors_end>:
 304:	11 24       	eor	r1, r1
 306:	1f be       	out	0x3f, r1	; 63
 308:	cf ef       	ldi	r28, 0xFF	; 255
 30a:	cd bf       	out	0x3d, r28	; 61
 30c:	df e7       	ldi	r29, 0x7F	; 127
 30e:	de bf       	out	0x3e, r29	; 62

00000310 <__do_clear_bss>:
 310:	20 e4       	ldi	r18, 0x40	; 64

00000312 <.Loc.1>:
 312:	a0 e0       	ldi	r26, 0x00	; 0

00000314 <.Loc.2>:
 314:	b0 e4       	ldi	r27, 0x40	; 64

00000316 <.Loc.3>:
 316:	01 c0       	rjmp	.+2      	; 0x31a <.Loc.5>

00000318 <.Loc.4>:
 318:	1d 92       	st	X+, r1

0000031a <.Loc.5>:
 31a:	a2 30       	cpi	r26, 0x02	; 2

0000031c <.Loc.6>:
 31c:	b2 07       	cpc	r27, r18

0000031e <.Loc.7>:
 31e:	e1 f7       	brne	.-8      	; 0x318 <.Loc.4>

00000320 <L0^A>:
 320:	13 d0       	rcall	.+38     	; 0x348 <main>
 322:	1b c0       	rjmp	.+54     	; 0x35a <_exit>

00000324 <__bad_interrupt>:
 324:	6d cf       	rjmp	.-294    	; 0x200 <__vectors>

00000326 <__vector_49>:
}

uint8_t g;
bool flag;

ISR(TCA1_CMP0_vect) {
 326:	8f 93       	push	r24
 328:	8f b7       	in	r24, 0x3f	; 63
 32a:	8f 93       	push	r24

0000032c <.LBB10>:
  barrier([] {
    ++g;
 32c:	80 91 01 40 	lds	r24, 0x4001	; 0x804001 <g>
 330:	8f 5f       	subi	r24, 0xFF	; 255
 332:	80 93 01 40 	sts	0x4001, r24	; 0x804001 <g>

00000336 <.Loc.7>:
    if (g > 100) flag = true;
 336:	85 36       	cpi	r24, 0x65	; 101
 338:	18 f0       	brcs	.+6      	; 0x340 <.L2>

0000033a <.Loc.8>:
 33a:	81 e0       	ldi	r24, 0x01	; 1
 33c:	80 93 00 40 	sts	0x4000, r24	; 0x804000 <flag>

00000340 <.L2>:
  });
}
 340:	8f 91       	pop	r24
 342:	8f bf       	out	0x3f, r24	; 63
 344:	8f 91       	pop	r24
 346:	18 95       	reti

00000348 <main>:
  inline DisableInterruptsRestore() {
 348:	8f b7       	in	r24, 0x3f	; 63

0000034a <.LVL4>:
    cli();
 34a:	f8 94       	cli

0000034c <.LBB40>:

int main(void) {
  while (true) {
    access([]{
      if (flag) {
 34c:	90 91 00 40 	lds	r25, 0x4000	; 0x804000 <flag>
 350:	91 11       	cpse	r25, r1

00000352 <.Loc.27>:
        flag = false;
 352:	10 92 00 40 	sts	0x4000, r1	; 0x804000 <flag>

00000356 <.LBB48>:
    SREG = save;
 356:	8f bf       	out	0x3f, r24	; 63

00000358 <.LBE36>:
  while (true) {
 358:	f7 cf       	rjmp	.-18     	; 0x348 <main>

0000035a <_exit>:
 35a:	f8 94       	cli

0000035c <__stop_program>:
 35c:	ff cf       	rjmp	.-2      	; 0x35c <__stop_program>
