前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

20.3. コールバッククラス

コールバックを処理するためのクラスとして、 SFXCallback / SFXTimer / SFXTask クラスがあります。

SFXTimer クラスと SFXTask クラスは、 共に SFXCallback クラスを利用して実装されています。

20.3.1. SFXCallback クラス

SFXCallback クラスは、 コールバック処理の核となるクラスです。 内部に BREW 環境とコールバック情報を受け渡しするための BREW API AEECallback 構造体を保持し、 コールバックのパラメータ設定や、コールバック登録の確認やキャンセルを行えます。

SFXCallback::Set 関数では、 以下のように BREW API CALLBACK_Init 関数を呼び出して、 SFXCallback クラスが内部に保持する BREW API AEECallback 構造体に、 コールバック関数とコールバック関数に渡すデータを設定しています。

例 20.8. SFXCallback::Set 関数の実装

class SFXCallback {

    ...

    private:
        SFXCallback クラスは AEECallback 構造体を内部に保持する
        AEECallback _callback;

    ...

}

/*public */Void SFXCallback::Set(CallbackSPP spp, VoidPtr reference)
{
    _callback に登録済みのコールバックをキャンセルする
    Cancel();

    _callback のデータをクリアする
    SFXHelper::memset(&_callback, 0, sizeof(_callback));

    _callback をコールバック関数とコールバック関数に渡すデータで初期化する
    CALLBACK_Init(&_callback, spp, reference);
    return;
}// SFXCallback::Set //

interface_cast 演算子により、 SFXCallback クラスを BREW API AEECallback 構造体にキャストできます。 また、この逆のキャストも可能です。

一般に、この演算子を利用して BREW API と SophiaFramework UNIVERSE とで BREW API AEECallback 構造体の受け渡しを行います。

interface_cast 演算子を使用して、 SFXCallback クラスを AEECallback 構造体に変換し、 BREW API ISHELL_SetTimerEx 関数に渡すコードは、以下の通りです。

例 20.9. SFXCallback クラスを AEECallback 構造体に変換して BREW API に渡す方法

/*public */inline SFCError SFBShell::SetTimerEx(SInt32 mSecs, SFXCallbackPtr callback)
{
    return ISHELL_SetTimerEx(interface_cast(this), mSecs, interface_cast(callback));
}// SFBShell::SetTimerEx //
[Note] SFXCallback クラス

SFXCallback クラスは、 ストレージ系クラスの読み書きで使用されるコールバックや、 タイマー(SFXTimer、タスク(SFXTask)の実装で利用されています。

20.3.2. SFXTimer クラス

SFXTimer クラスは、 タイマー(指定時間が経過したときに処理を実行させるコールバック)を扱うためのクラスです。

SFXTimer クラスは、以下の手順で使用します。

  1. SFXTimer::Set 関数を呼び出してタイマーの情報(コールバック関数とコールバック関数に渡すデータ)を設定します。
  2. SFXTimer::Schedule 関数を呼び出してタイマーをスケジュールします(コールバックを AEE シェルに登録します)。 この関数の引数には、コールバックが呼び出されるまでの経過時間をミリ秒単位で指定します。
  3. SFXTimer::Schedule 関数の引数で指定した時間が経過すると、コールバックが呼び出されます。
  4. コールバックが呼び出されるまでに SFXTimer::Cancel 関数を呼び出すと、 スケジュールされていたタイマー(コールバックの登録)はキャンセルされます。
[Note] 内部の実装

SFXTimer クラスは、SFXCallback クラスを利用して実装されています。 タイマーのスケジュール(コールバックの登録)は、内部で BREW API ISHELL_SetTimerEx 関数を呼び出して行います。

例 20.10. SFXTimer クラスの使用方法

// SFXTimer インスタンスはクラスのメンバ変数として定義する
class MyClass {
private:
    SFXTimer _timer;
public:
    Void Start(Void);
    
    // コールバック関数
    XALLBACK_DECLARE_SFXTIMER(OnTimer)
};

Void MyClass::Start(Void)
{
    SFCError error;

    // タイマーにより呼び出される OnTimer 関数を設定する
    _timer.Set(XALLBACK_INTERNAL(OnTimer));

    // タイマーをスケジュールする
    // (1000 ミリ秒後に OnTimer 関数が呼び出される )
    error = _timer.Schedule(1000);

    if (error != SFERR_NO_ERROR) {
        // エラーのとき ( OnTimer 関数は呼び出されない )
    }
}

// タイマーによって呼び出されるコールバック関数
XALLBACK_IMPLEMENT_SFXTIMER(MyClass, OnTimer)
{
    TRACE("timer");
    
    // 以下のコードを追加すると、1000 ミリ秒毎にタイマーが呼び出されるようになる
    // _timer.Schedule(1000);
}
[Caution] SFXTimer インスタンスの保持

タイマーを利用しているときは、 SFXTimer インスタンスを解放してはいけません。

例 20.11. タイマーのキャンセル

// タイマーをキャンセルする
// この関数は任意の場所から呼び出してよい
_timer.Cancel();

SFXTimer::Cancel 関数は、 SFXTimer::~SFXTimer デストラクタや SFXTimer::Schedule / SFXTimer::Set 関数からも呼ばれます。

20.3.3. SFXTask クラス

SFXTask クラスは、 タスク(次回のイベントループ時に呼び出されるコールバック) を扱うためのクラスです。 このクラスは、主に協調的なマルチタスクの処理を実現するときに利用されます。

SFXTask クラスは、以下の手順で使用します。

  1. SFXTask::Set 関数を呼び出してタスクの情報(コールバック関数とコールバック関数に渡すデータ)を設定します。
  2. SFXTask::Schedule 関数を呼び出してタスクをスケジュールします(コールバックを AEE シェルに登録します)。
  3. 次回のイベントループで登録されたコールバックが呼び出されます。
  4. コールバックが呼び出されるまでに SFXTask::Cancel 関数を呼び出すと、 スケジュールされていたタスク(コールバックの登録)はキャンセルされます。
[Note] 内部の実装

SFXTask クラスは、SFXCallback クラスを利用して実装されています。 タスクのスケジュール(コールバックの登録)は、内部で BREW API ISHELL_Resume 関数を呼び出して行います。

BREW 環境では、約 1 秒以内で処理を終える必要があります。 そのため、1 秒以上時間がかかる処理は、 SFXTask クラスを使用して 1 秒以内で終了する処理に分割して実行します。 以下は、ひとつの処理を複数のタスクに分割して実行するコードです。

例 20.12. タスク分割

// SFXTask インスタンスはクラスのメンバ変数として定義する
class MyClass {
private:
    SFXTask _task;
    SInt32 _index;
    SInt32 _sum;
public:
    Void Start(Void);
    SInt32 Calculate(SInt32 index);

    // コールバック関数
    XALLBACK_DECLARE_SFXTASK(OnTask)
};

Void MyClass::Start(Void)
{
    SFCError error;

    _index = 1;
    _sum = 0;

    // タスクのスケジュールに必要な情報を設定する
    // ※ OnTask コールバック関数と OnTask コールバック関数に渡すデータ)を設定する
    _task.Set(XALLBACK_INTERNAL(OnTask));

    // タスクをスケジュールする
    // ※ 次回イベントループで OnTask コールバック関数が呼び出される
    error = _task.Schedule();

    if (error != SFERR_NO_ERROR) {
        // エラーのとき ( OnTask 関数は呼び出されない )
    }
    
    // このコードが終了すると、制御が BREW 環境に戻り、
    // 次回イベントループで BREW 環境から OnTask 関数が呼び出される
}

// 時間のかかる計算
SInt32 MyClass::Calculate(SInt32 index)
{
    SInt32 i;
    for (i = 0; i < 5000000; ++i) {
        ;
    }
    return index;
}

// 次回イベントループで BREW 環境から呼び出される OnTask コールバック関数
XALLBACK_IMPLEMENT_SFXTASK(MyClass, OnTask)
{
    SFCError error;

    // ひとつの計算を 100 回に分割して行う

    if (_index <= 100) { 

        // _index 回目の計算を行う
        _sum += Calculate(_index);
        ++_index;
        // タスクをスケジュールする
        // 次回イベントループで OnTask コールバック関数が呼び出される
        error = _task.Schedule();

        if (error != SFERR_NO_ERROR) {

            // エラーのとき ( OnTask コールバック関数は呼び出されない )
        }
    }
    else {

        // 結果を表示する
        TRACE("%d", _sum);
    }
}

上記コードは、以下のコードと同等の計算を行います。

SInt32 i;
SInt32 sum = 0;
for (i = 1; i <= 100; ++i) {
    sum += Calculate(i);
}

例 20.13. タスクのキャンセル

// タスクをキャンセルする
// この関数は任意の場所から呼び出してよい
_task.Cancel();

SFXTask::Cancel 関数は、 SFXTask::~SFXTask デストラクタや SFXTask::Schedule / SFXTask::Set 関数からも呼ばれます。