2016-04-11 21 views
1

Şu anda zaman harcayan görevleri bir sırayla gerçekleştiren bazı eşzamanlı C++ kodlarım var. Bunu paralel görevlere dönüştürmek için Boost coroutines kullanmayı düşünüyorum.Korout yürütmeleri arasında uyuma zorla

Görevlerin çekirdeği, senkronize bir API (şu anda kullanıyor) veya eylemi ilerletmek için düzenli olarak sorgulanması gereken ve tamamlanıp tamamlanmadığını belirleyen eşzamansız bir API sağlayan bir dış kütüphaneye yapılan çağrıdır. . API, iş parçacığı için güvenli değildir, ancak eşzamansız sürüm kullanılıyorsa, eşleme API'sinin kendisi eşzamanlı olarak çağrılmadığı sürece aynı anda gerçekleşen birden çok istekle başa çıkabilir.

(Herhangi bir iş parçacığı değiştirmek istemediğimden, ASIO sarmalayıcıları veya benzerlerini kullanmak yerine doğrudan coroutine API kullanmalıyım gibi görünüyor, ancak aksi takdirde ikna edilmeye razıyım. Şu anda 1.55, bu yüzden Fiber kütüphanesi mevcut değil, aynı zamanda bu kullanım için overkill gibi görünüyor.)

Şu andaki asıl sorularımın asıl meselesi, ankette azaltmanın nasıl uygulanacağından emin değilim. - paralel olarak çalışacak 100 görevim olduğunu söyle; Tüm 100 görev boyunca bir sorgulama çalışması yapmasını ve ardından belirli bir süre boyunca iş parçacığını uyutmasını istiyorum. Bazı görevler diğerlerine göre daha erken tamamlanabilir, bu nedenle daha sonra döngü başına 40 görevler sorgulamak ve daha sonra aynı zaman uyuyor olabilir. Aynı görevi bir kerede iki kez arayarak uykusuz bir uykudan geçirmesini istemiyorum.

+1

Peki, anlattığınız şeyi kodlamanızı engelleyen nedir? Koroutini sadece uyumak istiyorsa ve sadece tüm aktif koroutinler boyunca koşarak, uyuyarak ve tekrarladığında verim sağlayacak şekilde kodlayın. –

+0

Muhtemelen sadece yabancılık. Belki de bu varsayımdan daha basittir. – Miral

cevap

0

Tamam, düşündüğümden çok daha kolay olduğu ortaya çıktı. Bu defa ile sona erdi budur:

typedef boost::coroutines::coroutine<void>::push_type coroutine; 
typedef boost::coroutines::coroutine<void>::pull_type yield_context; 
typedef std::vector<coroutine> coroutine_list; 

bool run_once_all(coroutine_list& coros) 
{ 
    bool pending = false; 
    for (auto& coro : coros) 
    { 
     if (coro) 
     { 
      coro(); 
      pending = pending || !coro.empty(); 
     } 
    } 
    return pending; 
} 

void run_all(coroutine_list& coros, 
      const boost::chrono::nanoseconds& idle_ns) 
{ 
    while (run_once_all(coros)) 
    { 
     boost::this_thread::sleep_for(idle_ns); 
    } 
} 

void run_all(coroutine_list& coros, yield_context& yield) 
{ 
    while (run_once_all(coros)) 
    { 
     yield(); 
    } 
} 

Fikir sonra run_all imza void (yield_context&) ile daha sonra emplace_back lambda fonksiyonları bir coroutine_list, yapmalarıdır. Birincisi üst düzey ve ikincisi ise iç içe geçmiş koroutinler içindir.

Henüz büyük bir antrenman yapmamış olmama rağmen işe yarıyor. Aslında biraz şaşkınlık bu gibi bir şey kütüphanede değil.