C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
оцените template'ы, по возможности — жестко. надо критику.
olegenty
Отправлено: 12.11.2004, 16:23


Ветеран

Группа: Модератор
Сообщений: 2412



CODE


/////////////////////////////////////////////////////////////////////////////
//
// Чуть переработанный шаблон Loki для создания
// потоконезависимых объектов
//

template <class Host>
class ObjectLevelLockable
{
   TMultiReadExclusiveWriteSynchronizer *pmtx;
public:
   __fastcall ObjectLevelLockable()
   {
       pmtx = new TMultiReadExclusiveWriteSynchronizer();
   }

   __fastcall ~ObjectLevelLockable()
   {
       delete pmtx;
   }

   class Read;
   friend class Read;

   class Read
   {
       ObjectLevelLockable& host_;

       Read(const Read&);
       Read& operator=(const Read&);
   public:
       __fastcall Read(Host& host) : host_(host)
       {
           host_.pmtx->BeginRead();
       }
       __fastcall ~Read()
       {
           host_.pmtx->EndRead();
       }
   };

   class Write;
   friend class Write;

   class Write
   {
       ObjectLevelLockable& host_;

       Write(const Write&);
       Write& operator=(const Write&);
   public:
       Write(Host& host) : host_(host)
       {
           host_.pmtx->BeginWrite();
       }
       ~Write()
       {
           host_.pmtx->EndWrite();
       }
   };
};

///////////////////////////////////////////////////////////////////////////////
//
// Потоконезависимый класс-список указателей на объекты,
// удаляемых, либо неудаляемых при разрушении/очистке
// списка
//
template <class C, bool bFreeItems> class CThreadedPtrList: public ObjectLevelLockable<CThreadedPtrList<C, bFreeItems> >
{
private:
   TList *list;

   inline const C* __fastcall GetItem(int Index)
   {
       Read read(*this);
       return reinterpret_cast<C*>(list->Items[Index]);
   }
   inline void __fastcall SetItem(int Index, C* Value)
   {
       Write write(*this);
       list->Items[Index] = Value;
   }
public:
   __fastcall CThreadedPtrList(): list(new TList())
   {
   }
   __fastcall ~CThreadedPtrList()
   {
       Write write(*this);
       if (bFreeItems)
       {
           for (int i = 0; i < list->Count; i++)
           {
               if (list->Items[i])
               {
                   delete reinterpret_cast<C*>(list->Items[i]);
               }
           }
       }
       delete list;
   };
   inline void __fastcall Add(C* pItem)
   {
       Write write(*this);
       list->Add(pItem);
   }
   inline void __fastcall Delete(int iIndex)
   {
       Write write(*this);
       list->Delete(iIndex);
   }
   inline const C* __fastcall Last()
   {
       Read read(*this);
       return reinterpret_cast<C*>(list->Last());
   }

   inline const int __fastcall GetCount()
   {
       Read read(*this);
       return list->Count;
   }

   inline void __fastcall Clear()
   {
       Write write(*this);
       if (bFreeItems)
       {
           for (int i = 0; i < list->Count; i++)
           {
               if (list->Items[i])
               {
                   delete reinterpret_cast<C*>(list->Items[i]);
               }
           }
       }
       list->Clear();
   }

   __property C* Items[int Index] = {read = GetItem, write = SetItem};
   __property int Count = {read = GetCount};
};

//class CConnection;

class CUser
{
public:
   AnsiString   Nick     ;
   int          UID      ;
   AnsiString   Password ;
   //CConnection *Connection;
public:
   __fastcall CUser(const AnsiString   asNick,
                    const int          iUID  ,
                    const AnsiString   asPassword/*,
                    const CConnection *pConnection*/): Nick(asNick),
                                                     UID(iUID),
                                                     Password(asPassword)/*,
                                                     Connection((CConnection*)pConnection)*/
   {
   }
};

class CUL: public CThreadedPtrList<CUser, true>
{
};
Asher
Отправлено: 15.11.2004, 09:17


Мастер участка

Группа: Модератор
Сообщений: 550



Привет.
Сильно пока не вчитывался, понедельник утро как-никак, но навскидку... cool.gif

Применение reinterpret_cast выглядит уж черезчур жестоко smile.gif
По действию, IMHO разумеется, это сопоставимо с приведением к void*, а потом к любому требуемому типу. У меня гораздо более слабые нервы...

Прежде чем что-либо удалять не помешает сделать assert(NULL != pObj); В результирующем коде он не поучаствует, но при отладке сдорово поможет.

Сам подход к потокобезопасности вполне нормален и типичен, но мне, например, больше импонирует выриант подхода изложенный Zai++ здесь.
Потокобезопасное программирование
По сути это то-же самое, отличие только в "оформлении"
Из преимуществ: возможность быстро добавить к любому классу, добавив только код конструктора, и оставляет возможность использования непотокобезопасных методов.
Хотя если делать законченную библиотеку для передачи другому народу, то может это уже и не преимущество... wink.gif

Отредактировано Asher — 15/11/2004, 11:20
olegenty
Отправлено: 15.11.2004, 11:19


Ветеран

Группа: Модератор
Сообщений: 2412



2 Asher

в таком контексте я не рассуждал, но решение красивое. одно плохо — макросы. я никогда не писал на C, а при изучении C++ смотрел на них очень вскользь. если получится, просто добавлю шаблонную функцию с тем же смыслом, если нет — оставлю, как есть.

поясни, пожалуйста, более подробно, про reinterpret_cast, я не понял твоей мысли о слабости нервов.

accert — принимается, не подумал...
olegenty
Отправлено: 15.11.2004, 11:26


Ветеран

Группа: Модератор
Сообщений: 2412



2 Asher
всё, успел и мысль понять (кажется). просто заменю на static_cast()

Вернуться в Аспекты и идеология профессиональной разработки ПО