2004-03-26 00:12:50 +01:00
|
|
|
/*
|
2006-02-21 05:29:00 +01:00
|
|
|
* PROGRAM: Client/Server Common Code
|
|
|
|
* MODULE: fb_tls.h
|
|
|
|
* DESCRIPTION: Thread-local storage handlers
|
2004-03-26 00:12:50 +01:00
|
|
|
*
|
2004-06-30 03:26:40 +02:00
|
|
|
* The contents of this file are subject to the Initial
|
|
|
|
* Developer's Public License Version 1.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the
|
|
|
|
* License. You may obtain a copy of the License at
|
|
|
|
* http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
|
|
|
|
*
|
|
|
|
* Software distributed under the License is distributed AS IS,
|
|
|
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing rights
|
|
|
|
* and limitations under the License.
|
|
|
|
*
|
|
|
|
* The Original Code was created by Nickolay Samofatov
|
|
|
|
* for the Firebird Open Source RDBMS project.
|
|
|
|
*
|
|
|
|
* Copyright (c) 2004 Nickolay Samofatov <nickolay@broadviewsoftware.com>
|
|
|
|
* and all contributors signed below.
|
|
|
|
*
|
|
|
|
* All Rights Reserved.
|
|
|
|
* Contributor(s): ______________________________________.
|
|
|
|
*
|
|
|
|
*
|
2004-03-26 00:12:50 +01:00
|
|
|
*/
|
2008-12-05 01:56:15 +01:00
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
#ifndef CLASSES_FB_TLS_H
|
|
|
|
#define CLASSES_FB_TLS_H
|
2004-03-26 00:12:50 +01:00
|
|
|
|
|
|
|
// This unit defines a few handy macros
|
|
|
|
// TLS_DECLARE is used in place of variable declaration
|
|
|
|
// TLS_GET gives value of thread-specific variable
|
|
|
|
// TLS_SET sets value of thread-specific variable
|
|
|
|
//
|
|
|
|
// TLS variable type should be smaller than size of pointer to stay portable
|
|
|
|
|
2009-01-29 19:07:07 +01:00
|
|
|
#include "../common/classes/init.h"
|
|
|
|
|
2008-01-16 07:24:06 +01:00
|
|
|
#if defined(HAVE___THREAD)
|
2004-03-26 00:12:50 +01:00
|
|
|
// Recent GCC supports __thread keyword. Sun compiler and HP-UX should have it too
|
|
|
|
# define TLS_DECLARE(TYPE, NAME) __thread TYPE NAME
|
|
|
|
# define TLS_GET(NAME) NAME
|
2004-11-30 07:18:39 +01:00
|
|
|
# define TLS_SET(NAME, VALUE) NAME = (VALUE)
|
2004-04-06 07:53:36 +02:00
|
|
|
#elif defined(WIN_NT)
|
|
|
|
|
|
|
|
namespace Firebird {
|
|
|
|
|
|
|
|
template <typename T>
|
2009-01-29 19:07:07 +01:00
|
|
|
class Win32Tls : private InstanceControl
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2004-04-06 07:53:36 +02:00
|
|
|
public:
|
2009-03-04 11:26:16 +01:00
|
|
|
Win32Tls() : InstanceControl()
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2009-01-29 19:07:07 +01:00
|
|
|
if ((key = TlsAlloc()) == MAX_ULONG)
|
2006-02-21 05:29:00 +01:00
|
|
|
system_call_failed::raise("TlsAlloc");
|
2009-03-04 11:26:16 +01:00
|
|
|
// Allocated pointer is saved by InstanceList::constructor.
|
2009-03-05 07:05:19 +01:00
|
|
|
new InstanceControl::InstanceLink<Win32Tls, PRIORITY_TLS_KEY>(this);
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2008-04-19 13:11:10 +02:00
|
|
|
const T get()
|
|
|
|
{
|
2009-01-29 19:07:07 +01:00
|
|
|
fb_assert(key != MAX_ULONG);
|
|
|
|
const LPVOID value = TlsGetValue(key);
|
2006-02-21 05:29:00 +01:00
|
|
|
if ((value == NULL) && (GetLastError() != NO_ERROR))
|
|
|
|
system_call_failed::raise("TlsGetValue");
|
2009-01-29 19:07:07 +01:00
|
|
|
return (T) value;
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2008-04-19 13:11:10 +02:00
|
|
|
void set(const T value)
|
|
|
|
{
|
2009-01-29 19:07:07 +01:00
|
|
|
fb_assert(key != MAX_ULONG);
|
|
|
|
if (TlsSetValue(key, (LPVOID) value) == 0)
|
2006-02-21 05:29:00 +01:00
|
|
|
system_call_failed::raise("TlsSetValue");
|
|
|
|
}
|
2008-04-19 13:11:10 +02:00
|
|
|
~Win32Tls()
|
2009-01-29 19:07:07 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
void dtor()
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2006-02-21 05:29:00 +01:00
|
|
|
if (TlsFree(key) == 0)
|
|
|
|
system_call_failed::raise("TlsFree");
|
2009-01-29 19:07:07 +01:00
|
|
|
key = MAX_ULONG;
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2004-04-06 07:53:36 +02:00
|
|
|
private:
|
2008-12-05 01:56:15 +01:00
|
|
|
DWORD key;
|
2004-04-06 07:53:36 +02:00
|
|
|
};
|
|
|
|
} // namespace Firebird
|
2004-05-09 07:48:33 +02:00
|
|
|
# define TLS_DECLARE(TYPE, NAME) ::Firebird::Win32Tls<TYPE> NAME
|
2004-04-06 07:53:36 +02:00
|
|
|
# define TLS_GET(NAME) NAME.get()
|
2004-11-24 10:22:07 +01:00
|
|
|
# define TLS_SET(NAME, VALUE) NAME.set(VALUE)
|
2004-04-06 07:53:36 +02:00
|
|
|
|
2004-07-14 23:49:03 +02:00
|
|
|
// 14-Jul-2004 Nickolay Samofatov.
|
|
|
|
//
|
|
|
|
// Unfortunately, compiler-assisted TLS doesn't work with dynamic link libraries
|
2008-12-05 01:56:15 +01:00
|
|
|
// loaded via LoadLibrary - it intermittently crashes and these crashes are
|
2004-07-14 23:49:03 +02:00
|
|
|
// documented by MS. We may still use it for server binaries, but it requires
|
2008-12-05 01:56:15 +01:00
|
|
|
// some changes in build environment. Let's defer this till later point and
|
2004-07-14 23:49:03 +02:00
|
|
|
// think of reliable mean to prevent linking of DLL with code below (if enabled).
|
|
|
|
//
|
|
|
|
//# define TLS_DECLARE(TYPE, NAME) __declspec(thread) TYPE NAME
|
|
|
|
//# define TLS_GET(NAME) NAME
|
2004-11-30 07:18:39 +01:00
|
|
|
//# define TLS_SET(NAME, VALUE) NAME = (VALUE)
|
2004-03-26 00:12:50 +01:00
|
|
|
#else
|
|
|
|
|
2009-01-19 17:16:19 +01:00
|
|
|
#include "../common/classes/init.h"
|
|
|
|
|
2004-03-26 00:12:50 +01:00
|
|
|
#include <pthread.h>
|
|
|
|
|
|
|
|
namespace Firebird {
|
|
|
|
|
|
|
|
template <typename T>
|
2009-01-19 17:16:19 +01:00
|
|
|
class TlsValue : private InstanceControl
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2004-03-26 00:12:50 +01:00
|
|
|
public:
|
2009-03-04 11:26:16 +01:00
|
|
|
TlsValue() : InstanceControl()
|
2009-01-19 17:16:19 +01:00
|
|
|
#ifdef DEV_BUILD
|
|
|
|
, keySet(true)
|
|
|
|
#endif
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2009-01-14 15:27:11 +01:00
|
|
|
int rc = pthread_key_create(&key, NULL);
|
|
|
|
if (rc)
|
|
|
|
system_call_failed::raise("pthread_key_create", rc);
|
2009-03-04 11:26:16 +01:00
|
|
|
// Allocated pointer is saved by InstanceList::constructor.
|
|
|
|
new InstanceControl::InstanceLink<TlsValue, PRIORITY_TLS_KEY>(this);
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2009-03-05 01:52:25 +01:00
|
|
|
|
2008-04-19 13:11:10 +02:00
|
|
|
const T get()
|
|
|
|
{
|
2009-01-19 17:16:19 +01:00
|
|
|
fb_assert(keySet);
|
2006-02-21 05:29:00 +01:00
|
|
|
// We use double C-style cast to allow using scalar datatypes
|
|
|
|
// with sizes up to size of pointer without warnings
|
2009-01-15 04:46:48 +01:00
|
|
|
return (T)(IPTR) pthread_getspecific(key);
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2008-04-19 13:11:10 +02:00
|
|
|
void set(const T value)
|
|
|
|
{
|
2009-01-19 17:16:19 +01:00
|
|
|
fb_assert(keySet);
|
2009-01-15 08:41:11 +01:00
|
|
|
int rc = pthread_setspecific(key, (void*)(IPTR) value);
|
2009-01-19 17:16:19 +01:00
|
|
|
if (rc)
|
2009-01-14 15:27:11 +01:00
|
|
|
system_call_failed::raise("pthread_setspecific", rc);
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2008-04-19 13:11:10 +02:00
|
|
|
~TlsValue()
|
2009-01-19 17:16:19 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
void dtor()
|
2008-04-19 13:11:10 +02:00
|
|
|
{
|
2009-01-15 08:41:11 +01:00
|
|
|
int rc = pthread_key_delete(key);
|
2009-01-14 15:27:11 +01:00
|
|
|
if (rc)
|
|
|
|
system_call_failed::raise("pthread_key_delete", rc);
|
2009-01-19 17:16:19 +01:00
|
|
|
#ifdef DEV_BUILD
|
2009-01-14 15:27:11 +01:00
|
|
|
keySet = false;
|
2009-01-19 17:16:19 +01:00
|
|
|
#endif
|
2006-02-21 05:29:00 +01:00
|
|
|
}
|
2004-03-26 00:12:50 +01:00
|
|
|
private:
|
2008-12-05 01:56:15 +01:00
|
|
|
pthread_key_t key;
|
2009-01-19 17:16:19 +01:00
|
|
|
#ifdef DEV_BUILD
|
2009-01-14 15:27:11 +01:00
|
|
|
bool keySet; // This is used to avoid conflicts when destroying global variables
|
2009-01-19 17:16:19 +01:00
|
|
|
#endif
|
2004-03-26 00:12:50 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
} // namespace Firebird
|
|
|
|
|
2004-05-09 07:48:33 +02:00
|
|
|
# define TLS_DECLARE(TYPE, NAME) ::Firebird::TlsValue<TYPE> NAME
|
2004-03-26 00:12:50 +01:00
|
|
|
# define TLS_GET(NAME) NAME.get()
|
2004-11-24 10:22:07 +01:00
|
|
|
# define TLS_SET(NAME, VALUE) NAME.set(VALUE)
|
2004-03-26 00:12:50 +01:00
|
|
|
|
|
|
|
#endif
|
|
|
|
|
2004-03-28 11:10:30 +02:00
|
|
|
#endif // CLASSES_FB_TLS_H
|