информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
Портрет посетителяSpanning Tree Protocol: недокументированное применениеВсе любят мед
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
 Умер Никлаус Вирт 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
все доски
FAQ
IRC
новые сообщения
site updates
guestbook
beginners
sysadmin
programming
operating systems
theory
web building
software
hardware
networking
law
hacking
gadgets
job
dnet
humor
miscellaneous
scrap
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
[C++] вот так было бы правильней, используя наследственность, ну... 21.12.07 04:40  Число просмотров: 2753
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 21.12.07 04:42  Количество правок: 1
<"чистая" ссылка> <обсуждение закрыто>
> вот так было бы правильней, используя наследственность, ну
> естественно надо сделать private copy constructor и
> assignment operator.
> Вообче то ето школьная задачка, не так ли?

Так :(... Я бы даже сказал детсадовская... Но тем неменее могут быть и шероховатости!

> class ITopic
> {
> public:
> virtual ~ITopic(){};
> virtual _bstr_t GetValue() = 0;
> };

Я уберу virtual в определении деструктора ~ITopic. Эти указатели указывают на структуры данных, которые должны постоянно находиться в памяти и обновляться, возможно, из других потоков по наступлении некоторых событий.


> class CTopicVector
> {
> private:
> //I would use a smart pointer

Написал выше, что это нецелесообразно.


> //example:
> //map<int , smart_ptr<ITopic> > m_TopicData
> map<int , ITopic*> m_TopicData;

Возможно и не обойтись без map<int , ITopic*> vs vectior<Topic>. Но ... при использовании std::map мы можем сильно проиграть в производительности при большом числе элементов(~100 000) CTopicVector.
Ещё раз скажу о постановке задачи:

1)В начале цикла обработке CTopicVector::Size() == 0.
2) При поступлении обновлений данных, клиенты будут добавлять элементы при помощи AddTopic(ITopic* pTopic) в CTopicVector с указателями на свои структуры данных. Таким образом размер CTopicVector будет расти от нуля до некоторого значения N.
3)В некоторый момент (по таймеру, или условию N == MAX(N)) CTopicVector должен быть “flush” данные в некий процесс, и затем очищен. Функция, что ниже должна работать максимально быстро, чтобы не держать клиентов, обновляющих данные(ITopic, на некотором объекте синхронизации Lock()/Unlock():

STDMETHODIMP SomeObject::RefreshData( long *TopicCount,
SAFEARRAY **parrayOut)
{

...
// нечто вроде
Lock();
> int size = TopicVector.GetSize();
> for(int i = 0; i < size; ++i)
> {
> ITopic* pTopic = TopicVector.GetUnsafeTopic(i);
> if(pTopic)
> {
> OutputDebugString(pTopic->GetValue());
> }
> }
...
TopicVector.ClearVector()
Unlock();
}

Класс map куда более тяжелее в сравнении с vector при большом числе элементов (~100000) и при частом добавлении/удалении узлов. Напротив, для вектора можно “преаллокировать” сapacity(), так что освобождение вектора не будет приводить к фактической переаллокации памяти на глобальном хипе. В принципе, можно пойти дальше – создать массив вместо вектора в отдельном хипе. Пока не уверен, что это даст прирост производительности. Можно будет протестировать. И последнее, при интенсивных циклах создания/освобождения элементов TopicVector, при использовании vector или array не будет фрагментации памяти.


> CRITICAL_SECTION m_cs;
>
> public:
> CTopicVector()
> {
> InitializeCriticalSection(&m_cs);
> };
> virtual ~CTopicVector()
> {
> ClearVector();
> DeleteCriticalSection(&m_cs);
> };
>
> void ClearVector()
> {
> map<int , ITopic*>::iterator it;
> EnterCriticalSection(&m_cs);


Не пойдёт, см. ниже.


> try
> {
> for(it = m_TopicData.begin();it !=
> m_TopicData.end();++it)
> {
> delete (*it).second;
> }
> m_TopicData.clear();
> }catch(...){};
> LeaveCriticalSection(&m_cs);
> }
>
> int GetSize()
> {
> return (int)m_TopicData.size();
> }
> int AddTopic(ITopic* pTopic)
> {
> int iId = (int)m_TopicData.size();
> EnterCriticalSection(&m_cs);


Не пойдёт, см. ниже.


> try
> {
> m_TopicData[iId] = pTopic;
> }catch(...){}
> LeaveCriticalSection(&m_cs);
> return iId;
> };
> //unsafe reference to an object
> ITopic* GetUnsafeTopic(int iId)
> {
> ITopic *pTopic = NULL;
> EnterCriticalSection(&m_cs);
> try
> {
> pTopic = m_TopicData[iId];
> }catch(...){}
> LeaveCriticalSection(&m_cs);
> return pTopic;
> }
>
> };


Указанное выше “ниже” - это то, что блокировка должна охватывать весь процесс SomeObject::RefreshData. Иначе, данные CTopicVector будут неактуальными или испорченными другими клиентскими потоками, которые ” в этот момент” пытаются обновить свои структуры(ITopic. Даже если и не придавать значения такой “рассинхронизации” (не гут), то некоторые обновления и вовсе могут быть потеряны, т.к. по выходу из SomeObject::RefreshData вектор CtopicVector очищается. Поэтому необходимы отдельные методы Lock()/Unlock(). Другая причина в том, что вызов EnterCriticalSection – это не бесплатный вызов, даже если объект не блокируется (если критическая секция не занята, то на EnterCriticalSection может приходится ~ 100 тактов ЦПУ). Ну а если, уж объект синхнонизации блокирован, то дело совсем плохо. Поэтому нельзя, на мой взгляд, использовать такие Lock-и внутри циклов. Надо делать это снаружи циклов.

И последняя шероховатость, которая не относится к эффективности, но к элегантности:
и у Вас и у Нас есть по-существу GetUnsafeTopic, как Вы справедливо заметили . Ключевое слово здесь Unsafe, и я не знаю что с этим делать. Похоже этой неэлегантной шероховатости не избежать, так чтоб не родить другую неэлегантность.

В целом я очень признателен Вам, даже несмотря на шероховатости обсуждаемых решений. Это придало мне уверенности, что тот код (не мой), который мне надо адаптировать – в топку и целиком.
<programming> Поиск 






Rambler's Top100
Рейтинг@Mail.ru


  Copyright © 2001-2024 Dmitry Leonov   Page build time: 0 s   Design: Vadim Derkach