summaryrefslogtreecommitdiff
path: root/plugins/Dbx_tree/src/TLS.h
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/Dbx_tree/src/TLS.h')
-rw-r--r--plugins/Dbx_tree/src/TLS.h161
1 files changed, 161 insertions, 0 deletions
diff --git a/plugins/Dbx_tree/src/TLS.h b/plugins/Dbx_tree/src/TLS.h
new file mode 100644
index 0000000000..d309090a34
--- /dev/null
+++ b/plugins/Dbx_tree/src/TLS.h
@@ -0,0 +1,161 @@
+/*
+
+dbx_tree: tree database driver for Miranda IM
+
+Copyright 2010 Michael "Protogenes" Kunz,
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#pragma once
+
+#include "lockfree_hashmap.h"
+
+template <typename TAdministrator, typename TData>
+class CThreadLocalStorage
+{
+ private:
+ typedef struct TListElem
+ {
+ TListElem * Next;
+ TAdministrator * Admin;
+ TData Data;
+ TListElem(TListElem * ANext, TAdministrator * AAdmin, const TData & AData)
+ : Next(ANext), Admin(AAdmin), Data(AData)
+ { };
+
+ } TListElem, *PListElem;
+ static __declspec(thread) PListElem m_Head;
+
+ static inline uint32_t DummyHash(const void * Data, uint32_t Length)
+ {
+ return *reinterpret_cast<const uint32_t *>(Data);
+ }
+
+ lockfree::hash_map<DWORD, TData, DummyHash> * m_LockfreeList;
+ typedef typename lockfree::hash_map<DWORD, TData, DummyHash>::iterator TThreadStorage;
+
+ public:
+ CThreadLocalStorage();
+ ~CThreadLocalStorage();
+
+ TData & Open(TAdministrator * Admin, const TData & Default);
+ TData * Find(TAdministrator * Admin);
+ void Remove(TAdministrator * Admin);
+};
+
+const bool _CanUseTLS = ((LOBYTE(LOWORD(GetVersion()))) >= 6);
+
+template <typename TAdministrator, typename TData>
+typename CThreadLocalStorage<TAdministrator, TData>::PListElem CThreadLocalStorage<TAdministrator, TData>::m_Head = NULL;
+
+
+template <typename TAdministrator, typename TData>
+CThreadLocalStorage<TAdministrator, TData>::CThreadLocalStorage()
+{
+ m_LockfreeList = NULL;
+ if (!_CanUseTLS)
+ m_LockfreeList = new lockfree::hash_map<DWORD, TData, DummyHash>();
+}
+template <typename TAdministrator, typename TData>
+CThreadLocalStorage<TAdministrator, TData>::~CThreadLocalStorage()
+{
+ if (m_LockfreeList)
+ delete m_LockfreeList;
+}
+
+
+template <typename TAdministrator, typename TData>
+typename TData & CThreadLocalStorage<TAdministrator, TData>::Open(typename TAdministrator * Admin, const TData & Default)
+{
+ if (_CanUseTLS)
+ {
+ PListElem * last = &m_Head;
+ PListElem i = m_Head;
+ while (i && (i->Admin != Admin))
+ {
+ last = &i->Next;
+ i = i->Next;
+ }
+
+ if (i)
+ {
+ *last = i->Next;
+ i->Next = m_Head;
+ m_Head = i;
+ } else {
+ m_Head = new TListElem(m_Head, Admin, Default);
+ }
+ return m_Head->Data;
+ } else {
+ TThreadStorage & res = m_LockfreeList->insert(std::make_pair(GetCurrentThreadId(), Default)).first;
+ return res->second;
+ }
+}
+
+template <typename TAdministrator, typename TData>
+typename TData * CThreadLocalStorage<TAdministrator, TData>::Find(typename TAdministrator * Admin)
+{
+ if (_CanUseTLS)
+ {
+ PListElem * last = &m_Head;
+ PListElem i = m_Head;
+ while (i && (i->Admin != Admin))
+ {
+ last = &i->Next;
+ i = i->Next;
+ }
+
+ if (i)
+ {
+ *last = i->Next;
+ i->Next = m_Head;
+ m_Head = i;
+ } else {
+ return NULL;
+ }
+ return &m_Head->Data;
+ } else {
+ TThreadStorage & res = m_LockfreeList->find(GetCurrentThreadId());
+ if (res != m_LockfreeList->end())
+ return &res->second;
+ else
+ return NULL;
+ }
+}
+
+template <typename TAdministrator, typename TData>
+void CThreadLocalStorage<TAdministrator, TData>::Remove(typename TAdministrator * Admin)
+{
+ if (_CanUseTLS)
+ {
+ PListElem * last = &m_Head;
+ PListElem i = m_Head;
+ while (i && (i->Admin != Admin))
+ {
+ last = &i->Next;
+ i = i->Next;
+ }
+
+ if (i)
+ {
+ *last = i->Next;
+ delete i;
+ }
+ } else {
+ m_LockfreeList->erase(GetCurrentThreadId());
+ }
+}