~johill-lanl/epics-base/server1

« back to all changes in this revision

Viewing changes to src/libCom/misc/AllocatorArena.h

  • Committer: Jeff Hill
  • Date: 2019-04-18 00:47:52 UTC
  • Revision ID: johill@lanl.gov-20190418004752-x0oriyjzx4232ppt
added optimizations so that onlly one epics exit handler per-thread is allocated, on RTEMS allocated with calloc

Show diffs side-by-side

added added

removed removed

Lines of Context:
118
118
template < typename R, bool TRACE > class RackAllocPool;
119
119
template < typename R, bool TRACE > class RackAllocFreeList;
120
120
 
 
121
class epicsShareClass AllocatorArenaUntyped {
 
122
public:
 
123
    typedef void ( * PThreadExitHandler ) ( void * );
 
124
    AllocatorArenaUntyped ( PThreadExitHandler );
 
125
    int installExitHandler ();
 
126
    epicsThreadPrivateId id ( PThreadExitHandler );
 
127
private:
 
128
    AllocatorArenaUntyped * m_pNext;
 
129
    epicsThreadPrivateId m_id;
 
130
    PThreadExitHandler m_pThreadExit;
 
131
    void m_init ( PThreadExitHandler );
 
132
    static void m_exitFunc ( void * );
 
133
};
 
134
 
121
135
//
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 & );
195
209
private:
196
 
    union ThreadPrivateId {
197
 
        ThreadPrivateId () : m_epics ( 0 ) {}
198
 
        epicsThreadPrivateId m_epics;
199
 
        void * m_cmpAndSwap;
200
 
    };
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
420
428
    }
421
429
}
422
430
 
 
431
inline AllocatorArenaUntyped :: AllocatorArenaUntyped ( 
 
432
                                PThreadExitHandler const f )
 
433
{
 
434
    m_init ( f );
 
435
}
 
436
 
 
437
inline epicsThreadPrivateId 
 
438
        AllocatorArenaUntyped :: id ( PThreadExitHandler f )
 
439
{
 
440
    // additional lazy init prevents static init order issues
 
441
    if ( ! m_id ) {
 
442
        m_init ( f );
 
443
    }
 
444
    return m_id;
 
445
}
 
446
 
423
447
template < typename T, size_t N, typename A >
424
448
A AllocatorArena < T, N, A > :: m_rackAlloc;
425
449
 
538
562
}
539
563
 
540
564
template < typename T, size_t N, typename A >
541
 
void AllocatorArena < T, N, A > :: m_init ()
542
 
{
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 ();
549
 
    }
550
 
    const EpicsAtomicPtrT pBefore = 
551
 
        epicsAtomicCmpAndSwapPtrT ( & m_thrPrivId.m_cmpAndSwap, 
552
 
                                    0, newId.m_cmpAndSwap );
553
 
    if ( pBefore ) {
554
 
        epicsThreadPrivateDelete ( newId.m_epics );
555
 
    }
556
 
}
557
 
 
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 )
561
568
{
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 );
569
576
        }
570
577
    }
571
578
    else {
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 );
576
583
            }
577
 
            epicsThreadPrivateSet ( m_thrPrivId.m_epics, 0 );
 
584
            epicsThreadPrivateSet ( id, 0 );
578
585
            throw AtThreadExitBadAlloc ();
579
586
        }
580
587
    }
585
592
typename AllocatorArena < T, N, A > :: pointer
586
593
    AllocatorArena < T, N, A > :: m_threadPrivateAlloc ()
587
594
{
588
 
    if ( ! m_thrPrivId.m_epics ) {
589
 
        m_init ();
590
 
    }
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;
594
599
    if ( ! p ) {
595
 
        pRack = m_factory ( pRack );
 
600
        pRack = m_factory ( id, pRack );
596
601
        assert ( pRack );
597
602
        p = pRack->alloc ();
598
603
        assert ( p );
601
606
}
602
607
 
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 )
605
610
{
606
 
    if ( m_thrPrivId.m_epics ) {
607
 
        void * const pPriv = epicsThreadPrivateGet ( m_thrPrivId.m_epics );
608
 
        if ( pPriv ) {
609
 
            M_Rack * pRack = reinterpret_cast < M_Rack * > ( pPriv );
610
 
            if ( pRack->removeReference () == 0u ) {
611
 
                m_rackAlloc.destroy ( pRack );
612
 
            }
613
 
            epicsThreadPrivateSet ( m_thrPrivId.m_epics, 0 );
614
 
        }
 
611
    M_Rack * pRack = reinterpret_cast < M_Rack * > ( pPriv );
 
612
    if ( pRack->removeReference () == 0u ) {
 
613
        m_rackAlloc.destroy ( pRack );
615
614
    }
616
615
}
617
616
 
698
697
    m_epicsExitFunc ( 0 );
699
698
}
700
699
 
701
 
 
702
700
template < typename T, size_t N, typename A >
703
 
typename AllocatorArena < T, N, A > :: ThreadPrivateId 
704
 
    AllocatorArena < T, N, A > :: m_thrPrivId;
705
 
 
 
701
AllocatorArenaUntyped 
 
702
        AllocatorArena < T, N, A > :: m_untyped ( m_epicsExitFunc );
 
703
 
706
704
template < typename T, size_t N >
707
705
const size_t Rack < T, N > :: number = N;
708
706