20.8.4 Sequence

固定長および可変長に関係なくIDLに指定したSequenceは,現在の長さおよび最大長を持つC++クラスにマッピングされます。固定長シーケンスの最大長は,そのシーケンスの型によって定義されます。C++コンストラクタが呼び出される際に可変長シーケンスの最大長を指定できます。プログラミングによって,現在の長さを変更できます。コードサンプル20-28~20-29では,IDLシーケンスがアクセッサメソッドを含むC++クラスへとマッピングされています。

可変長シーケンスの長さが,指定した最大長よりも長い場合,Borland Enterprise Server VisiBrokerは,バッファが大きい方を透過的に割り当てます。その際,古いバッファが新しいバッファへとコピーされ,その古いバッファに割り当てられていたメモリが解放されます。しかし,最大長が減ると,使用されなかったメモリは解放されません。
コードサンプル20-28 IDL可変長シーケンス

// IDL
typedef sequence<long> LongSeq;

コードサンプル20-29 IDL可変長シーケンスのC++クラスへのマッピング

// C++
class LongSeq
{
   public:
       LongSeq(CORBA::ULong max=0);
       LongSeq(CORBA::ULong max=0, CORBA::ULong length,
               CORBA::Long *data, CORBA::Boolean release = 0);
       LongSeq(const LongSeq&);
       ~LongSeq();
       LongSeq&    operator=(const LongSeq&);
       CORBA::ULong    maximum() const;
       void   length(CORBA::ULong len);
       CORBA::ULong    length() const;
       const CORBA::ULong&    operator[ ](
                                 CORBA::ULong index) const;
       ...
       static LongSeq    *_duplicate(LongSeq* ptr);
       static void    _release(LongSeq *ptr);
       static CORBA::Long    *allocbuf(CORBA::ULong nelems);
       static void    freebuf(CORBA::Long *data);
   private:
       CORBA::Long* _contents;
       CORBA::ULong   _count;
       CORBA::ULong   _num_allocated;
       CORBA::Boolean   _release_flag;
       CORBA::Long   _ref_count;
};

コードサンプル20-29に示した可変長シーケンスのために生成されたメソッド一覧を次の表に示します。

表20-4 コードサンプル20-29に示した可変長シーケンスのために生成されたメソッドの一覧(C++)

メソッド説明
LongSeq(CORBA::ULong max=0)可変長シーケンスのコンストラクタは,最大長を引数として使用します。固定長シーケンスには定義された最大長が含まれます。
LongSeq(CORBA::Ulong max=0,
CORBA::ULong length,
CORBA::Long *data,
CORBA::Boolean release=0)
コンストラクタで,最大長,現在の長さ,対応するデータバッファのポインタ,解放フラグを設定できます。releaseが0でない場合にシーケンスのサイズを拡大する際,データバッファに対応するメモリを解放します。releaseが0である場合,古いデータバッファのメモリは解放されません。固定長シーケンスでは,max以外のこれらすべてのパラメタを使用します。
LongSeq(const LongSeq&)コピーコンストラクタは,ソースオブジェクトのディープコピーを実行します。
~LongSeq();解放フラグが構成された際に0以外の値を持つ場合だけ,デストラクタがシーケンスによって所有されるメモリを解放します。
operator=(const LongSeq&)代入演算子がディープコピーを実行します。必要な場合,古いメモリを解放します。
maximum()シーケンスのサイズを返します。
length()シーケンスの長さを設定したり,返したりするために,二つのメソッドが定義されます。
operator[ ] ()シーケンス内の要素にアクセスするために二つのインデックス演算子が提供されています。一方はその要素を修正するための演算子で,もう一方は要素を読み込むためだけ(読み取り専用)の演算子です。
_release()シーケンスを解放します。オブジェクトが生成され,シーケンス要素型が文字列およびオブジェクトリファレンスである場合で,コンストラクタの解放フラグが0以外の値であるときは,バッファが解放される前に各要素が解放されます。
allocbuf()
freebuf()
シーケンス用のメモリを割り当てたり,解放したりするために,これら二つの静的メソッドを使用します。
<この項の構成>
(1) シーケンスの管理型
(2) シーケンスでのメモリ管理

(1) シーケンスの管理型

コードサンプル20-29に示したLongSeqクラスに加えて,LongSeq_varクラスも生成されます。_varの詳細については,「21.6 <class_name>_var」を参照してください。また,通常の_varメソッドに加えて,シーケンスのインデックスメソッドが二つ定義されています。

コードサンプル20-30 シーケンスを表す_varクラスに追加された二つのインデックスメソッド

CORBA::Long& operator[ ](CORBA::ULong index);
const CORBA::Long& operator[ ](CORBA::ULong index) const;

(2) シーケンスでのメモリ管理

メモリ管理をする際には,次の事項に注意してください。コードサンプル20-31~20-32は,次の事項を配慮しています。

コードサンプル20-31 固定長シーケンスのIDL仕様

// IDL
typedef sequence<string, 3> StringSeq;

コードサンプル20-32 二つの固定長シーケンスでのメモリ管理の例

// C++
char *static_array[ ] = {(char*)"1", (char*)"2", (char*)"3"};
char **dynamic_array = StringSeq::allocbuf(3);
dynamic_array[0] = CORBA::string_dup("1");
dynamic_array[1] = CORBA::string_dup("2");
dynamic_array[2] = CORBA::string_dup("3");

// シーケンスを作成し,解放フラグはデフォルトのFALSEを設定します。
StringSeq static_seq(3, static_array);

// 別のシーケンスを作成し,解放フラグはTRUEを設定します。
StringSeq dynamic_seq(3, dynamic_array, 1);

static_seq[1] = "1"; // 古い領域は,解放されないでコピーされます。

char *str = CORBA::string_dup("1");
dynamic_seq[1] = str; // 古い領域は,解放され代入されます。