ダウンロード
最新バージョン : 2.1.0-RELESE
| 2.1.0-RELESE | ダウンロードページ |
OpenRTM@Github
OpenRTM-aist GitHubサイト
ROS
Robot Operating System
Choreonoid
モーションエディタ/シミュレータ
DAQ-Middleware
ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク
産総研が提供するRTC集
東京オープンソースロボティクス協会
| 2.1.0-RELESE | ダウンロードページ |
OpenRTM-aist GitHubサイト
Robot Operating System
モーションエディタ/シミュレータ
ネットワーク分散環境でデータ収集用ソフトウェアを容易に構築するためのソフトウェア・フレームワーク
産総研が提供するRTC集
東京オープンソースロボティクス協会
구조체·/오브젝트 레퍼런스
CORBA 의 구조체는 C++ 에 대하고, 구조체 "struct" 에 매핑 된다.
// -*- IDL -*- struct Profile { short short_value; long long_value; };// -*- C++ -*- struct Profile { CORBA::Short short_value; CORBA::Long long_value; };class Profile_var { };구조체에 가변장의 멤버 (string, wstring, sequence, (가변장 멤버를 가지는 struct, 가변장 멤버를 가지는 union)가 포함되어 있으면, 구조체는 가변장 데이터로 간주해집니다. 이 경우, 고정장의 구조체와는 다른 C++ 코드가 생성되어 반환값이나 out 파라미터에 있어서의 취급이 다릅니다.
가변장의 구조체로서 _var 클래스를 사용하는 경우, 가변장의 멤버가 할당할 수 있는 메모리는 자동적으로 관리됩니다.
_var 형
변환 constructor (T_ptr)
_CORBA_ObjRef_Var(T_ptr p) : pd_objref(p) {}_ptr형의 오브젝트 참조의 소유권은_var형으로 옮기기 위해, 참조 카운트의 증감은 없다.
변환 constructor (const T_var&)
Object_var(const T_var& p) : pd_ref(T::_duplicate(p.pd_ref)) {}대입원의_var형의 오브젝트 참조의 소유권은 카피된다.
변환 constructor (const T_member)
in인수와 in() 함수
단순하게 오브젝트 참조의_ptr형 포인터를 돌려준다. 소유권의 이동은 일어나지 않는다.
T_ptr in() const { return pd_objref; }통상, 함수의in인수에 오브젝트 참조를 건네줄 때에 사용한다. 오브젝트 참조가 주어진 측의 함수는, 소유권을 가지지 않기 때문에 함수내에서release해선 안 된다. 함수로부터 돌아온 뒤, _var형 변수에 여전히 소유권이 보관 유지되고 있어_var형 변수의 해체시에 오브젝트는release된다.
오브젝트 참조를in인수로서 받는 함수를 정의하는 경우는, _ptr형의 인수로서 정의한다.게다가 함수내에서는, 그 오브젝트의 오퍼레이션을 부르는 것만으로,release등은 가선 안 된다. 또, 함수내에서 오브젝트 참조를 어딘가(글로벌 변수, static 변수, 오브젝트의 멤버등 )에 보존하고 싶은 경우는, 소유권을 카피하기 위해(때문에) duplicate 함수로 복제할 필요가 있다.
void myfunc(MyObject_ptr obj) { obj->function(); CORBA::release(obj); // ×이것은 해선 안 된다 m_obj = obj; // ×소유권을 가지고 있지 않다 m_obj = MyObject::duplicate(obj); // ○소유권을 복제 } {// 다른 문맥 MyObject_var obj(hoge->get_object()); myfunc(obj.in()); // 소유권의 이행은 일어나지 않는다 } // 스코프를 빠졌으므로 참조 카운트가 감소 된다out 인수와 out() 함수
현재 소유하고 있는 참조를release(참조 카운트를 감소) 하고, 레퍼런스의 포인터를 nil에 세트 해 돌려준다. 즉,out()함수 호출 이전에도 해 오브젝트 참조를 보관 유지하고 있는 경우는 그 소유권을 방폐해 참조는 파기된다.
T_ptr& out() { T_Helper::release(pd_objref); pd_objref = T_Helper::_nil(); return pd_objref; }통상, 함수의out인수에 오브젝트 참조를 건네줄 때에 사용한다.즉, 함수로부터 돌아온 뒤, 이 변수에 새롭게 오브젝트 참조가 보관 유지되고 있는 것이 기대된다. 이 때, 오브젝트 참조의 소유권은 이 변수에 보관 유지되고 있다고 생각한다. out()로 변수를 건네받은 함수측에서는, 어떠한 형태로 오브젝트 참조를 생성 또는 복제하고, 인수에 소유권을 건네줄 필요가 있다.
오브젝트 참조를out인수로서 받는 함수를 정의하는 경우는, _ptr형 참조의 인수로서 정의한다.함수내에서는, 인수는 반드시 nil 오브젝트 참조이며, 한편 통상 어떠한 오브젝트를 소유권을 주어 대입하는 것이 기대된다.
void myfunc(MyObject_ptr& obj) { assert(CORBA::is_nil(obj)); // 반드시 nil 오브젝트 obj->function(); // nil이므로 오퍼레이션은 부를 수 없다 // m_obj 는_var형의 멤버 변수 obj = m_obj; // ×소유권을 복제하고 있지 않다. // return 후, 함수의 밖에서 마음대로 release 될지도 모른다. obj = MyObject::duplicate(obj); // ○소유권을 복제하고 있다. // return 후, 함수의 밖에서 release 되어도, 오브젝트 참조는 해체되지 않는다. return; } {// 다른 문맥 MyObject_var obj; obj = get_object(); // △out 변수로서 사용하므로 건네주기 전에는 아무것도 들어갈 수 없는 것이 좋다 myfunc(obj.out()); // 오브젝트가 대입되어 되돌아 왔을 것 assert(!CORBA::is_nil(obj)); obj->function(); } // 스코프를 빠졌으므로 참조 카운트가 감소 된다.inout()
레퍼런스에의 포인터의 참조를 돌려준다.
T_ptr& inout() { return pd_objref; }통상, 함수의inout인수에 오브젝트 참조를 건네줄 때에 사용한다. 즉, 함수내에서는 어떠한 오브젝트 참조가 인수에 들어가 있는 것이 기대되어 오브젝트의 소유권은 함수 측에 옮긴다.또, 함수는 어떠한 오브젝트 참조를 이 인수에게 주어 돌려주는 것이 기대되어 인수 즉 호출해 원의 변수에 소유권을 준다. 함수내에서는 인수에 오브젝트 참조를 새롭게 세트 하는 경우는, 우선release하고 나서 새로운 오브젝트 참조를 생성 또는 복제해 인수에 소유권을 건네줄 필요가 있다.
오브젝트 참조를inout인수로서 취하는 함수는, 설계의 관점으로부터 별로 추천 되지 않는다.만약,inout인수로서 취하는 함수를 정의할 필요가 있는 경우는, _ptr형 참조의 인수로서 정의한다.
void myfunc(MyObject_ptr& obj) { if (!CORBA::is_nil(obj)) { obj->function(); // obj 가 nil가 아니면 오퍼레이션을 부를 수 있다. } CORBA::release(obj); // release 할 책임은 이 함수에 있다 /* * 이 함수내에서, obj에 새로운 오브젝트 참조가 있는 경우에 한정해, * 인수를 받은 직후에, _var 변수에 대입해 두는 것으로, * 함수 종료시에 자동적으로 참조 카운트를 감소 * 하는 테크닉을 사용해도 괜찮다. * MyObject_var deleter = obj; */ // MyObject_var m_obj 로 한다 obj = m_obj; // × 소유권을 복제하고 있지 않다 // return 후, 함수의 밖에서 release 될지도 모른다. obj = MyObject::_duplicate(m_obj); // ○ obj 에도 MyObject의 소유권이 주어졌다 // return 후, 함수의 밖에서 release 되어도, 오브젝트 참조는 해체되지 않는다. } {// 다른 문맥 MyObject_var obj; obj = get_object(); // obj 는 소유권을 가지고 있다 myfunc(obj); // 함수내에서 releae 된다 // obj 가 가리키는 것은 바뀌고 있을지도 모르다. } // 스코프를 빠졌으므로 참조 카운트가 감소 된다._retn()
현재 가지고 있는 오브젝트 참조의 소유권을 방폐하고 포인터를 돌려준다.
T_ptr _retn() { T_ptr tmp = pd_objref; pd_objref = T_Helper::_nil(); return tmp; }통상, 함수의 반환값에 오브젝트 참조를 돌려주는 경우에 사용된다. 소유권은 함수의 호출 측에 건너므로, 호출측에서는 오브젝트 참조를 파기할 책임이 있다.따라서, 호출측에서 release 하는지, _var형 변수로 받을 필요가 있다.
반대로, 반환값으로 오브젝트 참조를 돌려주는 경우, 호출측에서는 반드시 release에 의해 참조 카운트가 감소 되기 위해, 함수내에서는 _duplicate()등에서 소유권을 복제해 둘 필요가 있다.
MyObject_ptr myfunc() { MyObject_var ret; ret = m_obj; // ×소유권이 ret로 옮겨져 버린다. // return 후, 함수의 밖에서 release 될지도 모른다. ret = MyObject::_duplicate(m_obj); // ○소유권의 복제 // return 후, release가 불려도, m_obj 는 소유권을 계속 보관 유지한다. return ret._retn(); } { // 다른 문맥 MyObject_var obj; obj = myfunc(); // 오브젝트의 소유권을 취득 obj->function(); MyObject_ptr ptr; ptr = myfunc(); //오브젝트의 소유권을 취득 ptr->function(); CORBA::release(ptr); // 참조 카운트를 감소 } // 스코프를 빠졌으므로 참조 카운트가 감소 된다규칙의 정리
_var형, _ptr형의 대입으로의 레퍼런스 카운트
_ptr형에의_var형의 대입
포인터에의 대입.
복제 이루어, 해방하지 않고.
{ MyObject_var var; var = myfunc(); // 오브젝트의 소유권을 취득 MyObject_ptr ptr ptr = MyObject::_duplicate(var); //오브젝트의 소유권을 취득(참조 카운트의 인크리먼트(increment)) // ptr = var; // 이것은 참조 카운트 에러를 일으킬 우려가 있다.호출 후, ptr와 var는 같은 오브젝트 // (을)를 찌를 것이다가, 참조 카운트의 보수는 이루어지는거야.var는, 그 대상 오브젝트의 소지를 유지 // 한다.또, ptr가 그것이 이전에 가리키고 있던 오브젝트나 프록시에의 유일한 포인터였다 // 그렇다면, 메모리 리크가 생긴다. CORBA::release(ptr); // 참조 카운트를 감소 } // var에 관해서는, 스코프를 빠졌으므로 참조 카운트가 감소 된다_var형에의_ptr형의 대입
_var가 보유하고 있는 오브젝트에 대해서 release() 되지만, 인수로 건네받은_ptr형의 오브젝트에 대해서는 duplicate() 되지 않는다.
복제 이루어, 해방 있어.
inline T_var& operator= (T_ptr p) { T_Helper::release(pd_objref); pd_objref = p; return *this; }{ MyObject_ptr ptr; ptr = myfunc(); // 오브젝트의 소유권을 취득 MyObject_var obj; obj = MyObject::_duplicate(ptr); //오브젝트의 소유권을 취득(참조 카운트의 인크리먼트(increment)) CORBA::release(ptr); // 참조 카운트를 감소 } // obj에 관해서는, 스코프를 빠졌으므로 참조 카운트가 감소 된다_var형에의_var형의 대입
_var가 보유하고 있는 오브젝트에 대해서 release()가 콜 되어 한편, 인수로 건네받은 오브젝트에 대해서도 duplicate()가 콜 된다.
복제 있어, 해방 있어.
inline T_var& operator= (const T_var& p) { if( &p != this ) { T_Helper::duplicate(p.pd_objref); T_Helper::release(pd_objref); pd_objref = p.pd_objref; } return *this; }{ MyObject_var var1; var1 = myfunc(); // 오브젝트의 소유권을 취득 MyObject_var var2; var2 = var1; //오브젝트의 소유권을 취득(참조 카운트는 자동으로 인크리먼트(increment) 된다) } // var1, var2에 관해서는, 스코프를 빠졌으므로 참조 카운트가 감소 된다_narrow()로의 레퍼런스 카운트
_narrow() 처리의 과정에 대하고, _narrow()의 호출이 성공했을 경우, 그 대상 오브젝트의 레퍼런스 카운트는 인크리먼트(increment) 되지만, 실패했을 경우는 인크리먼트(increment) 되지 않는다.
감소는 행해지지 않는다.
RTC::RTObject_ptr RTC::RTObject::_narrow(::CORBA::Object_ptr obj) { if( !obj || obj->_NP_is_nil() || obj->_NP_is_pseudo() ) return _nil(); _ptr_type e = (_ptr_type) obj->_PR_getobj()->_realNarrow(_PD_repoId); return e ? e : _nil(); }void* omniObjRef::_realNarrow(const char* repoId) { // Attempt to narrow the reference using static type info. void* target = _ptrToObjRef(repoId); if( target ) { if (!lid || (lid && !lid->deactivated() && lid->servant() && lid->servant()->_ptrToInterface(repoId))) { omni::duplicateObjRef(this); } else { omniObjRef* objref; omniIOR* ior; { ior = pd_ior->duplicateNoLock(); } { objref = omni::createObjRef(repoId,ior,1,0); } } } else { if( _real_is_a(repoId) ) { omniObjRef* objref; omniIOR* ior; { ior = pd_ior->duplicateNoLock(); } { objref = omni::createObjRef(repoId,ior,1,_identity()); } } } } return target; }규칙
클라이언트측
클라이언트가 호출로부터 오브젝트 참조를 수신한다면, 그 클라이언트는 그 오브젝트 참조가 불필요해졌을 때에는 그것을 개방하지 않으면 안 된다.
(인용: 「CORBA 분산 오브젝트 Orbix를 이용해」 P.98 오브젝트 참조를 위한 메모리 메니지먼트)
서버측
호출 측에 건네주는 참조의 소유권은 방폐된다(즉, 그 참조 카운트는 하나 감소 된다.따라서, 통상은, 참조를 돌려주기 전에 적당한 _duplicate() 함수를 호출하게 된다)
(인용: 「CORBA 분산 오브젝트 Orbix를 이용해」 P.98 오브젝트 참조를 위한 메모리 메니지먼트)
참고 문헌