C ++ Dil Programları: Choroutine için öncelikli bir zamanlayıcı

Adanali

Active member
C ++ Dil Programları: Choroutine için öncelikli bir zamanlayıcı


  1. C ++ Dil Programları: Choroutine için öncelikli bir zamanlayıcı

Bu, C ++ Coroutinen için zamanlayıcı ile ilgili mini serimin üçüncü makalesi. İlk iki makale Dian-Lun Lin'in konuklarının gönderileriydi:










Rainer Grimm yıllardır yazılım mimarı, ekip ve eğitim müdürü olarak çalıştı. C ++ programlama dilleri, Python ve Haskell hakkında makaleler yazmayı seviyor, ancak uzman konferanslarla konuşmayı da seviyor. Modern C ++ blogunda, C ++ tutkusuyla yoğun bir şekilde ilgileniyor.













Dian-Luns Scheduer, Std :: Stack ve Std :: Coda konteyneri temelini çekti. . std::stack görevlerini ilk çıkış stratejisine göre yönlendirin, std::queue Öte yandan, ilk çıkışa göre.

Aşağıdaki kod parçası, kuyruk tabanlı zamanlayıcıdır:



class Scheduler {

std::queue<std::coroutine_handle<>> _tasks;&#13;
&#13;
public: &#13;
&#13;
void emplace(std::coroutine_handle<> task) {&#13;
_tasks.push(task);&#13;
}&#13;
&#13;
void schedule() {&#13;
while(!_tasks.empty()) {&#13;
auto task = _tasks.front();&#13;
_tasks.pop();&#13;
task.resume();&#13;
&#13;
if(!task.done()) { &#13;
_tasks.push(task);&#13;
}&#13;
else {&#13;
task.destroy();&#13;
}&#13;
}&#13;
}&#13;
&#13;
auto suspend() {&#13;
return std::suspend_always{};&#13;
}&#13;
};


Bu öncelik programını genişletmek oldukça basittir.



Öncelik tabanlı bir zamanlayıcı


std::priority_queue Yanında std::stack VE std::queue C ++ 98'deki üçüncü konteyner adaptörü.

. std::priority_queue öyle std::queue benzer. Temel fark, en büyük unsurlarının her zaman öncelik kuyruğunun üstünde olmasıdır. std::priority_queue Varsayılan olarak karşılaştırma operatörünü kullanmak std::less. . Nachschlagezeit birinde std::priority_queue Sabittir, ancak eklemek ve ortadan kaldırmak logaritmiktir.

Onları değiştiriyorum std::queue Bir dosya aracılığıyla önceki programda std::priority_queue:



// priority_queueScheduler.cpp&#13;
&#13;
#include <coroutine>&#13;
#include <iostream>&#13;
#include <queue>&#13;
#include <utility>&#13;
&#13;
&#13;
struct Task {&#13;
&#13;
struct promise_type {&#13;
std::suspend_always initial_suspend() noexcept { return {}; }&#13;
std::suspend_always final_suspend() noexcept { return {}; }&#13;
&#13;
Task get_return_object() { &#13;
return std::coroutine_handle<promise_type>::from_promise(*this); &#13;
}&#13;
void return_void() {}&#13;
void unhandled_exception() {}&#13;
};&#13;
&#13;
Task(std::coroutine_handle<promise_type> handle): handle{handle}{}&#13;
&#13;
auto get_handle() { return handle; }&#13;
&#13;
std::coroutine_handle<promise_type> handle;&#13;
};&#13;
&#13;
class Scheduler {&#13;
// (1)&#13;
std::priority_queue<std::pair<int, std::coroutine_handle<>>> _prioTasks;&#13;
&#13;
public: &#13;
&#13;
void emplace(int prio, std::coroutine_handle<> task) { // (2)&#13;
_prioTasks.push(std::make_pair(prio, task));&#13;
}&#13;
&#13;
void schedule() {&#13;
while(!_prioTasks.empty()) { // (3)&#13;
auto [prio, task] = _prioTasks.top();&#13;
_prioTasks.pop();&#13;
task.resume();&#13;
&#13;
if(!task.done()) { &#13;
_prioTasks.push(std::make_pair(prio, task)); // (4)&#13;
}&#13;
else {&#13;
task.destroy();&#13;
}&#13;
}&#13;
}&#13;
&#13;
auto suspend() {&#13;
return std::suspend_always{};&#13;
}&#13;
};&#13;
&#13;
&#13;
Task TaskA(Scheduler& sch) {&#13;
std::cout << "Hello from TaskAn";&#13;
co_await sch.suspend();&#13;
std::cout << "Executing the TaskAn";&#13;
co_await sch.suspend();&#13;
std::cout << "TaskA is finishedn";&#13;
}&#13;
&#13;
Task TaskB(Scheduler& sch) {&#13;
std::cout << "Hello from TaskBn";&#13;
co_await sch.suspend();&#13;
std::cout << "Executing the TaskBn";&#13;
co_await sch.suspend();&#13;
std::cout << "TaskB is finishedn";&#13;
}&#13;
&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
Scheduler scheduler1;&#13;
&#13;
scheduler1.emplace(0, TaskA(scheduler1).get_handle()); // (5) &#13;
scheduler1.emplace(1, TaskB(scheduler1).get_handle());&#13;
&#13;
scheduler1.schedule();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
Scheduler scheduler2;&#13;
&#13;
scheduler2.emplace(1, TaskA(scheduler2).get_handle()); // (6)&#13;
scheduler2.emplace(0, TaskB(scheduler2).get_handle());&#13;
&#13;
scheduler2.schedule();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}


İlk olarak std::priority_queue Bir çift (öncelik, sap) (1). Şimdi bu çift açık olacak _prioTask Yayınlanan (2). Zamanlayıcı gerçekleştirdiğinde, _prioTask Boştur (3), aksi takdirde ilk görev çağrılır, kaldırılır ve alınır. Etkinlik bitmediğinde, _prioTasks taşındı (4).

Bir kullanımı std::priority_queue<std::pair<int, std::coroutine_handle<>>> Görevlerin ilk kez daha yüksek bir öncelikle gerçekleştirildiği hoş yan etkiye sahiptir. Faaliyetlerin zamanlayıcı (5 ve 6) üzerinde konumlandırıldığı sırada hiçbir fark yaratmaz; Öncelikli etkinlik 1 önce çalışır.









Bir sonraki makalemdeki öncelik tedavinizi geliştirmeden önce bakıcıyı basitleştirmek istiyorum.

Basitleştirilmiş Koro


İşte önceki choutines TaskA VE TaskB:



Task TaskA(Scheduler& sch) {&#13;
std::cout << "Hello from TaskAn";&#13;
co_await sch.suspend();&#13;
std::cout << "Executing the TaskAn";&#13;
co_await sch.suspend();&#13;
std::cout << "TaskA is finishedn";&#13;
}&#13;
&#13;
Task TaskB(Scheduler& sch) {&#13;
std::cout << "Hello from TaskBn";&#13;
co_await sch.suspend();&#13;
std::cout << "Executing the TaskBn";&#13;
co_await sch.suspend();&#13;
std::cout << "TaskB is finishedn";&#13;
}&#13;



Yerine co_await Zamanlayıcı arayın, önceden tanımlanmış beklentiyi doğrudan arayarak değiştiriyorum std::suspend_always. Böylece zamanlayıcı süspansiyonunu kaldırabilirim. İkincisi, koro faaliyetlerinizin adını alır:



Task createTask(const std::string& name) {&#13;
std::cout << name << " startn";&#13;
co_await std::suspend_always();&#13;
std::cout << name << " executen";&#13;
co_await std::suspend_always();&#13;
std::cout << name << " finishn";&#13;
}&#13;



Son olarak, ilgili baskı ile basitleştirilmiş program.



// priority_queueSchedulerSimplified.cpp&#13;
&#13;
#include <coroutine>&#13;
#include <iostream>&#13;
#include <queue>&#13;
#include <utility>&#13;
&#13;
&#13;
struct Task {&#13;
&#13;
struct promise_type {&#13;
std::suspend_always initial_suspend() noexcept { return {}; }&#13;
std::suspend_always final_suspend() noexcept { return {}; }&#13;
&#13;
Task get_return_object() { &#13;
return std::coroutine_handle<promise_type>::from_promise(*this); &#13;
}&#13;
void return_void() {}&#13;
void unhandled_exception() {}&#13;
};&#13;
&#13;
Task(std::coroutine_handle<promise_type> handle): handle{handle}{}&#13;
&#13;
auto get_handle() { return handle; }&#13;
&#13;
std::coroutine_handle<promise_type> handle;&#13;
};&#13;
&#13;
class Scheduler {&#13;
&#13;
std::priority_queue<std::pair<int, std::coroutine_handle<>>> _prioTasks;&#13;
&#13;
public: &#13;
&#13;
void emplace(int prio, std::coroutine_handle<> task) {&#13;
_prioTasks.push(std::make_pair(prio, task));&#13;
}&#13;
&#13;
void schedule() {&#13;
while(!_prioTasks.empty()) {&#13;
auto [prio, task] = _prioTasks.top();&#13;
_prioTasks.pop();&#13;
task.resume();&#13;
&#13;
if(!task.done()) { &#13;
_prioTasks.push(std::make_pair(prio, task));&#13;
}&#13;
else {&#13;
task.destroy();&#13;
}&#13;
}&#13;
}&#13;
&#13;
};&#13;
&#13;
&#13;
Task createTask(const std::string& name) {&#13;
std::cout << name << " startn";&#13;
co_await std::suspend_always();&#13;
std::cout << name << " executen";&#13;
co_await std::suspend_always();&#13;
std::cout << name << " finishn";&#13;
}&#13;
&#13;
&#13;
int main() {&#13;
&#13;
std::cout << 'n';&#13;
&#13;
Scheduler scheduler1;&#13;
&#13;
scheduler1.emplace(0, createTask("TaskA").get_handle());&#13;
scheduler1.emplace(1, createTask(" TaskB").get_handle());&#13;
&#13;
scheduler1.schedule();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
Scheduler scheduler2;&#13;
&#13;
scheduler2.emplace(1, createTask("TaskA").get_handle());&#13;
scheduler2.emplace(0, createTask(" TaskB").get_handle());&#13;
&#13;
scheduler2.schedule();&#13;
&#13;
std::cout << 'n';&#13;
&#13;
}








Sırada ne var?


Bir sonraki makalemde, görevlerin öncelikli tedavisini daha da geliştireceğim.


(RME)
 
Üst