LoginSignup
1
0

More than 3 years have passed since last update.

EventQueueを使ってみたよ (6)

Last updated at Posted at 2019-12-31

前回の記事では、EventQueueについてThe EventQueue API Tutorialでイベントループを使うところまで読んでみました。今回は、優先順位について考えます。

題材について

この記事で題材として取り上げたのは、The EventQueue APIというTutorialです。

優先順位付け(Prioritization)

The EventQueue has no concept of event priority.

EventQueueは、イベントの優先順位という概念がありません。

If you schedule events to run at the same time, the order in which the events run relative to one another is undefined.

複数のイベントが同時に実行されるようにスケジュールされたとき、それぞれのイベント同士の順序は定義されていません。

The EventQueue only schedules events based on time.

EventQueueは、イベントを時間に基づいてスケジューリングをするだけです。

If you want to separate your events into different priorities, you must instantiate an EventQueue for each priority.

複数のイベントに異なる優先順位を設定したいときには、それぞれの優先順位について別々のEventQueueオブジェクトのインスタンスを作成しなくてはなりません。

You must appropriately set the priority of the thread dispatching each EventQueue instance.

それぞれのEventQueueインスタンスを扱うスレッドの優先順位を適切に設定しなくてはなりません。

イベントキューは、単純なキューとして働くので、キューに入ったイベント同士に優先順位をつけることはできません。そういった動作が必要な時は、別々のイベントキューを作成し、それぞれを別のスレッドに割り当てて、スレッドの優先順位によってイベントの優先順位を決定します。

コードを書いてみた

優先順位付けの項目は、説明文だけだったので、独自にプログラムを作成してみました。

#include "mbed.h"

EventQueue queue1(32 * EVENTS_EVENT_SIZE);
Thread thread1(osPriorityNormal);
EventQueue queue2(32 * EVENTS_EVENT_SIZE);
Thread thread2(osPriorityNormal);

void thread1Task(void) {
    printf("  thread1: start %p at %lld\r\n", ThisThread::get_id(), Kernel::get_ms_count());
    CyDelay(2000);
    printf("  thread1: end %p at %lld\r\n", ThisThread::get_id(), Kernel::get_ms_count());
}

void thread2Task(void) {
    printf("thread2: start %p at %lld\r\n", ThisThread::get_id(),  Kernel::get_ms_count());
    CyDelay(3000);
    printf("thread2: end %p at %lld\r\n", ThisThread::get_id(),  Kernel::get_ms_count());
}

int main() {
    // Start the event queue
    thread1.start(callback(&queue1, &EventQueue::dispatch_forever));
    thread2.start(callback(&queue2, &EventQueue::dispatch_forever));
    printf("Starting in context %p at %lld\r\n", ThisThread::get_id(), Kernel::get_ms_count());
    // Queue two tasks into queue2
    queue2.call(thread2Task);
    queue2.call(thread2Task);
    // Queue three tasks into queue1
    queue1.call(thread1Task);
    queue1.call(thread1Task);
    queue1.call(thread1Task);
}

ふたつのイベントキューqueue1queue2を作成して、それぞれをスレッドthread1thread2で走らせます。まずは、どちらのスレッドも同じ優先順位osPriorityNormalで実行します。それぞれのスレッドで実行するイベントは、thread1Taskthread2Taskで、CyDelay()関数を使って長い時間を要するタスクを模擬しています。

queue1には2秒間CPUを使うthread1Taskを三つ、queue2には3秒間CPUを使うthread2Taskを二つ入れています。実行結果は、以下の通りです。

Starting in context 080043e0 at 0
  thread1: start 08004e14 at 0
thread2: start 08004ed4 at 6
  thread1: end 08004e14 at 4152
  thread1: start 08004e14 at 4152
thread2: end 08004ed4 at 6239
thread2: start 08004ed4 at 6239
  thread1: end 08004e14 at 8315
  thread1: start 08004e14 at 8315
  thread1: end 08004e14 at 12483
thread2: end 08004ed4 at 12485

まず、thread1thread2のタスクが6ミリ秒の差で実行を開始します。最初のthread1のタスクは4152ミリ秒後に終了します。CPUを独占できれば2秒で終わるはずですが、およそ2倍の時間を要しています。このことから、thread1thread2のタスクが、ほぼ同等に実行されていたことがわかります。その後も、thread1thread2は、CPUを分け合いながら実行されていることがわかります。

次に、thread1の優先順位をthread2よりも高くしてみます。

EventQueue queue1(32 * EVENTS_EVENT_SIZE);
Thread thread1(osPriorityAboveNormal);
EventQueue queue2(32 * EVENTS_EVENT_SIZE);
Thread thread2(osPriorityNormal);

実行結果は、こうなりました。

Starting in context 080043e0 at 0
  thread1: start 08004e14 at 0
  thread1: end 08004e14 at 2076
  thread1: start 08004e14 at 2076
  thread1: end 08004e14 at 4150
  thread1: start 08004e14 at 4150
  thread1: end 08004e14 at 6225
thread2: start 08004ed4 at 6225
thread2: end 08004ed4 at 9340
thread2: start 08004ed4 at 9340
thread2: end 08004ed4 at 12463

thread1の優先順位が高くなったことで、thread2thread1のイベントがすべて終わるまで実行されません。その代わり、全体の終了時刻は、少しだけ早くなっています。これは、タスクの切り替えによるオーバヘッドが少なくなったためと考えられます。

次回は、イベントへのメモリ割り当てについて考えます。

関連サイト

Mbed OSのページ
EventQueueのTutorial
Mbed対応Cypress製品のページ

関連記事

EventQueueを使ってみたよ (1)
EventQueueを使ってみたよ (2)
EventQueueを使ってみたよ (3)
EventQueueを使ってみたよ (4)
EventQueueを使ってみたよ (5)
EventQueueを使ってみたよ (6)
EventQueueを使ってみたよ (7)
EventQueueを使ってみたよ (8)
EventQueueを使ってみたよ (9)

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0