информационная безопасность
без паники и всерьез
 подробно о проектеRambler's Top100
За кого нас держат?Портрет посетителя
BugTraq.Ru
Русский BugTraq
 Анализ криптографических сетевых... 
 Модель надежности двухузлового... 
 Специальные марковские модели надежности... 
 Бэкдор в xz/liblzma, предназначенный... 
 Три миллиона электронных замков... 
 Doom на газонокосилках 
главная обзор RSN блог библиотека закон бред форум dnet о проекте
bugtraq.ru / форум / programming
Имя Пароль
ФОРУМ
если вы видите этот текст, отключите в настройках форума использование JavaScript
регистрация





Легенда:
  новое сообщение
  закрытая нитка
  новое сообщение
  в закрытой нитке
  старое сообщение
  • Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
  • Новичкам также крайне полезно ознакомиться с данным документом.
Согласен, что погнал, но не только здесь 23.12.07 00:22  Число просмотров: 2212
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> > Я уберу virtual в определении деструктора ~ITopic.
> Нууу, брат ты погнал, "Я уберу virtual в определении
> деструктора ~ITopic"
> сотри немедленно и считай что я не слышал :).

Я попробовал встоить код в существующий солюшен... Не работает.

> показал бы ТОТ код , который "не нужен"

Не могу. То собственность комании. Там активно темплейты используются.
<programming>
[C++] Получилось хорошее решение (но я испортил нитку в форуме). 19.12.07 07:50  
Автор: void <Grebnev Valery> Статус: Elderman
Отредактировано 28.12.07 08:17  Количество правок: 4
<"чистая" ссылка> <обсуждение закрыто>
Прошу прощения, но я испортил нитку. Я хотел "ответить" на свой постинг в корень но каким -то образом затёр своё первое сообщение. Администраторы/модераторы - я не хотел..... ;( Если можно, то исправьте плз.
-----

В общем получилось весьма универсальное и производительное решение, см ниже.
Не map, а всё ж вектор. Работает быстро. Решение годится (протестировано) для 2-х типов задач:

- когда для обновлений добавляются относительно "статичные" топики, например, статусные переменные, результаты запросов к базам данных и т.д. Такие топики могут быть добавлены в вектор при помощи TopicVector::AddTopic и обновлены Subscriber-ом по таймеру.

- когда обновляются относительно "быстрые" топики 10000-15000 раз в секунду, например, данные для Microsoft RTD (real time data server). Не вдаваясь в обсуждение майкрософтовской трактовки "real time data", скажу, что данные накапливаются в TopicVector по приходу обновлений для топика при помощи TopicVector::UpdateTopic. Главный трюк - когда приходит обновление устанавливаем topic->m_cRef ++ , а когда Subscriber получает обновления из TopicVector, то он сбрасывает эти значения topic->m_cRef = 0.
Таким образом, вектор содержит единственное "вхождение" топика (как map), а данные всегда актуальны. Это в разы быстрее, чем map.

В принципе, по результатам тестов - решение весьма производительно. Если же надо будет быстрее, то, думаю, вектор можно будет заменить массивом (может и на отдельном хипе). Сделать это будет легко, поскольку для TopicVector не предусматривается операции удаления/вставки отдельного элемента, а только добаление в хвост и очистка всего вектора.


#include <string>
#include <vector>
#include "comdef.h"

const int INVALIDE_TOPIC_ID = -1;
const int TOPICVECTOR_RESERVE_SIZE = 500000;

typedef variant_t topic_t;

class Topic {
public:
virtual topic_t GetValue(void) const PURE;
Topic(long ID = INVALIDE_TOPIC_ID) : m_topicID(ID), m_cRef(0L) {};
virtual ~Topic(){};
long m_topicID;
long m_cRef;
};

class TopicVector
{
public:
void AddTopic(Topic* topic)
{
m_vector.push_back(topic);
topic->m_cRef ++;
}
void UpdateTopic(Topic* topic)
{
if ( 0 == topic->m_cRef)
m_vector.push_back(topic);
topic->m_cRef ++;
}
size_t Size(void) const
{
return m_vector.size();
}
bool IsValidTopic(const size_t idx) const
{
if (NULL != m_vector.at(idx) && INVALIDE_TOPIC_ID != m_vector.at(idx)->m_topicID )
return true;
else
return false;
}
Topic* operator[](const size_t idx)
{
return m_vector.at(idx);
}
void Lock(void)
{
::EnterCriticalSection(&m_cs);
}
void Unlock(void)
{
::LeaveCriticalSection(&m_cs);
}
void Clear(void)
{
m_vector.clear();
}
TopicVector()
{
::InitializeCriticalSection(&m_cs);
m_vector.reserve(TOPICVECTOR_RESERVE_SIZE);
}
~TopicVector()
{
::DeleteCriticalSection(&m_cs);
}

private:
std::vector<Topic*> m_vector;
CRITICAL_SECTION m_cs;
};
вот так было бы правильней, используя наследственность, ну... 20.12.07 02:13  
Автор: + <Mikhail> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
вот так было бы правильней, используя наследственность, ну естественно надо сделать private copy constructor и assignment operator.
Вообче то ето школьная задачка, не так ли?
class ITopic
{
public:
    virtual ~ITopic(){};
    virtual _bstr_t GetValue() = 0;
};
class CTopicVector
{
private:
    //I would use a smart pointer 
    //example:
    //map<int , smart_ptr<ITopic> > m_TopicData
    map<int , ITopic*> m_TopicData;
    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;
    }

};

class CTopic1: public ITopic
{
private:
    _bstr_t m_bstrVal;
    int     m_iVal;
public:
    CTopic1(_bstr_t bstrVal, int iVal)
        :m_bstrVal(bstrVal),m_iVal(iVal){}

    _bstr_t GetValue()
    {
        return m_bstrVal + L":" + _bstr_t(_variant_t(m_iVal)) + L"\n";
    }
};

class CTopic2: public ITopic
{
private:
    double  m_dVal;
    bool    m_bVal;
public:
    CTopic2(double dVal, bool bVal)
        :m_dVal(dVal),m_bVal(bVal){}

    _bstr_t GetValue()
    {
        return _bstr_t(_variant_t(m_dVal)) + L":" + (m_bVal?L"true\n":L"false\n");
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    CTopicVector TopicVector;
    TopicVector.AddTopic(new CTopic1(L"Topic1",1));
    TopicVector.AddTopic(new CTopic1(L"Topic1",2));
    TopicVector.AddTopic(new CTopic1(L"Topic1",3));
    TopicVector.AddTopic(new CTopic2(3.14,true));
    int size = TopicVector.GetSize();
    for(int i = 0; i < size; ++i)
    {
        ITopic* pTopic = TopicVector.GetUnsafeTopic(i);
        if(pTopic)
        {
            OutputDebugString(pTopic->GetValue());
        }
    }
    return 0;
}

---
> Буду рад и благодарен, если кто-нить подскажет элегантное
> решение. Задача такова:
> Есть произвольные структуры данных (векторы, массивы и т.д)
> classA {...}
> classBB {...}
> ....
>
> и есть векторы, массивы, мапы этих структур
>
> vector<A> va;
> vector<BB> vb;
> ...
>
> Каждый экземпляр таких структур/классов может
> быть”отображён” на более простой тип, например, строку,
> целое, булево и т.д. Т.е. Для каждого класса может быть
> определена некоторая функция, типа virtual variant_t
> GetTopicValue(const LPVOID pdata) const.
>
>
> Существует поток, в котором надо единообразно периодически
> “пробегать” по списку (контейнеру ссылок) всех этих
> элементов, с тем чтобы в цикле получать разультат
> “отображения” каждого экемпляра списка, например, в
> псевдокоде надо выполнить:
>
> loop for each in (va,vb, ...)
> v = each.GetTopicValue(NULL);
>
> Другие потоки добавляют в данный список ссылки на
> существующие структуры, например, когда данные обновлены.
>
> Я смотрел аналогичный код некоторых гурей, у которых я
> учусь– мне плохо стало от крутизны, непонятности,
> темплейтности, объектно ориентированности и ненужности.
> Попробовал сделать сам – получается просто, но хочется ещё
> более просто, изящно и элегантно. Попробовал темлейты
> прикрутить (как у гурей) – не получается чтоб это нужно
> было (от недостатка моих знаний, видимо). Наколеночный код
> у меня таков:
>
> #include "stdafx.h"
> #include <string>
> #include <vector>
> #include <sstream>
> #include "comdef.h"
>
>
> ///////////////////////////////////////////////////////////
> //////
> //
> // Generic topic containers
> //
> ///////////////////////////////////////////////////////////
> //////
>
> interface ITopic {
> virtual variant_t GetTopicValue(const LPVOID pdata)
> const PURE;
> virtual ~ITopic(){};
> };
>
> class Topic {
> public:
> virtual variant_t GetTopicValue(const LPVOID pdata)
> const
> {
> return (m_topicInterface ?
> m_topicInterface->GetTopicValue(pdata) : variant_t());
> }
> Topic() : m_topicID(0L), m_topicInterface(NULL) {}
> long m_topicID;
> ITopic* m_topicInterface;
> };
>
> class TopicVector
> {
> public:
> void AddTopic(const long ID, ITopic* item)
> {
> Topic topic;
> topic.m_topicID = ID;
> topic.m_topicInterface = item;
> m_vector.push_back(topic);
> }
> size_t Size(void) const
> {
> return m_vector.size();
> }
> Topic& operator[](const size_t idx)
> {
> return m_vector.at(idx);
> }
> void Lock(void)
> {
> ::EnterCriticalSection(&m_cs);
> }
> void Unlock(void)
> {
> ::LeaveCriticalSection(&m_cs);
> }
> TopicVector()
> {
> ::InitializeCriticalSection(&m_cs);
> }
> ~TopicVector()
> {
> Lock();
> for (size_t i = 0; i < m_vector.size();
> i ++)
> delete
> m_vector.at(i).m_topicInterface;
> Unlock();
> ::DeleteCriticalSection(&m_cs);
> }
> private:
> std::vector<Topic> m_vector;
> CRITICAL_SECTION m_cs;
> };
>
> ///////////////////////////////////////////////////////////
> //////
> //
> // Example: concrete topics
> //
> ///////////////////////////////////////////////////////////
> //////
>
> class ConcreteTopicA: public ITopic {
> public:
> virtual variant_t GetTopicValue(const LPVOID data)
> const
> {
> std::ostringstream s;
> s << m_sval << ":" <<
> m_ival;
> return _bstr_t(s.str().c_str());
> }
> ConcreteTopicA(const std::string& sval, const
> int ival): m_sval(sval), m_ival(ival) {};
> virtual ~ConcreteTopicA() {};
> private:
> std::string m_sval;
> int m_ival;
> };
>
> class ConcreteTopicB: public ITopic {
> public:
> virtual variant_t GetTopicValue(const LPVOID data)
> const
> {
> std::ostringstream s;
> s << m_bval << ":" <<
> m_fval;
> return _bstr_t(s.str().c_str());
> }
> ConcreteTopicB(const bool bval, const double&
> fval): m_bval(bval), m_fval(fval) {};
> virtual ~ConcreteTopicB() {};
> private:
> bool m_bval;
> double m_fval;
> };
>
>
> int _tmain(int argc, _TCHAR* argv[])
> {
> // create concrete topics
> ConcreteTopicA* topicA = new ConcreteTopicA("some
> string value", 100);
> ConcreteTopicB* topicB = new ConcreteTopicB(true,
> 1000.0);
>
> // add topics
> TopicVector topics;
> topics.Lock();
>
> topics.AddTopic(1, topicA);
> topics.AddTopic(2, topicB);
>
> //print it
> variant_t v;
> for (size_t i = 0; i < topics.Size(); i ++) {
> v = topics[i].GetTopicValue(NULL);
> // TO DO
> }
>
> topics.Unlock();
>
> return 0;
> }
>
> Спасибо, если кто предложит красивое, простое решение.
[C++] вот так было бы правильней, используя наследственность, ну... 21.12.07 04:40  
Автор: 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, и я не знаю что с этим делать. Похоже этой неэлегантной шероховатости не избежать, так чтоб не родить другую неэлегантность.

В целом я очень признателен Вам, даже несмотря на шероховатости обсуждаемых решений. Это придало мне уверенности, что тот код (не мой), который мне надо адаптировать – в топку и целиком.
Нууу, брат ты погнал, "Я уберу virtual в определении... 21.12.07 21:05  
Автор: + <Mikhail> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> > вот так было бы правильней, используя
> наследственность, ну
> > естественно надо сделать private copy constructor и
> > assignment operator.
> > Вообче то ето школьная задачка, не так ли?
>
> Так :(... Я бы даже сказал детсадовская... Но тем неменее
> могут быть и шероховатости!
>
> > class ITopic
> > {
> > public:
> > virtual ~ITopic(){};
> > virtual _bstr_t GetValue() = 0;
> > };
>
> Я уберу virtual в определении деструктора ~ITopic.
Нууу, брат ты погнал, "Я уберу 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 не будет фрагментации
> памяти.

Фрагментация будет по любому, если ты конечно не преаллоцируешь память для твоих Topic objects

>
>
> > 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. Даже если и не

поетому smart poiter и нужен

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

поетому smart poiter и нужен


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

показал бы ТОТ код , который "не нужен"
Согласен, что погнал, но не только здесь 23.12.07 00:22  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
> > Я уберу virtual в определении деструктора ~ITopic.
> Нууу, брат ты погнал, "Я уберу virtual в определении
> деструктора ~ITopic"
> сотри немедленно и считай что я не слышал :).

Я попробовал встоить код в существующий солюшен... Не работает.

> показал бы ТОТ код , который "не нужен"

Не могу. То собственность комании. Там активно темплейты используются.
А вот ещё мелькнуло... Может вообще не освобождать вектор в... 21.12.07 05:11  
Автор: void <Grebnev Valery> Статус: Elderman
<"чистая" ссылка> <обсуждение закрыто>
А вот ещё мелькнуло... Может вообще не освобождать вектор в методе RefreshData. Тогда, можно будет использовать map, и дополнительно устанавливать флаг = 1 если данные были обновлены клиентом (флаг = 1 устанавливается клиентом), и сбрасывать флаг в 0 в методе RefreshData.
Единственный недостаток пока вижу, это то, что если клиент перестал обновлять топик, (отсоединился), то соответствующуб ссылку надо удалить. Впрочем, это будет случаться не очень часто.

???

> 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();
> }
1




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


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