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
|
Привет.
Сильно пока не вчитывался, понедельник утро как-никак, но навскидку...
Применение reinterpret_cast выглядит уж черезчур жестоко
По действию, IMHO разумеется, это сопоставимо с приведением к void*, а потом к любому требуемому типу. У меня гораздо более слабые нервы...
Прежде чем что-либо удалять не помешает сделать assert(NULL != pObj); В результирующем коде он не поучаствует, но при отладке сдорово поможет.
Сам подход к потокобезопасности вполне нормален и типичен, но мне, например, больше импонирует выриант подхода изложенный Zai++ здесь.
Потокобезопасное программирование
По сути это то-же самое, отличие только в "оформлении"
Из преимуществ: возможность быстро добавить к любому классу, добавив только код конструктора, и оставляет возможность использования непотокобезопасных методов.
Хотя если делать законченную библиотеку для передачи другому народу, то может это уже и не преимущество...
Отредактировано 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()
|
|
|