// File: ArashPartow[P]exprtk-extras/exprtk_loop_timeout_rtc.cpp
// Function: void loop_timeout_rtc<double>()
void loop_timeout_rtc()
{
   typedef exprtk::expression<T>      expression_t;
   typedef exprtk::parser<T>          parser_t;
   typedef exprtk::loop_runtime_check loop_runtime_check_t;

   const std::string sieve_of_eratosthenes_program =
      " var sieve[10^8] := [false];                   "
      " var m := trunc(sqrt(sieve[]));                "
      "                                               "
      " sieve[0] := true;                             "
      " sieve[1] := true;                             "
      "                                               "
      " for (var i := 0; i <= m; i += 1)              "
      " {                                             "
      "    if (false == sieve[i])                     "
      "    {                                          "
      "       for (var j := i^2; j < sieve[]; j += i) "
      "       {                                       "
      "          sieve[j] := true;                    "
      "       }                                       "
      "    }                                          "
      " };                                            "
      "                                               "
      " var prime_count := sieve[] - sum(sieve);      "
      "                                               "
      " prime_count == 5761455;                       ";

   timeout_rtc_handler loop_runtime_check;
   loop_runtime_check.loop_set = loop_runtime_check_t::e_all_loops;
   loop_runtime_check.max_loop_iterations =
      static_cast<std::uint64_t>(10e8 * std::log10(std::log10(10e8))); // O(n) = nlog(log(n))

   vector_access_rtc vec_rtc;

   expression_t expression;

   parser_t parser;

   parser.register_loop_runtime_check(loop_runtime_check);
   parser.register_vector_access_runtime_check(vec_rtc);

   parser.compile(sieve_of_eratosthenes_program,expression);

   const auto max_duration = std::chrono::seconds(1);
   const auto timeout_tp   = std::chrono::steady_clock::now() + max_duration;
   loop_runtime_check.set_timeout_time(timeout_tp);

   try
   {
      expression.value();
   }
   catch (timeout_rtc_handler::timeout_exception& /*toe*/)
   {
      printf("Timeout Exception\n");
   }
   catch (std::runtime_error& rte)
   {
      printf("Exception: %s\n",rte.what());
   }

   parser.clear_loop_runtime_check();
}

// Assembly:
subq $0xb48, %rsp            # imm = 0xB48
leaq 0xb27(%rsp), %rdi
movq %rdi, 0x18(%rsp)
callq 0x111680
movq 0x18(%rsp), %rdx
leaq 0x32ecf0(%rip), %rsi    # 0x447555
leaq 0xb28(%rsp), %rdi
callq 0x118780
jmp 0x118874
leaq 0xb27(%rsp), %rdi
callq 0x1117a0
leaq 0xae8(%rsp), %rdi
callq 0x118ec0
jmp 0x118890
movl $0x7, 0xaf0(%rsp)
movsd 0x329765(%rip), %xmm0   # 0x442008
movsd %xmm0, 0x10(%rsp)
callq 0x1113c0
callq 0x1113c0
movsd 0x10(%rsp), %xmm1
mulsd %xmm1, %xmm0
movaps %xmm0, %xmm1
cvttsd2si %xmm1, %rax
movq %rax, %rdx
sarq $0x3f, %rdx
movsd 0x32973c(%rip), %xmm1   # 0x442010
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
andq %rdx, %rcx
orq %rcx, %rax
movq %rax, 0xaf8(%rsp)
leaq 0xae0(%rsp), %rdi
callq 0x118f30
leaq 0xac0(%rsp), %rdi
callq 0x118f60
jmp 0x118907
leaq 0x48(%rsp), %rdi
movl $0x7f, %esi
callq 0x119010
jmp 0x118918
leaq 0x198(%rsp), %rdi
leaq 0x48(%rsp), %rsi
callq 0x119140
jmp 0x11892c
leaq 0x48(%rsp), %rdi
callq 0x119970
leaq 0x198(%rsp), %rdi
leaq 0xae8(%rsp), %rsi
callq 0x1199e0
jmp 0x11894d
leaq 0x198(%rsp), %rdi
leaq 0xae0(%rsp), %rsi
callq 0x119a00
jmp 0x118964
leaq 0x198(%rsp), %rdi
leaq 0xb28(%rsp), %rsi
leaq 0xac0(%rsp), %rdx
callq 0x119a20
jmp 0x118983
movq $0x1, 0x40(%rsp)
callq 0x111650
movq %rax, 0x30(%rsp)
leaq 0x30(%rsp), %rdi
leaq 0x40(%rsp), %rsi
callq 0x11a2b0
movq %rax, 0x8(%rsp)
jmp 0x1189ac
movq 0x8(%rsp), %rax
movq %rax, 0x38(%rsp)
leaq 0xae8(%rsp), %rdi
leaq 0x38(%rsp), %rsi
callq 0x11a300
jmp 0x1189ca
leaq 0xac0(%rsp), %rdi
callq 0x11a320
jmp 0x1189d9
jmp 0x118ae2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
leaq 0xb27(%rsp), %rdi
callq 0x1117a0
jmp 0x118c01
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
jmp 0x118bf4
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
jmp 0x118bda
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
jmp 0x118bcd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
leaq 0x48(%rsp), %rdi
callq 0x119970
jmp 0x118bcd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
jmp 0x118bc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
movl 0xb14(%rsp), %eax
movl %eax, 0x4(%rsp)
movl $0x2, %ecx
cmpl %ecx, %eax
jne 0x118b3a
movq 0xb18(%rsp), %rdi
callq 0x111070
movq %rax, 0x20(%rsp)
leaq 0x32ee41(%rip), %rdi    # 0x447911
xorl %eax, %eax
callq 0x111080
jmp 0x118ad9
callq 0x1114f0
jmp 0x118ae0
jmp 0x118ae2
leaq 0x198(%rsp), %rdi
callq 0x11a340
jmp 0x118af1
leaq 0x198(%rsp), %rdi
callq 0x11a360
leaq 0xac0(%rsp), %rdi
callq 0x11a560
leaq 0xae0(%rsp), %rdi
callq 0x11a5a0
leaq 0xae8(%rsp), %rdi
callq 0x11a5b0
leaq 0xb28(%rsp), %rdi
callq 0x1117b8
addq $0xb48, %rsp            # imm = 0xB48
retq
movl 0x4(%rsp), %eax
movl $0x1, %ecx
cmpl %ecx, %eax
jne 0x118bc0
movq 0xb18(%rsp), %rdi
callq 0x111070
movq %rax, 0x28(%rsp)
movq 0x28(%rsp), %rdi
movq (%rdi), %rax
movq 0x10(%rax), %rax
callq *%rax
movq %rax, %rsi
leaq 0x32ed91(%rip), %rdi    # 0x447902
xorl %eax, %eax
callq 0x111080
jmp 0x118b7a
callq 0x1114f0
jmp 0x118b81
jmp 0x118ae2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
callq 0x1114f0
jmp 0x118ba1
jmp 0x118bc0
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0xb18(%rsp)
movl %eax, 0xb14(%rsp)
callq 0x1114f0
jmp 0x118bbe
jmp 0x118bc0
leaq 0x198(%rsp), %rdi
callq 0x11a360
leaq 0xac0(%rsp), %rdi
callq 0x11a560
leaq 0xae0(%rsp), %rdi
callq 0x11a5a0
leaq 0xae8(%rsp), %rdi
callq 0x11a5b0
leaq 0xb28(%rsp), %rdi
callq 0x1117b8
movq 0xb18(%rsp), %rdi
callq 0x111470
movq %rax, %rdi
callq 0x118e80
nopw %cs:(%rax,%rax)