Logo Search packages:      
Sourcecode: maxdb-7.5.00 version File versions

void* sqltlsgetmemory ( int  key,
size_t  bytes,
void(*)(void *)  initfunc,
IFR_Bool  initialize 
)

Gets thread-local memory that is mapped to a specific key. The memory is freed at thread exit, if not before.

Parameters:
key The key to the TLS, which must be less than IFR_TLSINDEX_MAX.
bytes The size in bytes that are to be allocated.
initfunc A function called once when the memory is allocated, if not NULL
initialize Whether the allocation should be done, if the key is not found.
Returns:
The memory identified by key, or 0 if there is a system level error, or there is no memory and initialize was false.

Definition at line 325 of file IFRUtil_Tls.cpp.

References tls_memchunk::memory, sqlgetthreadid(), sqlgettls(), sqlsettls(), and tls_memchunk::threadid.

    {
        if(key <0 || key>=IFR_TLSINDEX_MAX) {
            return 0;
        }
        
        // !!!
        // we don't have to wrap this into sqlonce, and we 
        // MUST NOT do so, as it is called the 1st defined time
        // already in a sqlonce context
        // !!!
        if(!tls_initialised) {
            if(!initialize) {
                return 0;
            }
            allocate_tls(&tls_init_successfully);
            tls_initialised=1;
        }
        
        if(!tls_init_successfully) {
            return 0;
        }
        // we can get the content 
        void *handle=sqlgettls(tls_key);
        
        if(handle == 0 && !initialize) {
            return 0;
        }
        
#ifdef _WIN32
        if(handle == 0) {
            teo07_ThreadId tid=sqlgetthreadid();
            IFR_UInt4 hash=hash_threadid(tid);
            IFR_UInt4 initialhash=hash;
            
            while(true) {
                // we must lock the position before we can enter
                while(InterlockedCompareExchange(tls_mem_lock + hash, 1, 0)) {
                    Sleep(50);
                }
                if(tls_mem[hash].threadid == 0) {
                    tls_mem[hash].threadid = tid;
                    InterlockedExchange(tls_mem_lock + hash, 0);
                    break;
                } else {
                    // check whether there is someone real in this ...
                    IFR_Bool canOccupy=false;
                    HANDLE h = OpenThread(THREAD_QUERY_INFORMATION,
                                          FALSE,
                                          tls_mem[hash].threadid);
                    // if the open fails, this thread does not exist,
                    // otherwise we need to check whether it is still executing.
                    if(h != NULL) {
                        DWORD exitcode;
                        BOOL  getexit_result;
                        getexit_result=GetExitCodeThread(h, &exitcode);
                        CloseHandle(h);
                        if(getexit_result && exitcode!=STILL_ACTIVE) {
                            canOccupy=true;
                        }
                    } else {
                        canOccupy=true;
                    }
                    
                    if(canOccupy) {
                        tls_mem[hash].threadid = tid;
                        InterlockedExchange(tls_mem_lock + hash, 0);
                        // recycle the waste of the previous thread
                        for(int i=0; i<IFR_TLSINDEX_MAX; ++i) {
                            if(tls_mem[hash].memory[i]) {
                                char *todel=(char *) tls_mem[hash].memory[i];
                                sqlfree((tsp00_Uint1 *)todel);
                                tls_mem[hash].memory[i]=0;
                            }
                        }
                        break;
                    } else {
                        InterlockedExchange(tls_mem_lock + hash, 0);
                        hash= (hash+1) % TLS_MAX_THREADS;
                        if(hash == initialhash) {
                            // if we have traveled one round, we give up
                            return 0;
                        }
                    }
                } 
            }
            
            handle = tls_mem + hash;
            tsp00_ErrTextc  errtext;
            teo07_ThreadErr threaderr;
            sqlsettls(tls_key, handle, errtext, &threaderr);
        }
#else
        // Unix - we look whether we have a handle, otherwise simply create one.
        if(handle == 0) {
            tsp00_Bool wasok;
            tls_memchunk *chunk;
            sqlallocat(sizeof(tls_memchunk), ( tsp00_Uint1 **) &chunk, &wasok);
            for(int i=0; i<IFR_TLSINDEX_MAX; ++i) {
                chunk->memory[i]=0;
            }
            chunk->threadid=sqlgetthreadid();
            handle = chunk;
            tsp00_ErrTextc  errtext;
            teo07_ThreadErr threaderr;
            sqlsettls(tls_key, handle, errtext, &threaderr);
        }
#endif
           
        tls_memchunk *chunk=(tls_memchunk*)handle;
        if(chunk->memory[key] == 0) {
            if(!initialize) {
                return 0;
            }
            tsp00_Bool wasok;
            sqlallocat(bytes, (tsp00_Uint1 **) &(chunk->memory[key]), &wasok);
            if(initfunction != 0) {
                (*initfunction)(chunk->memory[key]);
            }
        }
        return chunk->memory[key];

    }


Generated by  Doxygen 1.6.0   Back to index