Windows版 iTRONサービスコールの作成 (データキュー)
(その6)

データキューからデータを受信する

データキューからデータを受信するサービスコールは以下のとおりです。


サービスコール名説明
rcv_dtq

タイムアウトなしでデータキューからデータを受信します。

prcv_dtq

ポーリング方式でデータキューからデータを受信します。

trcv_dtq

タイムアウト付きでデータキューからデータを受信します。

データキューからデータを受信する (タイムアウトなし)

タイムアウトなしでデータキューからデータを受信するには以下のサービスコールを使用します。



    ER rcv_dtq( ID dtqid, VP_INT *p_data )
	

引数説明
dtqid

データキューID番号。

p_data

データキューから取得したデータを格納する領域のポインタ。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のデータキューID番号。

E_NOEXS

指定したデータキューID番号は登録されていない。

E_PAR

パラメータエラー。

E_CTX

非コンテキスト・タスクからの呼び出し。


・サービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  データキューからの受信 (タイムアウトなし).
 *
 *  @param  [in]    dtqid   データキューID番号.
 *  @param  [out]   p_data  データキューから受信したデータを格納する領域のポインタ.
 *
 *  @retval エラーコード.
 */
ER      rcv_dtq( ID dtqid, VP_INT *p_data )
{
    //! タイムアウトなしでデータキューからデータを受信する.
    return trcv_dtq( dtqid, p_data, TMO_FEVR );
}
	

trcv_dtq()のタイムアウト設定に TMO_FEVR を指定して呼び出します。

データキューにデータが無い場合は、データキューにデータが格納されるまでタスクをスリープさせます。

データキューからデータを受信する (ポーリング)

ポーリングでデータキューからデータを受信するには以下のサービスコールを使用します。



    ER prcv_dtq( ID dtqid, VP_INT *p_data )
	

引数説明
dtqid

データキューID番号。

p_data

データキューから取得したデータを格納する領域のポインタ。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のデータキューID番号。

E_NOEXS

指定したデータキューID番号は登録されていない。

E_PAR

パラメータエラー。

E_TMOUT

データキューにデータが無い。


・サービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  データキューからの受信 (ポーリング).
 *
 *  @param  [in]    dtqid   データキューID番号.
 *  @param  [out]   p_data  データキューから受信したデータを格納する領域のポインタ.
 *
 *  @retval エラーコード.
 */
ER      prcv_dtq( ID dtqid, VP_INT *p_data )
{
    //! データ受信待ちなしでデータキューからデータを受信する.
    return trcv_dtq( dtqid, p_data, TMO_POL );
}
	

trcv_dtq()のタイムアウト設定に TMO_POL を指定して呼び出します。

データキューにデータが無い場合は、タスクをスリープさせずに戻り値をE_TMOUTとしてすぐにサービスコールから戻ります。

データキューからデータを受信する (タイムアウト付き)

タイムアウト付きでデータキューからデータを受信するには以下のサービスコールを使用します。



    ER trcv_dtq( ID dtqid, VP_INT *p_data, TMO tmout )
	

引数説明
dtqid

データキューID番号。

p_data

データキューから取得したデータを格納する領域のポインタ。

tmout

タイムアウトの設定値。

  • TMO_FEVRの場合、永久にデータキューにデータがセットされるのを待ちます。
  • TMO_POLの場合、データキューにデータが無くてもタスクをスリープしません。
  • その他の正数はタイムアウト値となります。

戻り値説明
E_OK

正常終了。

E_ID

範囲外のデータキューID番号。

E_NOEXS

指定したデータキューID番号は登録されていない。

E_TMOUT

データキューにデータが無くてタイムアウト。

E_PAR

パラメータエラー。

E_CTX

非コンテキスト・タスクからの呼び出し。


・サービスコールのソースコードは以下のようになります。


/****************************************************************************/
/*!
 *  @brief  データキューからの受信 (タイムアウトあり).
 *
 *  @param  [in]    dtqid   データキューID番号.
 *  @param  [out]   p_data  データキューから受信したデータを格納する領域のポインタ.
 *  @param  [in]    tmout   タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      trcv_dtq( ID dtqid, VP_INT *p_data, TMO tmout )
{
    ER      ercd;
    DWORD   data;

    //! 引数が不正な場合はエラーにする.
    if( !p_data ){
        return E_PAR;
    }
    wi_CommonLock();

    //! データキューからデータを受信する.
    ercd = wi_ReceiveDataQueue( dtqid, &data, tmout );
    if( ercd == E_OK ){
        *p_data = (VP_INT)data;
    }
    wi_CommonUnlock();
    return ercd;
}
	

指定したデータキューからデータを取得します。

データキューにデータが無い場合は、データキューにデータが格納されるか、タイムアウトで設定した時間が経過するまでタスクをスリープさせます。

データキューからデータを取得する関数

データキューからデータを取得する関数のソースコードは以下のとおりです。



/****************************************************************************/
/*!
 *  @brief  データキューからの受信.
 *
 *  @param  [in]    id      データキューID番号.
 *  @param  [out]   data    データキューから受信したデータを格納する領域のポインタ.
 *  @param  [in]    tmout   タイムアウト設定.
 *
 *  @retval エラーコード.
 */
ER      wi_ReceiveDataQueue( INT id, DWORD *data, TMO tmout )
{
    ER          ercd;
    WIDTQOBJ    *p;
    WITSKOBJ    *tsk;

    //! データキューIDのオブジェクトを取得する.
    p = (WIDTQOBJ *)wi_FindObject( id, TMAX_MAXDTQ, ObjList, &ercd );
    if( !p ){
        return ercd;
    }
    //! 引数が不正な場合はエラーにする.
    if( !data ){
        return E_PAR;
    }
    //! データキューバッファを確保していない場合.
    if( p->QueSize == 0 || !p->QueBuf ){

        if( p->SndWaitQue ){
            tsk = (WITSKOBJ *)(p->SndWaitQue);

            //! 送信メッセージを取り出す.
            *data = (DWORD)(tsk->Param[0]);

            //! メッセージ受信先を待っているタスクを起床させる.
            wi_TaskWakeup( tsk->Hdr.Id, TTW_SDTQ, &(p->SndWaitQue) );
            return E_OK;
        }else{
            //! メッセージが送信されるまでタスクをスリープさせる.
            ercd = wi_TaskWait( id, TTW_RDTQ, tmout, p->Attribute, &(p->RcvWaitQue) );
            if( ercd == E_OK ){
                //! 送信メッセージを取り出す.
                tsk = wi_GetTaskObject( TSK_SELF );
                if( tsk ){
                    *data = (DWORD)(tsk->Param[0]);
                }
            }
            return ercd;
        }
    }
    //! データキューにデータがある場合、データを取り出して終了する.
    if( p->GetPos != p->PutPos ){

        //! データキューの先頭からデータを取り出す.
        *data = p->QueBuf[p->GetPos];

        //! データキューの読み出し位置を更新する.
        p->GetPos = wi_IncRingPositon( p->GetPos, p->QueSize );

        //! バッファが空くのを待っているタスクがある場合はタスクを起床させる.
        if( p->SndWaitQue ){
            wi_TaskWakeup( p->SndWaitQue->Id, TTW_SDTQ, &(p->SndWaitQue) );
        }
        return E_OK;
    }
    //! メッセージを受信するまでタスクをスリープさせる.
    ercd = wi_TaskWait( id, TTW_RDTQ, tmout, p->Attribute, &(p->RcvWaitQue) );
    if( ercd == E_OK ){
        if( p->GetPos != p->PutPos ){
            //! データキューの先頭からデータを取り出す.
            *data = p->QueBuf[p->GetPos];

            //! データキューの読み出し位置を更新する.
            p->GetPos = wi_IncRingPositon( p->GetPos, p->QueSize );
        }
    }
    return ercd;
}
	

データキューからデータを取得する関数は以下のような処理を行います。

  • 引数で指定されたデータキューID番号に該当するデータキュー・オブジェクトを取り出します。
  • データキューのバッファを確保していない場合、メッセージ送信待ちをしているタスクがあれば、送信データを受け取って正常終了します。このとき送信待ちをしているタスクを起床します。
    メッセージ送信待ちをしているタスクがない場合はメッセージが送信されるまでタスクをスリープさせます。
  • データキューのバッファにデータがある場合はバッファから先頭のデータを取り出して正常終了にします。バッファが空くのを待っているタスクがある場合は、そのタスクを起床して終了にします。
  • データキューのバッファにデータがない場合、メッセージを送信されるか、タイムアウトになるまでタスクをスリープさせます。
  • タスクのスリープから復帰したときに正常終了で復帰した場合のみ、データキューのバッファの先頭からデータを取り出します。


Windowsは米国Microsoft Corporationの登録商標です。