# Improved thread local storage for angelscript

This topic is 4038 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

## Recommended Posts

Just a suggestion leading on from the discussion here. Use the OS's thread local functionality, mostly it's no critical sections or mutexes required. They are also fairly easy to wrap, here is my own code for it, feel free to incorporate this into angelscript. Autocleanup of the TLS data on windows does require a dll, I simply split thread local storage into it's own lib on windows for that reason. This code makes the assumption that thread local keys are created in the main thread. It comes from my sourceforge project http://ldk.sourceforge.net/ and is zlib licensed, and there's other stuff in there that may well be useful for angelscript because I designed this library to become the base of a hard realtime scripting language.
//ThreadLocalStorage.h
extern "C"
{
//////////////////////////////////////////////////////////////////////////////////////
/// @{
///
/// Programs often need global or static variables that have different values in
/// different threads. Since threads share one memory space, this cannot be achieved
/// with regular variables. Thread local storage is the answer to this need.
///
/// Each thread possesses a private memory block, the thread-local data area (TLD).
/// This area is indexed by TLS keys. The TLD area associates values of type void *
/// to TLS keys. TLS keys are common to all threads, but the value associated with
/// a given TLS key can be different in each thread.
///
/// For concreteness, the TLS areas can be viewed as arrays of void * pointers, TLS
/// keys as integer indices into these arrays, and the value of a TLS key as the value
/// of the corresponding array element in the calling thread.
///
/// When a thread is created, its TLS area initially associates NULL with all keys.
/// This behavior is undocumented on MS Windows.
///
//////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////
/// \brief A pointer to a function used to free a piece of thread local storage.
///////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////
/// \typedef size_t TLSKey
/// \brief A key used to access thread local storage.
//////////////////////////////////////////////////////////////////////////////////////
typedef size_t TLSKey;

//////////////////////////////////////////////////////////////////////////////////////
/// \brief Create a key for thread local storage.
/// \param dtor A pointer to a function to free a piece of thread local storage.
/// \return A unique key to be used with \em threadLocalSet() and
//////////////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////////////
/// \fn void threadLocalSet(TLSKey key, void* object)
/// \brief Associate an object with a key for the current thread.
/// \param key The unique identifier associated with an object in the current thread.
/// \param object The object to associate with \em key in the current thread.
//////////////////////////////////////////////////////////////////////////////////////
LDK_TLS_API void threadLocalSet(TLSKey key, void* object);

//////////////////////////////////////////////////////////////////////////////////////
/// \brief Get the object associated with \em key for the current thread.
/// \param key The unique identifier associated with an object in the current thread.
/// \return NULL if there is nothing associated with a key in the current thread,
/// otherwise the associated object.
/////////////////////////////////////////////////////////////////////////////////////

/// @}

#include <assert.h>
#ifdef unix

{
}

{
TLSKey key = 0;
assert(!test);
return key;
}

{
assert(!test);
}
#elif defined _WINDOWS

#include <windows.h>
#include <map>

#ifdef _MSC_VER
#pragma warning (disable : 4267)
#endif

namespace
{
TLSMap gTLSCleanup;
}

{
return TlsGetValue(key);
}

{
TLSKey key = TlsAlloc();
assert(key != TLS_OUT_OF_INDEXES);
gTLSCleanup[key] = dtor;
return key;
}

{
int test = TlsSetValue(key, data);
assert(test);
}

{
TLSMap::iterator i = gTLSCleanup.begin();
while(i != gTLSCleanup.end())
{
if(data && (*i).second)
(*i).second(data);
i++;
}
}

bool __stdcall DllMain(HINSTANCE hndl, DWORD reason, LPVOID reserved)
{
switch(reason)
{
case DLL_PROCESS_ATTACH:
//do nothing
break;
//do nothing
break;
break;
case DLL_PROCESS_DETACH:
//do nothing?
break;
}
return true;
}
#ifdef _MSC_VER
#pragma warning (default : 4267)
#endif

#endif //unix


[Edited by - penguinpusher on June 13, 2007 5:50:54 AM]

##### Share on other sites
Thanks, this looks interesting indeed. I'll see how I can adapt it to AngelScript. Though it seems the critical sections really aren't the bottle-neck for multithreaded applications.

And also, this only solves the thread local storage, critical sections will still be necessary for protected reference counters and so on.

Regards,
Andreas

##### Share on other sites
Yep, I read that, but getting rid of crit sections won't do any harm at all :)

It's quite possible to do lockless smartpointers using atomic primitives, but it's no fun trying to make it portable, particularly across CPUs. It's quite easy if one sticks to using GCC though, it has atomic intrinsics.

here are the docs

[Edited by - penguinpusher on June 13, 2007 7:23:38 AM]

##### Share on other sites
Regarding atomic operations:

Windows:
InterlockedIncrement/InterlockedDecrement (http://msdn2.microsoft.com/en-us/library/ms683614.aspx)

Linux:
atomic_inc/atomic_dec (http://docs.sun.com/app/docs/doc/816-5168/6mbb3hr3n?a=view)

You should use these functions for reference counting.

##### Share on other sites
I wish it were so simple :) That manpage you linked to is for Solaris rather than Linux, atomic stuff is one of those things that isn't standardised across unicies (hence the coolness of the gcc intrinsics). Linux has a bunch of different stuff with similar functionality, it's still in atomic.h, but it's not part of the c library. There is a separate atomic.h file full of inline asm for each architecture in the kernel headers, mine is at /usr/src/linux-headers-2.6.20-15/include/asm-i386/atomic.h

The functions aren't documented in any manpages I know of, and the atomic.h headers aren't needed for glibc. You have to have the full kernel headers packages installed to get them.

##### Share on other sites
For atomic operations, the libatomic_ops library from HP is interesting.

It contains implementations for a lot of platforms, including linux and windows. It's licensed under a MIT-style license.

##### Share on other sites
Wow, thanks Gyrbo. Off to work to make my own SmartPointer classes lock free!

WitchLord I will have a go at hacking AngelScript handles to be lock free using this library once I've re done (been planning a re-write anyway) and tested my own SmartPointers and will post code if successful. Or if you'd prefer I'll do an svn patch. However I don't have a multiprocessor machine to test on atm.

If you haven't adapted the thread local storage code for AS I'll do it too, I was under the impression that AS used no mutexes/critical sections by means of using different interpreters in different threads and keeping instances of objects isolated between threads. I need a harder realtime scripting language than what AS currently is for low latency audio (~ 1 millisecond buffer sizes).

##### Share on other sites
Quote:
 Original post by penguinpusherI need a harder realtime scripting language than what AS currently is for low latency audio (~ 1 millisecond buffer sizes).

penguinpusher... i need that too!
i've done some tests some months ago, and while AS perform very fast, sometimes it is just too slow for that purpose.

anyway, when u got something usable for realtime audio manipulation you can post a shout here

:)

##### Share on other sites
When you do your modifications of AngelScript, keep in mind that the code cannot have any dependencies on external libraries. If you send me code I prefer that you send me a zip of your changed files, rather than a SVN patch. I'll use WinMerge to merge the code with the library and check in the code.

The only critical sections you'll have problem with in multithreaded applications are the ones already mentioned (i.e. the thread local storage for storing the currently active context, and the reference counters on the engine). You yourself have suggested the improvements on those so once that's implemented there should be no more critical sections, right?

Multithreaded programming and hard realtime applications are not my strong side, so feel free to make more suggestions. I'll try to adopt as much as possible that doesn't interfere with my goals for the library.

Regards,
Andreas

1. 1
2. 2
Rutin
23
3. 3
JoeJ
20
4. 4
5. 5

• 22
• 40
• 23
• 13
• 13
• ### Forum Statistics

• Total Topics
631732
• Total Posts
3001926
×