FBIagent
Erfahrenes Mitglied
Guten Tag,
ich habe mir eine kleine Allocator Klasse geschrieben, die mir nach Wahl einen
FixedSize oder DynamicSize Pool an Object-Pointern zur verfügung stellt.
Der Allocator ist so Konstruiert, dass als Template Typ(Typ für die Object-Pointer)
nur Klassen angegeben werden können, die von der Base "Reusable" erben.
Um den Thread der gerade ein Reusable Object anfordert, habe zur entlastung einen
AllocatorUpdate Thread für den Allocator geschrieben, damit dieser das nächste
Reusable Object kenzeichnet, damit der Thread, der ein Object fordert nicht selbst
danach suchen muss.
Nun stellt sich mir nur eine Frage. Und zwar wenn der Allocator für Dynamische
Anzahl von Objects initialisiert wird, muss das realocieren ja irgendwo stattfinden.
Da hätte ich nun 2 möglichkeiten:
1. Der Thread der gerade ein object anfordert prüft ob ein reusable zum reusen gekennzeichnet ist. Dies versucht dieser 5 mal in Intervallen von 10ms. Wenn bis dahin kein Reusable Object vom AlocatorUpdate thread gekennzeichnet wird eine MemoryException geworfen.
2. Da der AllocatorUpdate Thread immer das NextReusable kennzeichnet könnte dieser wenn er kein neues reusable findet neuen spiecher allocieren.
void Run() ist diemthode überschrieben aus "Thread" die aufgerufen wird wenn man den thread startet.
Wie man sieht verwende ich im momment die erste variante.
Was haltet ihr von der 2ten Variante und was denkt ihr welche Vorteile und Nachteile
die beiden möglichkeiten miteinander verglichen mitbringen.
Danke im Vorraus
Best wishes
FBIagent
ich habe mir eine kleine Allocator Klasse geschrieben, die mir nach Wahl einen
FixedSize oder DynamicSize Pool an Object-Pointern zur verfügung stellt.
Der Allocator ist so Konstruiert, dass als Template Typ(Typ für die Object-Pointer)
nur Klassen angegeben werden können, die von der Base "Reusable" erben.
Um den Thread der gerade ein Reusable Object anfordert, habe zur entlastung einen
AllocatorUpdate Thread für den Allocator geschrieben, damit dieser das nächste
Reusable Object kenzeichnet, damit der Thread, der ein Object fordert nicht selbst
danach suchen muss.
Nun stellt sich mir nur eine Frage. Und zwar wenn der Allocator für Dynamische
Anzahl von Objects initialisiert wird, muss das realocieren ja irgendwo stattfinden.
Da hätte ich nun 2 möglichkeiten:
1. Der Thread der gerade ein object anfordert prüft ob ein reusable zum reusen gekennzeichnet ist. Dies versucht dieser 5 mal in Intervallen von 10ms. Wenn bis dahin kein Reusable Object vom AlocatorUpdate thread gekennzeichnet wird eine MemoryException geworfen.
2. Da der AllocatorUpdate Thread immer das NextReusable kennzeichnet könnte dieser wenn er kein neues reusable findet neuen spiecher allocieren.
C++:
#ifndef __UTILS_ALLOC_H__
#define __UTILS_ALLOC_H__
#include ".\MemoryException.h"
#include ".\WinAPI\Parallelism\Mutex.h"
#include ".\WinAPI\Parallelism\MutexLocker.h"
#include ".\WinAPI\Parallelism\Thread.h"
#include <iostream>
#include <windows.h>
namespace Utils {
enum AllocatorType {
AT_FIXED,
AT_DYNAMIC
};
template < class T >
class Allocator
: public Utils::WinAPI::Parallelism::Thread {
public:
Allocator( unsigned int Size, AllocatorType AllocType )
: m_AllocInterval( Size ), m_Size( m_AllocInterval ), m_NextReusable( NULL ), m_PoolMutex(), m_AllocType( AllocType ) {
try {
m_Pool = new T*[ m_Size ];
for ( unsigned int i = 0;i < m_Size;++ i ) {
m_Pool[ i ] = new T();
}
} catch ( std::bad_alloc &e ) {
throw mMemoryException( StaticString( "Failed to pre allocate allocator pool objects!" ), sizeof( T ) * m_Size );
}
}
virtual ~Allocator() {
for ( unsigned int i = 0;i < m_Size;++ i ) {
delete m_Pool[ i ];
}
delete[] m_Pool;
}
void Run() {
while ( true ) {
MuteBlock( m_PoolMutex ) {
if ( m_NextReusable == NULL ) {
//bool NewObject = true;
for ( unsigned int i = 0;i < m_Size;++ i ) {
if ( m_Pool[ i ]->IsReusable() ) {
m_NextReusable = m_Pool[ i ];
//NewObject = false;
break;
}
}
/* if ( NewObject ) {
// TODO: allocate space for m_AllocInterval new objects
}*/
}
}
Sleep( 1 );
}
}
T *Get() {
int Attemps = 0;
while ( true ) {
MuteBlock( m_PoolMutex ) {
if ( m_NextReusable != NULL ) {
T *Reusable = m_NextReusable;
m_NextReusable = NULL;
Reusable->Reuse();
return Reusable;
}
}
++ Attemps;
if ( Attemps == 5 ) {
MuteBlock( m_PoolMutex ) {
if ( m_AllocType == AT_DYNAMIC ) {
T **TempPool = NULL;
try {
TempPool = new T*[ m_Size + m_AllocInterval ];
for ( unsigned int i = 0;i < m_Size + m_AllocInterval;++ i ) {
if ( i < m_Size ) {
TempPool[ i ] = m_Pool[ i ];
} else {
try {
TempPool[ i ] = new T();
} catch ( std::bad_alloc &e ) {
for ( int j = m_Size; j < i;++ j ) {
delete TempPool[ j ];
}
delete[] TempPool;
throw e;
}
}
}
delete[] m_Pool;
m_Pool = TempPool;
m_Size += m_AllocInterval;
m_Pool[ m_Size - 1 ]->Reuse();
return m_Pool[ m_Size - 1 ];
} catch ( std::bad_alloc &e ) {
throw mMemoryException( StaticString( "Failed to pre allocate new allocator pool objects!" ), sizeof( T ) );
}
} else if ( m_AllocType == AT_FIXED ) {
return NULL;
}
}
}
Sleep( 10 );
}
}
unsigned int GetSize() {
MuteBlock( m_PoolMutex ) {
return m_Size;
}
}
private:
unsigned int m_AllocInterval;
unsigned int m_Size;
T **m_Pool;
T *m_NextReusable;
Utils::WinAPI::Parallelism::Mutex m_PoolMutex;
AllocatorType m_AllocType;
};
} // namespace Utils
#endif
void Run() ist diemthode überschrieben aus "Thread" die aufgerufen wird wenn man den thread startet.
Wie man sieht verwende ich im momment die erste variante.
Was haltet ihr von der 2ten Variante und was denkt ihr welche Vorteile und Nachteile
die beiden möglichkeiten miteinander verglichen mitbringen.
Danke im Vorraus
Best wishes
FBIagent
Zuletzt bearbeitet von einem Moderator: