Библиотека реализующая ThreadLocal<T>
От: Caracrist https://1pwd.org/
Дата: 13.04.12 00:24
Оценка:
Покритикуйте имплементацию обёртки для thread local объектов:
+ tls а не эмулятор, со всеми вытекающими
+ простая имплементация
+ проблем мало, и они декларированны
+ работает
  ThreadLocal.h
#include "windows.h"
class ThreadLocalBase
{
public:
    virtual void DestructThreadLocalInstance() = 0;
    void * GetValue()
    {
        return TlsGetValue(GetIndex());
    }
    void SetValue(void * val)
    {
        TlsSetValue(GetIndex(), val);
    }
    DWORD GetIndex()
    {
        return m_tlsIndex;
    }
protected:
    DWORD m_tlsIndex;
    ~ThreadLocalBase(){}
};

DWORD AddAtThreadExit(ThreadLocalBase *);
void RemoveAtThreadExit(ThreadLocalBase *);

template<typename T>
class ThreadLocal : protected ThreadLocalBase
{
public:
    ThreadLocal()
    {
        m_tlsIndex = AddAtThreadExit(this);
    }    
    ~ThreadLocal()
    {
                ThreadLocal::DestructThreadLocalInstance();
        RemoveAtThreadExit(this);
    }    
    T * operator->()
    {        
        return &(**this);
    }
    T& operator*()
    {
        T *  val = (T*)GetValue();
        if (!val) 
        {
            val = new T();
            SetValue(val);
        }
        return *val;
    }
private:
    virtual void DestructThreadLocalInstance() override
    {
        void * val = GetValue();
        if (val)
        {
            delete (T*)val;
            SetValue((void*)0);
        }
    }
};

  ThreadLocal.cpp
#include "ThreadAtExit.h"
#include <set>

volatile long mutex = 0;
struct lock
{
    lock() { while (InterlockedExchange(&mutex, 1) == 1) SwitchToThread();}
    ~lock() { InterlockedExchange(&mutex, 0);}
};
std::set<ThreadLocalBase *> AtExitSet;
DWORD AddAtThreadExit(ThreadLocalBase * tlb)
{
    lock _;
    AtExitSet.insert(tlb);
    return TlsAlloc();
}
void RemoveAtThreadExit(ThreadLocalBase * tlb)
{
    lock _;
    AtExitSet.erase(tlb);
    TlsFree(tlb->GetIndex());
}
void DestructThreadLocals()
{
    lock _;
    for(std::set<ThreadLocalBase *>::iterator it = AtExitSet.begin(), it_end =  AtExitSet.end();
        it != it_end;
        ++it)
    {
        (*it)->DestructThreadLocalInstance();
    }
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        DestructThreadLocals();
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

  ThreadLocal.def
LIBRARY   ThreadLocal
EXPORTS
   AddAtThreadExit   @1
   RemoveAtThreadExit   @2


Сразу оговорюсь, что это не продакшен код, а всего лиш собранная на коленке и доведённая до состояния стояния идея, решающая возможно основную, но относительно узкую задачу.
Соответственно, самодельный спин мютекс логично заменить чем-то принятым на месте работы, а имена функций, классов и переменных подогнать под местные конвенции.

О недостатках:
1. Не достаточно настраевоемо
2. Windows specific
3. Требует дополнительный Dll
4. Не работает с Delay Load (в деструкторе вызывается экспортируемая функция)
5. Выгрузка бинарника со статиком приводит к потере объекта для каждого из построивших себе инстанс оставшихся потоков.

Моё мнение об этих недостатках:
1. можно расширить по мере надобности
2. увы (если идея ясна, то не сложно переписать на pthread)
3. в большинстве случаев не проблема
4. По большому счёту, нет такой нужды
5. В подавляющем большинстве случаев магии выгрузки библиотек нет, и проблем с этим связанных решать не надо.
~~~~~
~lol~~
~~~ Single Password Solution
Re: Библиотека реализующая ThreadLocal<T>
От: Andrew S Россия http://alchemy-lab.com
Дата: 20.05.12 21:21
Оценка: 2 (1)
C>3. Требует дополнительный Dll

TLS Callbacks
http://www.codeproject.com/Articles/8113/Thread-Local-Storage-The-C-Way

PS. Мое мнение об этом — скрипач не нужен. Храните деньги в сберегательной кассе переменные на стеке потока. Если нет возможности куда-то вниз передать — используйте tls только как моникер на объект. Владеть им он не должен.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re: Библиотека реализующая ThreadLocal<T>
От: о_О
Дата: 20.05.12 21:47
Оценка:
Здравствуйте, Caracrist, Вы писали:

C>Сразу оговорюсь, что это не продакшен код, а всего лиш собранная на коленке и доведённая до состояния стояния идея

и какой смысл выкладывать не продакшен код? написать — не проблема, проблема написать хорошо.

C>О недостатках:

C>1. Не достаточно настраевоемо
даже 100 строк кода нет

C>2. Windows specific

хорошо хоть SwitchToThread(), а не Sleep() но вообще, по хорошему, надо отрывать кое-чего за невозможность контролировать такие места

C>3. Требует дополнительный Dll

О_О

собственно, возникает вопрос: а че так плоско-то? кому оно кроме тебе надо в столь зачаточном виде?
Re: Библиотека реализующая ThreadLocal<T>
От: о_О
Дата: 20.05.12 21:58
Оценка:
Да и, есть же __declspec(thread). Что с ним не так?
Re[2]: Библиотека реализующая ThreadLocal<T>
От: Andrew S Россия http://alchemy-lab.com
Дата: 20.05.12 22:21
Оценка: 1 (1)
о_О>Да и, есть же __declspec(thread). Что с ним не так?

Не работает в dll. http://support.microsoft.com/kb/118816/en-us
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[2]: Библиотека реализующая ThreadLocal<T>
От: Caracrist https://1pwd.org/
Дата: 21.05.12 06:57
Оценка:
Здравствуйте, о_О, Вы писали:

C>>О недостатках:

C>>1. Не достаточно настраевоемо
о_О>даже 100 строк кода нет
C>>можно расширить по мере надобности

C>>2. Windows specific

о_О>хорошо хоть SwitchToThread(), а не Sleep() но вообще, по хорошему, надо отрывать кое-чего за невозможность контролировать такие места
C>>самодельный спин мютекс логично заменить чем-то принятым на месте работы

C>>3. Требует дополнительный Dll

о_О>О_О
о_О>собственно, возникает вопрос: а че так плоско-то? кому оно кроме тебе надо в столь зачаточном виде?
оно и мне не нужно на данный момент
~~~~~
~lol~~
~~~ Single Password Solution
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.