LoginSignup
2
0

More than 3 years have passed since last update.

EventQueueを使ってみたよ (2)

Last updated at Posted at 2019-12-29

EventQueueについてThe EventQueue API Tutorialの序文を読んでみた前回の記事に続いて、今回は、イベントループのコードを書きます。

題材について

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

イベントループを作る(Creating an event loop)

お待たせしました。コードが出てきますよ。

You must create and start the event loop manually.

イベントループは手作業で作成して実行を始めなくてはなりません。

The simplest way to achieve that is to create a Thread and run the event queue's dispatch method in the thread:

実現のための一番簡単な方法は、Threadを作成し、そのスレッドでイベントキューのdispatchメソッドを実行することです。

手作業(manually)とは書いてありますが、実際にはもちろんプログラムで実行します。
スレッドを作って、dispatchを呼び出して、細かいことはいいからコードを見てみましょう。

#include "mbed.h"

// Create a queue that can hold a maximum of 32 events
EventQueue queue(32 * EVENTS_EVENT_SIZE);
// Create a thread that'll run the event queue's dispatch function
Thread thread;

int main () {
    // Start the event queue's dispatch thread
    thread.start(callback(&queue, &EventQueue::dispatch_forever));
}

まず、EventQueueオブジェクトのインスタンスqueueを作っています。引数には、このインスタンスで使用するキューのバイト数を指定しています。キューの要素一つ当たりEVENTS_EVENT_SIZEの大きさが必要なので、それを32倍して32要素分の領域を確保しています。
次にThreadオブジェクトのthreadを作っています。引数を与えてスタックサイズなどを指定できるのですが、ここではデフォルトの値を使用するので、引数はありません。
main()の中では、threadインスタンスにcallback関数を与えて実行させています。ここでcallback()と書かれているのは、callback関数を返すtemplateのようで、要は、こういうことを意味しているようです。

#include "mbed.h"

// Create a queue that can hold a maximum of 32 events
EventQueue queue(32 * EVENTS_EVENT_SIZE);
// Create a thread that'll run the event queue's dispatch function
Thread thread;

void dispatchTask(void) {
    queue.dispatch_forever();
}

int main () {
    // Start the event queue's dispatch thread
    thread.start(dispatchTask);
}

ここで呼び出しているdispatch_foreverメソッドは、キューからイベントを取り出して実行するという手続きを繰り返す無限ループになっています。このループそのものを制御したいときには、別のdispatchメソッドも使用できます。

void dispatchTask(void) {
    DigitalOut led1(LED1);
    for (;;) {
        queue.dispatch(500);
        led1 = !led1;
    }
}

dispatchメソッドの引数には、timeoutの時間をミリ秒単位で与えます。このようにすると、イベントの到着が無かった場合には、dispatchメソッドを抜けて別の処理、例えばLEDを点滅させるなどの処理を行うことができます。

void dispatchTask(void) {
    queue.dispatch(-1);
}

また、負の値を与えた場合には、永遠にイベントの到着を待ちます。これは、dispatch_foreverメソッドと同じ振る舞いになります。

void dispatchTask(void) {
    for (;;) {
        queue1.dispatch(0);
        queue2.dispatch(0);
    }
}

引数にゼロを与えると、イベントキューにイベントが到着していない場合、すぐにdispatchメソッドを抜けてきます。そのため、このように複数のイベント処理を並べる書き方もできます。しかしながら、これではイベントを検出するためのループにCPUを喰われてしまいます。メモリに余裕があれば、それぞれのイベントキューに独立したThreadを与えた方が良いでしょう。

Note that though this document assumes the presence of a single event loop in the system, there's nothing preventing the programmer from running more than one event loop, simply by following the create/start pattern above for each of them.

この文書では、システムに単一のイベントループが存在すると仮定していますが、複数のイベントループを実行するのを妨げる理由は全くありません。それぞれのイベントループに対して「作成して・実行する」という手順を踏むだけです。

次は、作ったイベントループを使います。

関連サイト

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

関連記事

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

2
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
2
0