На базарной площади довольно часто можно слышать высказывания об
Обероне. Мне кажется, что на базарной площади пора появиться ветке об
этой системе и языке, что-то вроде "Мысли об Обероне". Что это такое, перспективы
этой системы, что
полезного можно извлечь из него для программирования на Дельфи
(например) и др.
Ответ на
»сообщение 4525« (Cardinal)
___________________________
Владимир, а где можно взять Вашу библиотеку?
Есть ряд "моментиков".
Раньше она выкладывалась на qnxclub.net . Но недавно какие-то тюркоговорящие г.твар..лар, прикрывающиеся истинными мусульманскими ценностями, под лозунгами борьбы с западными капиталистами, его ломанули... Причём, ломанули, наследив, где только можно было, чуть ли не паспорта свои только что не позабыли... :о) Скорее всего какая-то мОлодежь... Очень жаль, что среди всяких народов есть свои придурки...
Но и там уже довольно старая версия лежала. она не могла правильно обрабатывать случаи спонтанной гибели потока, залочившего кучу мьютексов и - "зеркальную ситуацию" - внезапную смерть объекта-носителя мьютекса, который был кем-то залочен... То есть аккуратно "развести" эти ситуации и освободить системные ресурсы она не была в состоянии. В новой версии это стало возможным.
Кроме того, теперь можно использовать объекты-таймеры, вызывающие при срабатывании (назначаемые) методы объектов.
Да, я напоминаю, что библиотека писалась ТОЛЬКО для систем, реализующих POSIX-потоки... Аналог для Винды я принципиально писать не буду. Если кто хочет - могу скинуть ссылки и статьи об эмуляции средств phread в винде... Но, овчинка выделки просто не стОит - снижение производительности прям-таки оглушающее...... Ну и, наконец, это просто выглядит калично, уродливо и отвратно - как собака с пятой ногой... :о)
Посоветуйте, куда выложить исходники. На sourceforge.net я сунулся, но, то ли у нас прокся как-то настроена по каличному, то ли, одновременно с этим, у меня провайдер что-то перемудрил, - я не могу никак свой аккаунт там создать. Регистрация проходит нормально, на моё мыло приходит извещение о начале процесса регистрации, но на последнем шаге мне возвращается невразумительный текст о невозможности их сервера сделать чего-то там...
Уважаемые коллеги!
Я, наверняка уже всех достал, но исчё раз напоминаю, что libAO жива и вроде как даже работает... :о)
Для тех, кто всё ещё не в курсе libAO - "эмуляция" синтаксиса и семантики активных объектов а ля Active Oberon в Си++.
Два примера:
1) Очередь буферов "без гонок" при добавлении-изъятии буфера.
Здесь демонстрируется только применение эксклюзивных блоков и ожидание выполнения условия.
////////////////////////////////////////////////////////////////////////////////
class Buffers_t
{
DECL_X;
bool is_owner; // если истина, очередь удаляет свои буферы в деструкторе
public:
Buffers_t( bool a_is_owner = false ) : is_owner( a_is_owner ) { }
~Buffers_t();
int Add( Buffer_t* );
Buffer_t* Get( bool wait_until_not_empty = false );
};
////////////////////////////////////////////////////////////////////////////////
Buffers_t::~Buffers_t()
{
if( is_owner ) while( !items.empty() ) delete Get();
}
//------------------------------------------------------------------------------
int Buffers_t::Add( Buffer_t* item )
{
X_BEGIN
try { items.push( item ); }
catch( ... ) { return E_BUFFERS_ADD; }
return EOK;
X_END
}
//------------------------------------------------------------------------------
Buffer_t* Buffers_t::Get( bool wait_until_not_empty = false )
{
X_BEGIN
if( items.empty() )
{ if( wait_until_not_empty )
X_AWAIT( !items.empty() );
else
return NULL;
}
Buffer_t* item = items.front();
items.pop();
return item;
X_END
}
2) Класс-предок всех обработчиков буферов, у которого существует входная очередь ожидающих обработки буферов.
Здесь показывается, как пользоваться активностями в экземплярах класса.
////////////////////////////////////////////////////////////////////////////////
//typedef struct { int input, lost, rejected, not_adjusted, filled, processed; } BuffersStatistics_s;
//------------------------------------------------------------------------------
class QueuedBufferProcessor_t : public BufferProcessor_t
{
DECL_ACTIVITY(QBPA);
protected:
DECL_X;
Buffers_t buffers;
Buffers_t free_buffers;
Buffers_t filled_buffers;
virtual int BufferIsValid(Buffer_t*) { return EOK; }
virtual void Process (Buffer_t*) = 0;
public:
QueuedBufferProcessor_t(Log_t* a_plog, int a_buffers_count, int a_buffer_N);
~QueuedBufferProcessor_t();
/*virtual*/int Accept(Buffer_t* pb, bool /*use_filled_if_no_free*/ = false);
////////////////////////////////////////////////////////////////////////////////
QueuedBufferProcessor_t::QueuedBufferProcessor_t( Log_t* a_plog,int a_buffers_count, int a_buffer_N )
: BufferProcessor_t(a_plog),
buffers(true)
{
try
{ if(CreateBuffers(a_buffers_count, a_buffer_N, &buffers, &free_buffers) != EOK)
throw E_QBP_CREATE_BUFFERS;
ACTIVITY_START(QueuedBufferProcessor_t, QBPA, "QBP", a_plog);
}
catch( int err_code )
{ char* err_str;
switch(err_code)
{ case E_QBP_CREATE_BUFFERS: err_str="при создании буферов"; break;
case E_QBP_START_A: err_str="при старте активности"; break;
default: err_str="!!! UNKONOWN ERROR !!!";
}
plog->Error("QueuedBufferProcessor_t::QueuedBufferProcessor_t: ошибка: %s", err_str);
throw;
}
};
//------------------------------------------------------------------------------
QueuedBufferProcessor_t::~QueuedBufferProcessor_t()
{
try {
ACTIVITY_STOP(QBPA); }catch(...){}
}
//------------------------------------------------------------------------------
ACTIVITY( QueuedBufferProcessor_t, QBPA )
// а могли бы и в объявлении класса тело активности определеить (после DECL_ACTIVITY), как обычного метода...
{
LOOP { Process( filled_buffers.Get(true) ); }
}
//------------------------------------------------------------------------------
int QueuedBufferProcessor_t::Accept( Buffer_t* pb, bool use_filled_if_no_free = false )
{
Buffer_t* pbuffer;
int err_code = BufferIsValid(pb);
if(err_code != EOK) return err_code;
LOOP
{ if((pbuffer = free_buffers.Get(false))) BREAK; // НЕ ЖДЁМ!
if(use_filled_if_no_free)
{ if((pbuffer = filled_buffers.Get(false))) BREAK;
return E_QBP_NO_BUFFERS;
}
else return E_QBP_NO_FREE_BUFFERS;
}
if(pbuffer->Copy(pb) != EOK)
{ free_buffers.Add(pbuffer);
return E_QBP_ADJUST_BUFFER;
}
filled_buffers.Add(pbuffer);
}