== セルタイプコードでのアロケータ == シグニチャの関数の引数の基本指定子として send または receive を指定すると、引数としてアロケータによりアロケートされたメモリ領域のアドレスが渡されます。 渡されたメモリ領域は、受け取った側で解放します。 send 指定された引数の場合、呼び元でアロケートし、呼び先でデアロケートします。 receive 指定された引数の場合、呼び先でアロケートし、呼び元でデアロケートします。 アロケート、デアロケート操作は、アロケータ呼び口を通して行います。 === アロケータ呼び口 === TECS では、メモリアロケータをセルとして実装しますが、アロケータセルの受け口に結合する呼び口が必要となります。 この呼び口のことをアロケータ呼び口と呼びます。 アロケータ呼び口は TECS CDL に明示的に記述しません。TECS ジェネレータにより生成されます。 アロケータ呼び口には、以下の名前が与えられます。 {{{ (アロケータ呼び口名) = (呼び口名または受け口名) + '_' + (関数名) + '_' + (引数名) }}} === アロケータ使用の具体例 === 以下に、アロケータを使用する例を示します。 TECS CDL のコード例には、呼び先のセルタイプおよびセル、呼び元のセルタイプおよびセルが実装されているとします。 ジェネレータによって呼び先および呼び元の双方に、アロケータ呼び口およびその結合が自動的に挿入されます。 【TECS CDL 記述例】 {{{ signature sSendRecv { /* この関数名に send, receive を使ってしまうと allocator 指定できない */ ER snd( [send(sAlloc),size_is(sz)]int8 *buf, [in]int32 sz ); ER rcv( [receive(sAllocTMO),size_is(*sz)]int8 **buf, [out]int32 *sz ); }; celltype tTestComponent { entry sSendRecv eS; }; // 受け口側で、send/receive 指定された引数ごとにアロケータを指定 [allocator(eS.snd.buf=alloc.eA,eS.rcv.buf=alloc.eA)] cell tTestComponent comp{ }; celltype tTestClient { call sSendRecv cS; }; // 呼び口側では、アロケータを指定しない cell tTestClient cl { cS = comp.eS; }; }}} 【アロケータ呼び口が挿入されたコード(TECS ジェネレータにより内部生成された状態)】 以下のコードは、内部状態を説明するためのものであって、以下のような TECS CDL コードを記述するものではありません。 {{{ celltype tTestComponent { entry sSendRecv eS; /* 自動生成されたアロケータ呼び口 */ call sAlloc cS_snd_buf; <<< 自動生成された呼び口 call sAlloc cS_rcv_buf; <<< 自動生成された呼び口 }; [allocator(eS.snd.buf=alloc.eA,eS.rcv.buf=alloc.eA)] cell tTestComponent comp{ /* 自動生成されたアロケータ呼び口の結合 */ eS_snd_buf = alloc.eA; <<< 自動生成された結合 eS_rcv_buf = alloc.eA; <<< 自動生成された結合 }; celltype tTestClient { call sSendRecv cS; /* 自動生成されたアロケータ呼び口 */ call sAlloc cS_snd_buf; <<< 自動生成された呼び口 call sAlloc cS_rcv_buf; <<< 自動生成された呼び口 }; cell tTestClient cl { cS = comp.eS; /* 自動生成されたアロケータ呼び口の結合 */ cS_snd_buf = alloc.eA; <<< 自動生成された結合 cS_rcv_buf = alloc.eA; <<< 自動生成された結合 }; }}} セルタイプ tTestClient の呼び口 cS の関数の send, receive 指定された引数に対して、以下のようなアロケータ呼び口関数が、生成されます。 アロケート関数、デアロケート関数の両方が使用できますが、send 指定された引数の場合、通常、呼び元で使用する必要があるのは、アロケート関数です。 rceive 指定された引数の場合は、デアロケート関数です。 {{{ // allocator port for call port: cS func: send param: buf ER cS_snd_buf_alloc( int32_t size, void** p ); ER cS_snd_buf_dealloc( const void* p ); // allocator port for call port: cS func: receive param: buf ER cS_rcv_buf_alloc( int32_t size, void** p ); ER cS_rcv_buf_dealloc( const void* p ); // allocator port for call port: cA func: send param: buf ER cA_snd_buf_alloc( subscript, int32_t size, void** p ); ER cA_snd_buf_dealloc( subscript, const void* p ); // allocator port for call port: cA func: receive param: buf ER cA_rcv_buf_alloc( subscript, int32_t size, void** p ); ER cA_rcv_buf_dealloc( subscript, const void* p ); }}} セルタイプ tTestComponent の受け口 eS の関数の send, receive 指定された引数に対しても、同様なアロケータ呼び口関数が、生成されます。 【未決定事項】アロケータを一々使い分けるのは、誤りのもとである。まとめる手段が必要。 === アロケータの例 === アロケータセルの例を以下に示します。 【TECS CDL 記述例】 {{{ signature sAlloc { ER alloc( [in]size_t len, [out]void *p ); ER dealloc( [in]void *p ); }; celltype tAlloc { entry sAlloc eA; }; cell alloc { }; }}} === リレーアロケータ === リレーアロケータの TECS CDL 記述例を示します。 【TECS CDL 記述例】 {{{ signature sSendRecv { /* この関数名に send, receive を使ってしまうと allocator 指定できない */ ER snd( [send(sAlloc),size_is(sz)]int8_t *buf, [in]int32_t sz ); ER rcv( [receive(sAlloc),size_is(*sz)]int8_t **buf, [out]int32_t *sz ); }; celltype tThroughComponent { [allocator( /* 受け口から呼び口へリレー */ snd.buf <= cSR.snd.buf, /* cSR:前方参照可能 */ rcv.buf <= cSR.rcv.buf )] entry sSendRecv eS; call sSendRecv cSR; }; /* セルの定義で、受け口の send/receive 指定された引数のアロケータ指定不要 */ cell tThroughComponent comp{ cSR = TargetCell.eS; /* TargetCell で allocator 指定が必要 */ }; }}} リレーアロケータの場合も、上述のアロケータの例と同様に、アロケータ呼び口と結合が生成されます。 tThroughComponent のセルタイプコードでは、以下のアロケータ呼び口関数が生成されます。 ただし、受け取ったものをそのまま渡すため、これらの呼び口関数は、実際には使用する必要はありません。 もし、受け取ったものをそのまま渡すのではなく、再アロケート(reallc) するような場合には、これらの呼び口を用いることになります。 (この例では realloc は含まれません) {{{ // allocator port for call port: eA func: snd param: buf ER eA_snd_buf_alloc( subscript, int32_t size, void** p ); ER eA_snd_buf_dealloc( subscript, const void* p ); // allocator port for call port: eA func: rcv param: buf ER eA_rcv_buf_alloc( subscript, int32_t size, void** p ); ER eA_rcv_buf_dealloc( subscript, const void* p ); // allocator port for call port: eS func: snd param: buf ER eS_snd_buf_alloc( int32_t size, void** p ); ER eS_snd_buf_dealloc( const void* p ); // allocator port for call port: eS func: rcv param: buf ER eS_rcv_buf_alloc( int32_t size, void** p ); ER eS_rcv_buf_dealloc( const void* p ); // allocator port for call port: cSR func: snd param: buf ER cSR_snd_buf_alloc( int32_t size, void** p ); ER cSR_snd_buf_dealloc( const void* p ); // allocator port for call port: cSR func: rcv param: buf ER cSR_rcv_buf_alloc( int32_t size, void** p ); ER cSR_rcv_buf_dealloc( const void* p ); }}} ------------ [TECS リファレンスマニュアル [wiki: トップ]] [TECS コンポーネント実装リファレンスマニュアル [wiki:IMPref トップ]・[wiki:IMPref_index 目次]]]