118
118
template < typename R, bool TRACE > class RackAllocPool;
119
119
template < typename R, bool TRACE > class RackAllocFreeList;
121
class epicsShareClass AllocatorArenaUntyped {
123
typedef void ( * PThreadExitHandler ) ( void * );
124
AllocatorArenaUntyped ( PThreadExitHandler );
125
int installExitHandler ();
126
epicsThreadPrivateId id ( PThreadExitHandler );
128
AllocatorArenaUntyped * m_pNext;
129
epicsThreadPrivateId m_id;
130
PThreadExitHandler m_pThreadExit;
131
void m_init ( PThreadExitHandler );
132
static void m_exitFunc ( void * );
122
136
// T - the allocation type
123
137
// N - the block size for pool allocation will be sizeof ( T ) * N
193
207
bool operator == ( AllocatorArena const & );
194
208
bool operator != ( AllocatorArena const & );
196
union ThreadPrivateId {
197
ThreadPrivateId () : m_epics ( 0 ) {}
198
epicsThreadPrivateId m_epics;
201
210
typedef typename A :: Rack M_Rack;
202
211
static A m_rackAlloc;
203
static ThreadPrivateId m_thrPrivId;
204
static void m_init ();
205
static M_Rack * m_factory ( M_Rack * pRackPrev );
212
static AllocatorArenaUntyped m_untyped;
213
static M_Rack * m_factory ( epicsThreadPrivateId, M_Rack * pRackPrev );
206
214
static pointer m_threadPrivateAlloc ();
207
215
static void m_epicsExitFunc ( void * );
208
216
}; // end of class AllocatorArena
431
inline AllocatorArenaUntyped :: AllocatorArenaUntyped (
432
PThreadExitHandler const f )
437
inline epicsThreadPrivateId
438
AllocatorArenaUntyped :: id ( PThreadExitHandler f )
440
// additional lazy init prevents static init order issues
423
447
template < typename T, size_t N, typename A >
424
448
A AllocatorArena < T, N, A > :: m_rackAlloc;
540
564
template < typename T, size_t N, typename A >
541
void AllocatorArena < T, N, A > :: m_init ()
543
STATIC_ASSERT ( sizeof ( m_thrPrivId.m_cmpAndSwap ) ==
544
sizeof ( m_thrPrivId.m_epics ) );
545
ThreadPrivateId newId;
546
newId.m_epics = epicsThreadPrivateCreate ();
547
if ( ! newId.m_epics ) {
548
throw ThreadPrivateIdBadAlloc ();
550
const EpicsAtomicPtrT pBefore =
551
epicsAtomicCmpAndSwapPtrT ( & m_thrPrivId.m_cmpAndSwap,
552
0, newId.m_cmpAndSwap );
554
epicsThreadPrivateDelete ( newId.m_epics );
558
template < typename T, size_t N, typename A >
559
565
typename A :: Rack *
560
AllocatorArena < T, N, A > :: m_factory ( M_Rack * const pRackPrev )
566
AllocatorArena < T, N, A > :: m_factory ( epicsThreadPrivateId const id,
567
M_Rack * const pRackPrev )
562
569
M_Rack * const pRack = m_rackAlloc.create ();
563
570
assert ( pRack );
564
571
pRack->addReference ();
565
epicsThreadPrivateSet ( m_thrPrivId.m_epics, pRack );
572
epicsThreadPrivateSet ( id, pRack );
566
573
if ( pRackPrev ) {
567
574
if ( pRackPrev->removeReference () == 0u ) {
568
575
m_rackAlloc.destroy ( pRackPrev );
572
const int status = epicsAtThreadExit ( m_epicsExitFunc, 0 );
579
const int status = m_untyped.installExitHandler ();
573
580
if ( status < 0 ) {
574
581
if ( pRack->removeReference () == 0u ) {
575
582
m_rackAlloc.destroy ( pRack );
577
epicsThreadPrivateSet ( m_thrPrivId.m_epics, 0 );
584
epicsThreadPrivateSet ( id, 0 );
578
585
throw AtThreadExitBadAlloc ();
585
592
typename AllocatorArena < T, N, A > :: pointer
586
593
AllocatorArena < T, N, A > :: m_threadPrivateAlloc ()
588
if ( ! m_thrPrivId.m_epics ) {
591
void * const pPriv = epicsThreadPrivateGet ( m_thrPrivId.m_epics );
595
const epicsThreadPrivateId id = m_untyped.id ( m_epicsExitFunc );
596
void * const pPriv = epicsThreadPrivateGet ( id );
592
597
M_Rack * pRack = reinterpret_cast < M_Rack * > ( pPriv );
593
598
pointer p = pRack ? pRack->alloc () : 0;
595
pRack = m_factory ( pRack );
600
pRack = m_factory ( id, pRack );
596
601
assert ( pRack );
597
602
p = pRack->alloc ();
603
608
template < typename T, size_t N, typename A >
604
void AllocatorArena < T, N, A > :: m_epicsExitFunc ( void * /* arg */ )
609
void AllocatorArena < T, N, A > :: m_epicsExitFunc ( void * const pPriv )
606
if ( m_thrPrivId.m_epics ) {
607
void * const pPriv = epicsThreadPrivateGet ( m_thrPrivId.m_epics );
609
M_Rack * pRack = reinterpret_cast < M_Rack * > ( pPriv );
610
if ( pRack->removeReference () == 0u ) {
611
m_rackAlloc.destroy ( pRack );
613
epicsThreadPrivateSet ( m_thrPrivId.m_epics, 0 );
611
M_Rack * pRack = reinterpret_cast < M_Rack * > ( pPriv );
612
if ( pRack->removeReference () == 0u ) {
613
m_rackAlloc.destroy ( pRack );
698
697
m_epicsExitFunc ( 0 );
702
700
template < typename T, size_t N, typename A >
703
typename AllocatorArena < T, N, A > :: ThreadPrivateId
704
AllocatorArena < T, N, A > :: m_thrPrivId;
701
AllocatorArenaUntyped
702
AllocatorArena < T, N, A > :: m_untyped ( m_epicsExitFunc );
706
704
template < typename T, size_t N >
707
705
const size_t Rack < T, N > :: number = N;