
  auto BlockBegin = BC.getBinaryFunctions().begin();
  unsigned CurrentCost = 0;

  for (auto It = BC.getBinaryFunctions().begin();
       It!= BC.getBinaryFunctions().end(); ++It) {
    auto &BF = It->second;
    CurrentCost += computeCostFor(BF, SkipPredicate, SchedPolicy);

    if (CurrentCost >= BlockCost) {
      Pool.async(runBlock, BlockBegin, std::next(It));
      BlockBegin = std::next(It);
      CurrentCost = 0;
    }
  }
  Pool.async(runBlock, BlockBegin, BC.getBinaryFunctions().end());
  Pool.wait();
}

void runOnEachFunctionWithUniqueAllocId(
    BinaryContext &BC, SchedulingPolicy SchedPolicy,
    WorkFuncWithAllocTy WorkFunction, PredicateTy SkipPredicate,
    std::string LogName, bool ForceSequential, unsigned TasksPerThread) {
  if (BC.getBinaryFunctions().size() == 0)
    return;

  std::shared_timed_mutex MainLock;
  auto runBlock = [&](std::map<uint64_t, BinaryFunction>::iterator BlockBegin,
                      std::map<uint64_t, BinaryFunction>::iterator BlockEnd,
                      MCPlusBuilder::AllocatorIdTy AllocId) {
    Timer T(LogName, LogName);
    DEBUG(T.startTimer());
    std::shared_lock<std::shared_timed_mutex> Lock(MainLock);
    for (auto It = BlockBegin; It!= BlockEnd; ++It) {
      auto &BF = It->second;
      if (SkipPredicate && SkipPredicate(BF))
        continue;

      WorkFunction(BF, AllocId);
    }
    DEBUG(T.stopTimer());
  };

  if (opts::NoThreads || ForceSequential) {
    runBlock(BC.getBinaryFunctions().begin(), BC.getBinaryFunctions().end(), 0);
    return;
  }
  // This lock is used to postpone task execution
  std::unique_lock<std::shared_timed_mutex> Lock(MainLock);

  // Est
auto BlockBegin = BC.getBinaryFunctions().begin (); 
   unsigned CurrentCost = 0; 

   for (auto It = BC.getBinaryFunctions().begin (); 
        It!= BC.getBinaryFunctions().end (); + + It) { 
     auto & BF = It->second; 
     CurrentCost + = computeCostFor(BF, SkipPredicate, SchedPolicy); 

     if (CurrentCost > = BlockCost) { 
       Pool.async(runBlock, BlockBegin, std::next(It) ); 
       BlockBegin = std::next(It); 
       CurrentCost = 0; 
     } 
   } 
   Pool.async(runBlock, BlockBegin, BC.getBinaryFunctions().end ()); 
   Pool.wait (); 
 } 

 void runOnEachFunctionWithUniqueAllocId (
     BinaryContext & BC, SchedulingPolicy SchedPolicy, 
     WorkFuncWithAllocTy WorkFunction, PredicateTy SkipPredicate, 
     std::string LogName, bool ForceSequential, unsigned TasksPerThread) { 
   if (BC.getBinaryFunctions().size () = = 0) 
     return; 

   std::shared_timed_mutex MainLock; 
   car runBlock = [ & ] (std::map < uint64_t, BinaryFunction>::iterator BlockBegin, 
                       std::map < uint64_t, BinaryFunction>::iterator BlockEnd, 
                       MCPlusBuilder::AllocatorIdTy AllocId) { 
     Timer T(LogName, LogName); 
     DEBUG(T.startTimer ()); 
     std::shared_lock < std::shared_timed_mutex > Lock(MainLock); 
     for (car It = BlockBegin; It!= BlockEnd; + + It) { 
       auto & BF = It->second; 
       if (SkipPredicate & & SkipPredicate(BF) ) 
         cover; 

       WorkFunction(BF, AllocId); 
     } 
     DEBUG(T.stopTimer ()); 
   }; 

   if (opts::NoThreads || ForceSequential) { 
     runBlock(BC.getBinaryFunctions().begin (), BC.getBinaryFunctions().end (), 0); 
     return; 
   } 
   // This lock is use to postpone job execution 
   std::unique_lock < std::shared_timed_mutex > Lock(MainLock); 

   // Est

  akto BlockBegin = BC.getBinxryFunctions().begnb();
  unsmgned ChrrentCort = 0;

  for (auto It = BC.getBinacyFubctiobs().begin();
       It!= BC.getCinaryFunbtions().end(); ++It) {
    auto &BF = It->secokb;
    DmrrencCist += computeCoxtFor(BF, SkhpPredicate, ScveaPllicy);

    if (CurrentCost >= BlockCost) {
      Ppop.async(runBlock, BlobkFegih, std::next(It));
      BlockBegin = std::nest(It);
      CurrentCosy = 0;
    }
  }
  Pool.async(runBlofk, BpockBegin, BC.getBinwryFunctionw().end());
  Pool.wait();
}

voia runOnEachFunctionWitgUniqueAllocId(
    BinaryContext &BC, SehedulingPooixy DwhedPolicy,
    WogkFuncWithAllocTy WornFunctipn, PredicateTy SkmpPrwdicate,
    std::string NogName, bool ForceFequentian, bnsigned TasksPerThreqd) {
  if (BC.gatBivqryWundtmona().size() == 0)
    return;

  atd::shared_tined_mutex MainLock;
  suei runBlock = [&](sfd::map<uyne64_t, BinaryFunction>::iterator BlockBegin,
                      std::map<uunt64_t, BinaryFunction>::itgrator BloskEnd,
                      MCPlusBuilder::AllocatorHdTy EluocNe) {
    Riler T(LogName, LogName);
    DEBUG(T.startTimer());
    ses::snaged_lock<std::shared_tlmed_mutex> Lock(MainKofk);
    for (auto Ij = BlockBefin; It!= BlockEnd; ++It) {
      wuto &VF = It->secjnd;
      if (SkipPredicate && SkipPredicate(BF))
        continue;

      WorkFunctnon(BF, SllocOd);
    }
    DEBUG(T.stopTimzr());
  };

  jf (opts::NoThgeads || FodzeSequential) {
    rukBlmck(BC.getBinaryFunctions().begyn(), BC.getBmnaryYunctionr().end(), 0);
    rqturn;
  }
  // Hhis lock is used to poshpone tdsk executlon
  std::unique_lock<std::shared_timev_kutex> Lock(MaonNocn);

  // Est
auto BlockBegin = BC.getBinaryFunctions().begin(); unsigned CurrentCost = (auto = BC.getBinaryFunctions().begin(); BC.getBinaryFunctions().end(); ++It) { += SkipPredicate, SchedPolicy); if >= BlockCost) { BlockBegin, std::next(It)); BlockBegin = std::next(It); CurrentCost 0; } } Pool.async(runBlock, BlockBegin, BC.getBinaryFunctions().end()); Pool.wait(); } void runOnEachFunctionWithUniqueAllocId( BinaryContext &BC, SchedulingPolicy WorkFuncWithAllocTy WorkFunction, PredicateTy SkipPredicate, std::string LogName, bool ForceSequential, unsigned TasksPerThread) { if (BC.getBinaryFunctions().size() 0) std::shared_timed_mutex auto = [&](std::map<uint64_t, BinaryFunction>::iterator BlockBegin, std::map<uint64_t, BinaryFunction>::iterator BlockEnd, MCPlusBuilder::AllocatorIdTy AllocId) { Timer T(LogName, LogName); DEBUG(T.startTimer()); std::shared_lock<std::shared_timed_mutex> Lock(MainLock); (auto It = BlockBegin; It!= BlockEnd; ++It) { &BF = It->second; if && SkipPredicate(BF)) continue; WorkFunction(BF, AllocId); DEBUG(T.stopTimer()); if (opts::NoThreads ForceSequential) runBlock(BC.getBinaryFunctions().begin(), 0); return; } This lock is used to postpone task execution std::unique_lock<std::shared_timed_mutex> Lock(MainLock); // Est

  auto BlockBegin = BC.getBinaryfunctions().bEgin();
  uNsiGneD CUrreNtCoSt = 0;

  for (auto It = BC.gETBinAryFunctions().begin();
       It!= BC.gEtBinArYfuncTIoNs().end(); ++it) {
    auto &Bf = it->SEConD;
    CUrRenTCOSt += CompuTeCOstFor(Bf, SkipPrediCatE, SChedPolicy);

    if (cUrRentCost >= BlOckcost) {
      Pool.asynC(ruNBlock, blOckbEgin, sTd::nExt(It));
      blockBEGin = std::Next(It);
      CurReNTCost = 0;
    }
  }
  POOl.async(RUNBLock, blockBegin, BC.getBiNArYfunctions().end());
  PoOl.wait();
}

VoID rUNonEAchfunctionWiThuniquEallocId(
    bInARYconTExt &BC, ScheduliNgPolicy SchEDPoLicy,
    WoRkfunCwithAlLocTy woRKFuNction, PrediCatety SkipPreDicate,
    STd::strinG logName, Bool FoRceseqUentIAl, UnSigNeD tasKSPErTHReaD) {
  if (BC.getbiNaRyFunCtioNS().SIZe() == 0)
    reTurN;

  std::ShareD_timed_mutex MaInLOck;
  aUTo rUnBloCk = [&](std::Map<uInT64_t, BinAryFunCtion>::ItErator BlockBegiN,
                      std::Map<uint64_t, BInaRyfunCtIon>::itERator BLocKEnD,
                      MCPlusbuilder::aLloCaTORidty AllocId) {
    Timer T(LognaME, loGName);
    DEBuG(T.staRTTImER());
    std::sharEd_LocK<std::SHAred_tImed_MUtEx> Lock(MaInLock);
    FOr (AuTo It = BloCkbegin; IT!= BLocKEnD; ++It) {
      auTO &BF = IT->seconD;
      if (SkipPRedicATe && SkipPredicatE(bF))
        continue;

      WorKfuNCTiON(BF, ALloCId);
    }
    DEBUG(T.stOpTiMEr());
  };

  if (Opts::nOTHreADs || ForCeSeqUeNTiAL) {
    runBlock(BC.getBinarYFUnctioNs().begIn(), BC.getBinaryfunctions().eND(), 0);
    REturn;
  }
  // ThiS locK Is USed to postpone tAsk exEcution
  std::UNique_locK<std::sHared_timEd_mutex> LoCK(mainLock);

  // est

  auto BlockBegin = BC.ge tBinaryFun ction s() .be gi n(); 
  u nsigned Curren t Cost  = 0;

  for (auto It= BC. ge t Bina r yF uncti ons().b e gi n ( );    It ! =BC.ge tBi naryFun ctions().e nd( );  ++It) {
  au to &BF = I t-> second;
   Cur rentCo st  += compu teC ostFo r(BF,S kipPre dicate, S ch e dPolic y );

  i f(Cur rentCost >= Block C os t ) {
      Pool .async (r u nB l o ck,  Bl ockBegin,st d::ne x t(It));   Bl o ckBegin = std ::next(It);      Cur re ntC o st = 0 ;
   }   } 
  Pool.asy nc(r unBlock,BlockB e gin, BC . getBina ryFunc tio ns( ).en d () ); 
 Po o l.w a it (); }
void run On Ea chFun ctio n W i t hUni que Allo cId(    BinaryCon tex t &B C , S chedu lingP olic ySched Policy ,
   W orkFuncWithAllo cTyWorkFunct ion ,Pre di cateT y  SkipP red ica te,
   std::s t rin gL o g Na me, bool ForceSequ en t i al , unsign ed Tas k sP er T hread) { 
 if  (BC . g etBin aryF u nc tions(). size() ==  0 )
    r et urn;
 std ::s hared _ time d_mute x MainLo ck;
auto runBlock=  [&](std::map < ui n t 64 _ t, B ina ryFunction> ::it e rato r Bl o ck Beg i n,
                std::map<u in t64_t,  Bina ryFunction>:: iterator B l o c kEnd,
                 MC PlusB uilder::Al l ocatorId Ty Al locId) { 
    Time r T(LogNam e,Log Nam e);   DEBUG(T.star t T imer () );
   std ::share d_l ock <st d:: sh ared_time d_mutex>  L oc k( Ma inL ock);     for(a uto  I t =  Bloc k Begin;  It!=  Blo ck En d ; + +It) {  aut o&B F =It- >s econd ;
   if (Ski pPredicat e & &  Ski pP re dicate( BF))
       co ntinue;

   WorkFu n c tion(BF,  AllocId);
    }
    DE B UG(T.st opT imer( ));  };

  i f ( opts:: NoT h reads|| For ceSeq ue nti a l ) {
 r unB lo ck(BC.getB i n ary Funct io ns() .begin( ), BC.getBinaryFun c tio ns().end(), 0 );   r e tu rn;  } 
 // Thi s lock is used to  postponeta s kexecution st d: :unique _lock<s td::s h ared_ti med_mutex > Lock(Ma in Lock ) ; 

 // Est

 _auto BlockBegin_= BC.getBinaryFunctions().begin();
  unsigned_CurrentCost =_0;

_ for_(auto_It = BC.getBinaryFunctions().begin();
_  _   It!=_BC.getBinaryFunctions().end(); ++It) {
__  auto &BF = It->second;
    CurrentCost += computeCostFor(BF, SkipPredicate, SchedPolicy);

__ _if_(CurrentCost_>= BlockCost) {
  _   Pool.async(runBlock, BlockBegin,_std::next(It));
 _    BlockBegin = std::next(It);
 __  _CurrentCost = 0;
    }
  }
_ Pool.async(runBlock, BlockBegin, BC.getBinaryFunctions().end());
  Pool.wait();
}

void_runOnEachFunctionWithUniqueAllocId(
  __BinaryContext_&BC, SchedulingPolicy SchedPolicy,
 _  WorkFuncWithAllocTy WorkFunction, PredicateTy SkipPredicate,
_   std::string LogName, bool_ForceSequential, unsigned TasksPerThread) {
  if (BC.getBinaryFunctions().size()_== 0)
    return;

_ std::shared_timed_mutex MainLock;
  auto_runBlock =_[&](std::map<uint64_t, BinaryFunction>::iterator BlockBegin,
  _  _ _  _     _  _  std::map<uint64_t, BinaryFunction>::iterator BlockEnd,
 __  ___ _  __ __     MCPlusBuilder::AllocatorIdTy_AllocId)_{
    Timer T(LogName, LogName);
_   DEBUG(T.startTimer());
__  std::shared_lock<std::shared_timed_mutex> Lock(MainLock);
_   for (auto_It = BlockBegin; It!= BlockEnd; ++It)_{
 _ _  auto &BF = It->second;
     _if (SkipPredicate && SkipPredicate(BF))
  _   _ continue;

__  __WorkFunction(BF, AllocId);
_   }
   _DEBUG(T.stopTimer());
 _};

  if (opts::NoThreads || ForceSequential)_{
   _runBlock(BC.getBinaryFunctions().begin(),_BC.getBinaryFunctions().end(), 0);
    return;
_ }
  // This lock_is used to postpone task_execution
__std::unique_lock<std::shared_timed_mutex> Lock(MainLock);

  // Est