Использовать несколько ORB через разные потоки (многопоточное клиентское приложение с несколькими сферами) — как?

Этот вопрос связан с: Можно ли иметь несколько объектов ORB в одном процессе?

Итак, благодаря @BrianKelly я нашел информацию о ORB идентификатор (хотя такой информации не было во всех ORBACUS документы, которые у меня есть), и я успешно создал простое приложение, которое подключается к различным CORBA серверы и успешно выполнено несколько CORBA Запросы.

Все идет нормально.

Теперь я хочу сделать это приложение многопоточным и запустить отдельный поток для подключения к различным серверам. Но ORB_init сбои.

Вот очень короткий код, который я использую для тестирования:

#include <OB/CORBA.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* run( void * );

struct config { const char* nameservice; const char* id; const char* exe; };

const bool mt = true;

int main()
{
config cfg1 = { "NameService=corbaloc::10.102.8.15:13069/NameService", "1", "test" };
config cfg2 = { "NameService=corbaloc::192.168.1.99:13069/NameService", "2", "test" };

if( mt )
{
pthread_t t1, t2;

pthread_create( &t1, NULL, run, (void*)&cfg1 );
pthread_create( &t2, NULL, run, (void*)&cfg2 );

pthread_join( t1, NULL ); pthread_join( t2, NULL );
}
else
{
run( (void*)&cfg1 );
run( (void*)&cfg2 );
}

printf( "SUCCESS!\n" );
return 0;
}

void* run( void* arg )
{
pthread_mutex_lock( &mutex );

int argc = 2; char* argv[3];

config* cfg = (config*)arg;
argv[0] = (char*)cfg->exe;
argv[1] = (char*)cfg->nameservice;
argv[2] = NULL;

CORBA::ORB_var m_varOrb = CORBA::ORB_init( argc, argv, cfg->id );

pthread_mutex_unlock( &mutex );
return NULL;
}

Так когда mt является falseвсе хорошо, я могу расширить код для создания некоторых специфичных для сервера объектов, для выполнения разных запросов и т. д. Но потом mt является trueвторой поток не вызывает ORB_init, Смотрите трассировку стека ниже.

Я почти уверен, что мне не хватает чего-то очень простого и глупого, но что?

$ g++ -g3 -ggdb -Wall -Wshadow -march=i486
-DUNIX -DLINUX -DPTHREADS -DMULTITHREAD -D_REENTRANT
-I. -I/usr/local/include/OB/ -I/usr/local/include/JTC/
-I/usr/include/OB/ -I/usr/include/JTC/ -L/usr/local/lib
-lpthread -lm -lz -lrt -ldl -lOB -lJTC -lCosNaming
test.cpp

Трассировки стека:

#0  0x00566402 in __kernel_vsyscall ()
#1  0x0080dfd0 in raise () from /lib/i686/nosegneg/libc.so.6
#2  0x0080f9b1 in abort () from /lib/i686/nosegneg/libc.so.6
#3  0x03dc490b in ~RefCount
(this=Could not find the frame base for "~RefCount".)
at ../../include/OB/RefCount_Ts_Linux-x86-32.h:43
#4  0x03ef8965 in ORBInstance
(this=Could not find the frame base for "ORBInstance".)
at ORBInstance.cpp:276
#5  0x03f134fe in ORB_impl
(this=Could not find the frame base for "ORB_impl".)
at ORB_impl.cpp:281
#6  0x03f24740 in OBCORBA::ORB_init
(ac=Could not find the frame base for
"OBCORBA::ORB_init(int&, char**, OB::Properties*,
OB::Logger*, OB::Reactor*,
char const*, char const*)". )
at ORB_init.cpp:994
#7  0x03f249d9 in CORBA::ORB_init
(ac=Could not find the frame base for
"CORBA::ORB_init(int&, char**, char const*, char const*)".)
at ORB_init.cpp:1014
#8  0x0804895d in run (arg=0xbfe8b544) at test_server.cpp:45
#9  0x007334d2 in start_thread () from /lib/i686/nosegneg/libpthread.so.0
#10 0x008b848e in clone () from /lib/i686/nosegneg/libc.so.6

0

Решение

Я нашел что-то вроде обходного пути. Делает мой код действительно уродливым и не легким для поддержки, но это все же что-то.

Вот что я сделал:

  • добавить механизм (в моем приложении), который будет подсчитывать необходимые потоки, прежде чем запускать их
  • Заранее ознакомьтесь с настройками — мне нужно знать необходимые параметры для сервисов именования (используется в ORB_init)
  • перед запуском любых потоков «менеджер» выполнит только раз ORB_init, но это пройдет несколько раз -ORBInitRef параметр, с разными значениями — по одному для каждого потока / соединения
  • после того, как это сделано, потоки запускаются, но вместо выполнения ORB_initони прямо исполняют resolve_initial_references и продолжить с конкретных вещей сервера

Примечание: мой пример не содержит resolve_initial_referencesпотому что авария в ORB_init,


Таким образом, применение этого «алгоритма» для этого «обходного пути» будет выглядеть так:

#include <OB/CORBA.h>

void* run( void * );
CORBA::ORB_var varORB;

int main()
{
/** The necessary configurations */
//-------------------------------------v
const char* nameservice1 = "NameService1=corbaloc::10.102.8.15:13069/NameService";
const char* nameservice2 = "NameService2=corbaloc::192.168.1.99:13069/NameService";
//-------------------------------------^

/** INIT the ORB **/
int argc = 5; char* argv[ 6 ];
const char* initref = "-ORBInitRef";
const char* exe = "test";

argv[0] = (char*)exe;
argv[1] = (char*)initref; argv[2] = (char*)nameservice1;
argv[3] = (char*)initref; argv[4] = (char*)nameservice2;
argv[5] = NULL;

varORB = CORBA::ORB_init( argc, argv );

pthread_t t1, t2;

char ns_id1 = '1', ns_id2 = '2';
pthread_create( &t1, NULL, run, (void*)&ns_id1 );
pthread_create( &t2, NULL, run, (void*)&ns_id2 );

pthread_join( t1, NULL ); pthread_join( t2, NULL );

varORB->destroy();

return 0;
}
void* run( void* arg )
{
char nameservice[] = "NameServiceN";

// set the right number of the nameservice
nameservice[ 11 ] = *((char*)arg);

varORB->resolve_initial_references( nameservice );

// do some CORBA-specific stuff

printf( "SUCCESS %c\n", *(char*)arg );
return NULL;
}

НОТА

Я до сих пор не могу поверить, что это единственный вариант. Если вы внимательно посмотрите на мой код (в вопросе), вы увидите, что:

  • Это ЯВЛЯЕТСЯ можно иметь несколько шаров (см. случай с mt == false)
  • призыв к ORB_init ЯВЛЯЕТСЯ синхронизированный
  • идентификатор ORB ЯВЛЯЕТСЯ реализовано и работает нормально (опять же с mt == false)

Так что это не фактический ответ на мой вопрос, это своего рода обходной путь.

Не имеет смысла (по крайней мере для меня) иметь возможность создавать несколько ORB в одном потоке, но не в нескольких потоках.

0

Другие решения

ORB будет использовать разные соединения (и потоки) с разными серверами каждый раз — всегда. Получение ответов и входящих звонков также обрабатываются в разных потоках (если это полезно и / или необходимо).

Я думаю, вы пытаетесь попытаться решить то, что ORB уже решил для вас. Это промежуточное ПО, не пугайтесь потоков и тому подобного. Это уже сделано экспертами CORBA.

0