• Nenhum resultado encontrado

CORBA C++ Tecgraf PUC-Rio. Outubro de 2013

N/A
N/A
Protected

Academic year: 2022

Share "CORBA C++ Tecgraf PUC-Rio. Outubro de 2013"

Copied!
46
0
0

Texto

(1)

Tecgraf PUC-Rio

Outubro de 2013

CORBA C++

(2)

Definição e História

• O que é o mapeamento CORBA C++ ?

– Documento que padroniza como as declarações de uma IDL são mapeadas para a linguagem C++

• antes de 1994

– Mapeamentos proprietários

• Desafio: linguagem multiparadigma

• 1994

– Primeira versão não publicada

– Anterior ao primeiro padrão(98) de C++!

• 2012

– Mapeamento(v1.3) para C++11 :)

(3)

Identificadores e módulos

• Identificadores

– São preservados com exceção de palavras reservadas da linguagem C++

• prefixo: _cxx_

• Módulos

– Mapeamento para namespaces – Módulo CORBA

//IDL

module A { /* definitions */ };

module B { /* definitions */ };

module A { /* more definitions */ };

//C++

namespace A { /* ... */ } namespace B { /* ... */ } namespace A { /* ... */ }

(4)

Tipos básicos

IDL C++ Size

short CORBA::Short >= 16 bits

long CORBA::Long >= 32 bits

long long CORBA::LongLong

unsigned short CORBA::UShort >= 16 bits unsigned long CORBA::ULong >= 32 bits unsigned long long CORBA::ULongLong

float CORBA::Float >= 32 bits

double CORBA::Double >= 64 bits

long double CORBA::LongDouble

char CORBA::Char >= 8 bits

wchar CORBA::WChar

boolean CORBA::Boolean Unspecified

octet CORBA::Octet >= 8 bits

(5)

Tipos básicos - overloading

• Todos os tipos básicos são mapeados para tipos C++ distinguíveis, exceto: char, boolean, octet e wchar

Exemplo:

namespace CORBA { typedef char Char;

typedef char Boolean;

}

void fn(CORBA::Char) { }

void fn(CORBA::Boolean { } // Ops!

(6)

string

• Mapeamento de strings para char *

• Wide strings para CORBA::WChar *

• Não usar o par new/delete !

//Alocação de (len+1) bytes.

//Retorno de um ponteiro nulo em caso de falha na alocação.

static char * string_alloc(CORBA::ULong len);

//Alocação e cópia

static char * string_dup(const char *);

//Desalocação

void string_free(char *);

(7)

const

• Mapeamento para constantes C++

//IDL

const string s = "str";

module A {

const short s = 20;

};

interface X {

const long l = 10;

};

//C++

static const char *const s = “str”;

namespace A {

const CORBA::Short s = 20;

}

class X { public:

static const CORBA::ULong l = 10;

};

(8)

enum

• Mapeamento para uma enumeração C++ (enum)

• Não se deve utilizar os valores ordinários

//IDL e C++

enum color { red, green, blue };

(9)

Tipos de tamanho variável

• Necessidade de se utilizar uma alocação dinâmica

– String

– Object reference – Any

– Sequence

– Struct (elemento de tamanho variável)

– Array (elemento de tamanho variável)

(10)

Gerenciamento da memória

• O que há de errado com o código abaixo ?

{

char *s = CORBA::string_dup(“str”);

foo();

string_free(s);

}

(11)

Gerenciamento da memória

• Uso de smart pointers para evitar memory leaks e facilitar o uso.

– RAII (Resource Acquisition Is Initialization) – std::auto_ptr

– std::unique_ptr, std::shared_ptr e std::weak_ptr

{

CORBA::String_var s(“str”);

foo();

}

(12)

Gerenciamento da memória

struct T_var { T_var();

T_var(T *);

T_var(const T_var &);

~T();

T_var & operator=(T *);

T_var & operator=(const T_var &);

T * operator->();

const T * operator->() const;

/* ... */

private:

T *p_;

};

(13)

Gerenciamento da memória

/* Inicializa o ponteiro interno como nulo. */

T_var();

/* Assume o ownership da instância apontada por p, que deve apontar para uma área de memória alocada dinamicamente. */

T_var(T *p);

/* Deep copy */

T_var(const T_var &);

/* Desaloca a instância apontada por p_ se ninguém mais estiver utilizando o recurso. */

~T_var();

/* Desaloca a instância apontada por p_ e assume o ownership da instância apontada por p */

T_var & operator=(T *);

/* Desaloca a instância apontada por p_ e faz deep copy de p */

T_var & operator=(const T_var &);

(14)

Gerenciamento da memória

/* Uso como ponteiro */

T * operator->();

const T * operator->() const;

/* Uso como referência */

operator T &();

const operator T &() const;

/* sequence ou array */

T & operator[](CORBA::ULong idx);

const T & operator[](CORBA::ULong idx) const;

(15)

Gerenciamento da memória

• Tipos de tamanho variável

operator T *&();

const T & in() const;

T & inout();

T *& out();

T * _retn();

• Tipos de tamanho fixo

T_var(const T &);

T_var & operator=(const T &);

const T & in() const;

T & inout();

T & out();

T _retn();

(16)

Gerenciamento da memória - string

String_var(); \\internal_pointer_ = 0

\\assume ownership String_var(char *);

String_var &operator=(char *);

\\deep copy

String_var(const char*);

String_var &operator=(const char *);

\\assume ownership

String_var(const String_var &);

String_var &operator(const String_var &);

~String_var(); \\string_free()

(17)

Gerenciamento da memória - string

\\conversão implícita

operator const char*() const;

operator char*&();

operator char*();

\\conversão explícita const char* in() const;

char*& inout();

char*& out(); \\string_free()

char* _retn(); \\yielding ownership char &operator[](CORBA::ULong index);

char operator[](CORBA::ULong index) const;

(18)

Gerenciamento da memória - string

CORBA::String_var ret = fn();

char *fn() {

CORBA::String_var s(CORBA::string_dup(str));

return s; \\Ops! Double free!

}

char *fn() {

CORBA::String_var s(CORBA::string_dup(str));

return CORBA::string_dup(s); \\Ok }

char *fn() {

CORBA::String_var s(CORBA::string_dup(str));

return s._retn(); \\Ok }

(19)

Gerenciamento da memória - string

• Strings declaradas em tipos definidos pelo usuário(struct, sequence, exception e array) são inicializadas com string vazia

• Necessidade de métodos para alocação e desalocação para evitar definições globais de operator new[] e operator delete[]

(20)

struct

• Mapeamento para uma struct de C++. Membros seguem as suas respectivas regras de mapeamento

\\IDL

struct A { double d;

string s;

};

\\C++

struct A {

CORBA::Double d;

CORBA::String_mgr s;

};

class A_var;

(21)

sequence

• Mapeamento para uma classe C++ que se comporta como um vetor de tamanho variável

\\IDL

typedef sequence<string> str_seq;

(22)

sequence

• Mapeamento para uma classe C++ que se comporta como um vetor de tamanho variável

– O número máximo de elementos é somente uma dica!

• Não há garantia que:

– os elementos serão pré-alocados no mesmo instante;

– serão alocados exatamente max elementos;

– os elementos ocuparão uma região contígua da memória.

• Cuidado ao manter ponteiros para sequences por conta de reallocations!

str_seq(); \\empty sequence str_seq(CORBA::ULong max);

(23)

sequence

\\deep copy

str_seq(const str_seq &);

str_seq & operator=(const str_seq &);

\\membros de tamanho variável são liberados

~str_seq();

(24)

sequence

\\número de elementos

CORBA::ULong str_seq::length() const;

\* aloca (len - length()) elementos ou trunca (length() - len) elementos. Novos elementos inicializados com default construtor ou string vazia se for o caso

*/

void str_seq::length(CORBA::ULong len);

(25)

• Indexação de 0 até length()-1

• Acesso fora do intervalo acima é undefined behavior

sequence

CORBA::String_mgr & operator[](CORBA::ULong idx);

const char * operator[](CORBA::ULong idx) const;

(26)

• Mapeamento para um array C++

array

//IDL

typedef string str_array[10];

//C++

typedef CORBA::String_mgr str_array[10];

typedef CORBA::String_mgr str_array_slice;

\\retorna null em caso de falha

str_array_slice * str_array_alloc();

str_array_slice * str_array_dup(const str_array_slice *);

void str_array_free(str_array_slice *);

void str_array_copy(str_array_slice *to, const str_array_slice * from);

(27)

• Mapeamento para um typedef C++

typedef

//IDL

typedef string str_array[4];

typedef str_array address;

//C++

/* declarações para str_array */

typedef str_array address;

typedef str_array_slice address_slice;

address_slice * address_alloc() { return address_alloc(); } address_slice * address_dup(const address_slice *p)

{ return str_array_dup(p); }

void address_free(address_slice *p) { str_array_free(p); }

void address_copy(address_slice *to, const address_slice * from) { str_array_copy(to, from); }

(28)

• Mapeamento para uma classe C++ que atua como um proxy

interface

//IDL

interface my_interface { void foo();

};

//C++

struct my_interface

: public virtual CORBA::Object {

virtual void foo() = 0;

};

• O uso de exception specifications é opcional

my_interface obj; //Errado my_interface *obj; //Errado

void f(my_interface &); //Errado my_interface_ptr obj; //Certo my_interface_var obj; //Certo

(29)

• Mapeamento para um par de métodos do tipo get e set

atributos

//IDL

interface my_interface { attribute long a;

readonly attribute long b;

};

//C++

virtual CORBA::Long a() = 0;

virtual void a(CORBA::Long val) = 0;

virtual CORBA::Long b() = 0;

(30)

• Mapeamento para uma classe que herda de CORBA::UserException

exception

//IDL

exception ex { string msg;

};

//C++

struct ex :

public CORBA::UserException {

CORBA::String_mgr msg;

ex(const char *msg);

};

(31)

• Mapeamento para a classe CORBA::Any que armazena internamente um type code e o valor de interesse

• Inserção de um valor através de operator<<=

• deep copy

any

//C++

CORBA::Any a;

a <<= “Hello”;

a <<= “World”; //desaloca “Hello” e copia “World”

a <<= CORBA::string_dup(“str”) //memory leak!

(32)

• Extração de um valor através de operator>>=

• Verificação do tipo durante a operação

any

//C++

CORBA::Any a;

a << static_cast<CORBA::Long>(99);

CORBA::Long val;

bool ret = (a >>= val);

assert(ret);

from_boolean(), to_boolean(), from_char(), to_char(), from_octet() e to_octet()

• Any retêm o ownership de uma string e entrega um ponteiro para um área de memória interna

(33)

in, inout, out (tamanho fixo), out (tamanho variável) e valor de retorno

caller (quem faz a chamada chamada) e callee (quem recebe a chamada)

• O caller sempre é responsável por desalocar!

Passagem de parâmetros

(34)

1. Caller faz a alocação e inicialização do parâmetro 2. Faz a chamada

3. ORB copia o parâmetro para o espaço de endereçamento do callee (no caso de uma chamada remota)

4. Callee obtêm um acesso somente de leitura a uma cópia local 5. Callee retorna

6. ORB desaloca a cópia (no caso de uma chamada remota)

7. Caller desaloca o parâmetro

Passagem de parâmetros - in

void foo(T_in);

(35)

1. Caller faz a alocação e inicialização do parâmetro 2. Faz a chamada

3. ORB copia o parâmetro para o espaço de endereçamento do callee (no caso de uma chamada remota)

4. Callee obtêm um acesso leitura e escrita a uma cópia local.

(se a modificação necessitar de um espaço maior uma realocação é realizada)

5. Callee retorna

6. ORB envia a cópia modificada de volta e desaloca a cópia. (O ORB do caller pode realocar e inicializar com o valor recebido do callee)

7. Caller desaloca o parâmetro

Passagem de parâmetros - inout

void foo(T_inout);

(36)

• T_out

• Tamanho fixo

• Tamanho variável

Passagem de parâmetros - T_out

//C++

struct String_out {

String_out(const char *&s) : ref_(s) { ref_ = 0; } String_out(const String_var &s) : ref_(s.ref_) { string_free(ref_);

ref_ = 0;

}

private:

char *& ref_;

};

typedef T &T_out;

(37)

1. Caller faz a alocação do parâmetro (tamanho fixo)

1. Caller define um ponteiro não inicializado como placeholder

(tamanho variável)

2. Faz a chamada

3. ORB de callee aloca o parâmetro 4. Callee inicializa o parâmetro

5. Callee retorna

6. ORB de callee envia o parâmetro de volta e o ORB de caller inicializa o parâmetro (no caso do tamanho variável o ORB de caller também aloca)

7. O ORB de callee desaloca o parâmetro 8. Caller desaloca o parâmetro

Passagem de parâmetros - out

void foo(T_out);

(38)

Passagem de parâmetros - valor de retorno

T foo();

• Segue as regras do parâmetro out

• Uso de _retn() para passar o ownership

char * name() {

String_var str = get_name();

foo(); //exception?!

return str._retn();

}

(39)

Passagem de parâmetros

IDL Type in inout out Return type

simple simple simple & simple & simple

enum enum enum & enum & enum

string const char * char *& char *& char *

any const Any & Any & Any *& Any *

objref objref_ptr objref_ptr & objref_ptr & objref_ptr sequence const sequence & sequence & sequence *& sequence * struct (fixed) const struct & struct & struct & struct struct (variable) const struct & struct & struct *& struct * array (fixed) const array array_slice * array_slice * array_slice * array (variable) const array array_slice * array_slice *& array_slice *

(40)

Passagem de parâmetros

IDL Type in inout/out return

string const String_var & String_var & String_var

any const Any_var & Any_var & Any_var

objref const objref_var & objref_var & objref_var sequence const sequence_var & sequence_var & sequence_var struct const struct_var & struct_var & struct_var array const array_var & array_var & array_var

(41)

Exemplo - Aplicação Stock Market

• IDL

– Compilação

• Servidor

– Implementação do servant

– Disponibilizar um CORBA Object

• IOR

• Cliente

– Interação com o objeto remoto

• IOR

(42)

StockMarket.idl

module StockMarket {

typedef string StockSymbol;

typedef sequence<StockSymbol> StockSymbolList;

interface StockServer {

float getStockValue(in StockSymbol symbol);

StockSymbolList getStockSymbols();

};

};

(43)

Servant

struct stock_market : public POA_StockMarket::StockServer {

CORBA::Float getStockValue(const char *symbol) {

/* ... */

}

StockMarket::StockSymbolList * getStockSymbols() {

StockMarket::StockSymbolList_var seq = new StockMarket::StockSymbolList;

seq->length(stocks_.size());

/* ... */

return seq._retn();

} };

(44)

Disponibilizar um CORBA Object

• Criar um ORB

• Obter o RootPOA

• Ativar o POA Manager

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

CORBA::Object_var o = orb->resolve_initial_references("RootPOA");

PortableServer::POA_var poa = PortableServer::POA::_narrow(o);

PortableServer::POAManager_var mgr = poa->the_POAManager();

mgr->activate();

(45)

Disponibilizar um CORBA Object

• Ativar o servant e criar um Object reference

• Disponibilizar a referência

• Escutar as requisições dos clientes

stock_market servant(s);

StockMarket::StockServer_var market = servant._this();

CORBA::String_var ior = orb->object_to_string(market);

std::cout << ior << std::endl;

orb->run();

(46)

Cliente

• Criar um ORB

• Criar um proxy para o objeto remoto dado um IOR

CORBA::ORB_var orb = CORBA::ORB_init(argc, argv);

CORBA::Object_var o = orb->string_to_object(ior);

StockMarket::StockServer_var server = StockMarket::StockServer::_narrow(o);

StockMarket::StockSymbolList_var symbols = server->getStockSymbols();

Referências