// File: ArnaudBienner[P]ExecuteAround/main.cpp
// Function: main
int main() {
  // 1) Simple example
  {
    std::cout << "Example 1: " << std::endl;
    int nb_call_before = 0;

    ExecuteAround<A, std::shared_ptr, std::function<void()>, std::function<void()>>
     execute_around(new A, std::bind(call_before, std::ref(nb_call_before)) , call_after);

    execute_around->f();

    execute_around->f();
  }

  // 2) Making all calls to a class threadsafe
  {
    std::cout << std::endl << "Example 2:" << std::endl;

    // Dummy mutex class
    struct Mutex {
      void lock() {
        std::cout << "dummy lock" << std::endl;
      }

      void unlock() {
        std::cout << "dummy unlock" << std::endl;
      }
    };

    Mutex mutex;
    ExecuteAround<A, std::shared_ptr, std::function<void()>, std::function<void()>>
      execute_around(new A, std::bind(&Mutex::lock, &mutex), std::bind(&Mutex::unlock, &mutex));
    execute_around->f();

    std::cout << std::endl << "Example2 with two calls in one expression:" << std::endl;

    // Warning! Mutex should be recursive for the next line to
    // work. Because the temporary object that will call "unlock"
    // upon destruction will still exists when the second call
    // to another execute_around class member will be called
    // (which makes a call to "lock")
    int res = execute_around->g() + execute_around->g();
    std::cout << "result: " << res << std::endl;
  }

}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x3d0, %rsp            # imm = 0x3D0
movq 0x5ce6(%rip), %rdi      # 0x7fd8
leaq 0x2de4(%rip), %rsi      # 0x50dd
callq 0x2090
movq %rax, %rdi
movq 0x5cb8(%rip), %rsi      # 0x7fc0
callq 0x20b0
movl $0x0, -0x4(%rbp)
movl $0x1, %edi
callq 0x20a0
movq %rax, -0x340(%rbp)
leaq -0x4(%rbp), %rdi
callq 0x3060
movq %rax, -0x90(%rbp)
leaq -0xec(%rip), %rsi       # 0x2250
leaq -0x88(%rbp), %rdi
movq %rdi, -0x348(%rbp)
leaq -0x90(%rbp), %rdx
callq 0x3020
movq -0x348(%rbp), %rsi
leaq -0x78(%rbp), %rdi
movq %rdi, -0x338(%rbp)
callq 0x3090
leaq -0xc4(%rip), %rsi       # 0x22b0
leaq -0xb0(%rbp), %rdi
movq %rdi, -0x330(%rbp)
callq 0x3130
movq -0x340(%rbp), %rsi
movq -0x338(%rbp), %rdx
movq -0x330(%rbp), %rcx
leaq -0x58(%rbp), %rdi
callq 0x31c0
jmp 0x23a7
leaq -0xb0(%rbp), %rdi
callq 0x3260
leaq -0x78(%rbp), %rdi
callq 0x3260
leaq -0x108(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x3280
jmp 0x23ce
leaq -0x108(%rbp), %rdi
callq 0x3340
movq %rax, -0x350(%rbp)
jmp 0x23e3
movq -0x350(%rbp), %rdi
callq 0x3360
jmp 0x23f1
leaq -0x108(%rbp), %rdi
callq 0x33a0
leaq -0x150(%rbp), %rdi
leaq -0x58(%rbp), %rsi
callq 0x3280
jmp 0x240f
leaq -0x150(%rbp), %rdi
callq 0x3340
movq %rax, -0x358(%rbp)
jmp 0x2424
movq -0x358(%rbp), %rdi
callq 0x3360
jmp 0x2432
leaq -0x150(%rbp), %rdi
callq 0x33a0
leaq -0x58(%rbp), %rdi
callq 0x33f0
movq 0x5b8a(%rip), %rdi      # 0x7fd8
movq 0x5b6b(%rip), %rsi      # 0x7fc0
movq %rsi, -0x378(%rbp)
callq 0x20b0
movq %rax, %rdi
leaq 0x2c7e(%rip), %rsi      # 0x50e9
callq 0x2090
movq -0x378(%rbp), %rsi
movq %rax, %rdi
callq 0x20b0
movl $0x1, %edi
callq 0x20a0
movq %rax, -0x370(%rbp)
leaq 0x439(%rip), %rax       # 0x28d0
movq %rax, -0x1f0(%rbp)
movq $0x0, -0x1e8(%rbp)
leaq -0x151(%rbp), %rax
movq %rax, -0x360(%rbp)
movq %rax, -0x1f8(%rbp)
leaq -0x1e0(%rbp), %rdi
movq %rdi, -0x368(%rbp)
leaq -0x1f0(%rbp), %rsi
leaq -0x1f8(%rbp), %rdx
callq 0x2890
movq -0x368(%rbp), %rsi
leaq -0x1c8(%rbp), %rdi
callq 0x2910
movq -0x360(%rbp), %rax
leaq 0x4b0(%rip), %rcx       # 0x29b0
movq %rcx, -0x240(%rbp)
movq $0x0, -0x238(%rbp)
movq %rax, -0x248(%rbp)
leaq -0x230(%rbp), %rdi
leaq -0x240(%rbp), %rsi
leaq -0x248(%rbp), %rdx
callq 0x2890
jmp 0x2535
leaq -0x218(%rbp), %rdi
leaq -0x230(%rbp), %rsi
callq 0x2910
jmp 0x254a
movq -0x370(%rbp), %rsi
leaq -0x1a8(%rbp), %rdi
leaq -0x1c8(%rbp), %rdx
leaq -0x218(%rbp), %rcx
callq 0x31c0
jmp 0x256d
leaq -0x218(%rbp), %rdi
callq 0x3260
leaq -0x1c8(%rbp), %rdi
callq 0x3260
leaq -0x290(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x3280
jmp 0x259a
leaq -0x290(%rbp), %rdi
callq 0x3340
movq %rax, -0x380(%rbp)
jmp 0x25af
movq -0x380(%rbp), %rdi
callq 0x3360
jmp 0x25bd
leaq -0x290(%rbp), %rdi
callq 0x33a0
movq 0x5a08(%rip), %rdi      # 0x7fd8
movq 0x59e9(%rip), %rsi      # 0x7fc0
callq 0x20b0
movq %rax, -0x388(%rbp)
jmp 0x25e5
movq -0x388(%rbp), %rdi
leaq 0x2b01(%rip), %rsi      # 0x50f4
callq 0x2090
movq %rax, -0x390(%rbp)
jmp 0x2601
movq -0x390(%rbp), %rdi
movq 0x59b1(%rip), %rsi      # 0x7fc0
callq 0x20b0
jmp 0x2616
leaq -0x2e0(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x3280
jmp 0x262b
leaq -0x2e0(%rbp), %rdi
callq 0x3340
movq %rax, -0x398(%rbp)
jmp 0x2640
movq -0x398(%rbp), %rdi
callq 0x3430
movl %eax, -0x39c(%rbp)
jmp 0x2654
leaq -0x328(%rbp), %rdi
leaq -0x1a8(%rbp), %rsi
callq 0x3280
jmp 0x2669
leaq -0x328(%rbp), %rdi
callq 0x3340
movq %rax, -0x3a8(%rbp)
jmp 0x267e
movq -0x3a8(%rbp), %rdi
callq 0x3430
movl %eax, -0x3ac(%rbp)
jmp 0x2692
movl -0x3ac(%rbp), %ecx
movl -0x39c(%rbp), %eax
addl %ecx, %eax
movl %eax, -0x3bc(%rbp)
leaq -0x328(%rbp), %rdi
callq 0x33a0
leaq -0x2e0(%rbp), %rdi
callq 0x33a0
movl -0x3bc(%rbp), %eax
movl %eax, -0x294(%rbp)
movq 0x5907(%rip), %rdi      # 0x7fd8
leaq 0x2a47(%rip), %rsi      # 0x511f
callq 0x2090
movq %rax, -0x3b8(%rbp)
jmp 0x26e6
movq -0x3b8(%rbp), %rdi
movl -0x294(%rbp), %esi
callq 0x20f0
movq %rax, -0x3c8(%rbp)
jmp 0x2701
movq -0x3c8(%rbp), %rdi
movq 0x58b1(%rip), %rsi      # 0x7fc0
callq 0x20b0
jmp 0x2716
leaq -0x1a8(%rbp), %rdi
callq 0x33f0
xorl %eax, %eax
addq $0x3d0, %rsp            # imm = 0x3D0
popq %rbp
retq
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0xb0(%rbp), %rdi
callq 0x3260
leaq -0x78(%rbp), %rdi
callq 0x3260
jmp 0x2877
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x27ab
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x108(%rbp), %rdi
callq 0x33a0
jmp 0x27ab
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x150(%rbp), %rdi
callq 0x33a0
leaq -0x58(%rbp), %rdi
callq 0x33f0
jmp 0x2877
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x27eb
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x218(%rbp), %rdi
callq 0x3260
leaq -0x1c8(%rbp), %rdi
callq 0x3260
jmp 0x2877
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x286b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x290(%rbp), %rdi
callq 0x33a0
jmp 0x286b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
jmp 0x285f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xb8(%rbp)
movl %eax, -0xbc(%rbp)
leaq -0x328(%rbp), %rdi
callq 0x33a0
leaq -0x2e0(%rbp), %rdi
callq 0x33a0
leaq -0x1a8(%rbp), %rdi
callq 0x33f0
movq -0xb8(%rbp), %rdi
callq 0x2100
nopw %cs:(%rax,%rax)