digitalmars.D - Request: 'local' keyword for TLS support
- Sean Kelly (55/55) Jan 03 2006 I've found thread local storage to be nearly indispensable at times, and...
- Kris (11/66) Jan 03 2006 I don't wish to confuse the waters, but isn't it far simpler to just ext...
- Sean Kelly (13/24) Jan 03 2006 Typically, yes. Though there are times when I think it's nice to have
- Kris (2/8) Jan 03 2006 I now see what you're getting at. Thanks!
I've found thread local storage to be nearly indispensable at times, and it seems awkward to do this via library routines in D, as the library calls are relatively slow and make this seem like a feature that has been tacked onto a language that was not designed to support multithreading. I would like to propose a new keyword, 'local', that may be used as a modifier for static variables which indicates that the variable should have per-thread storage. For reference, the Sun and Microsoft compilers currently have this feature via the __thread and __declspec keywords, and relevant documentation can be found on each. The salient portion of the MS docs is as follows: You must observe these guidelines when declaring thread local objects and variables: * You can apply the thread attribute only to data declarations and definitions, and classes that do not have member functions; thread cannot be used on function declarations or definitions. * The use of the thread attribute may interfere with delay loading of DLL imports. * You can specify the thread attribute only on data items with static storage duration. This includes global data objects (both static and extern), local static objects, and static data members of classes. You cannot declare automatic data objects with the thread attribute. * You must use the thread attribute for the declaration and the definition of a thread local object, whether the declaration and definition occur in the same file or separate files. * You cannot use the thread attribute as a type modifier. * Only POD classes may be instantiated using __declspec(thread). The thread attribute is ignored if no object is declared as part of the class declaration. Assuming the compiler doesn't take over control of thread initialization, perhaps it would be sufficient to place this restriction upon the thread entry point in library code: the first line of this routine should be a fixed-size void array with a size parameter of RESERVED_LOCAL_SIZE. For instance: void entryPoint(void* p) { void[RESERVED_LOCAL_SIZE] tls_data; ... } An alternative would be for the compiler supply an entry point that accepts a delegate parameter. Thus: // internal (in runtime code) extern (C) void compilerSuppliedEntryPoint(void* p) { // do whatever needs to be done (cast(void delegate()) p)(); } // in standard library extern (C) void compilerSuppliedEntryPoint(void*); class Thread { void start() { // call compiler routine with run method as parameter beginthread( &compilerSuppliedEntryPoint, 0, &run ); } private void run() { // user thread entry point } }
Jan 03 2006
"Sean Kelly" <sean f4.ca> wrote ...I've found thread local storage to be nearly indispensable at times, and it seems awkward to do this via library routines in D, as the library calls are relatively slow and make this seem like a feature that has been tacked onto a language that was not designed to support multithreading. I would like to propose a new keyword, 'local', that may be used as a modifier for static variables which indicates that the variable should have per-thread storage. For reference, the Sun and Microsoft compilers currently have this feature via the __thread and __declspec keywords, and relevant documentation can be found on each. The salient portion of the MS docs is as follows: You must observe these guidelines when declaring thread local objects and variables: * You can apply the thread attribute only to data declarations and definitions, and classes that do not have member functions; thread cannot be used on function declarations or definitions. * The use of the thread attribute may interfere with delay loading of DLL imports. * You can specify the thread attribute only on data items with static storage duration. This includes global data objects (both static and extern), local static objects, and static data members of classes. You cannot declare automatic data objects with the thread attribute. * You must use the thread attribute for the declaration and the definition of a thread local object, whether the declaration and definition occur in the same file or separate files. * You cannot use the thread attribute as a type modifier. * Only POD classes may be instantiated using __declspec(thread). The thread attribute is ignored if no object is declared as part of the class declaration. Assuming the compiler doesn't take over control of thread initialization, perhaps it would be sufficient to place this restriction upon the thread entry point in library code: the first line of this routine should be a fixed-size void array with a size parameter of RESERVED_LOCAL_SIZE. For instance: void entryPoint(void* p) { void[RESERVED_LOCAL_SIZE] tls_data; ... } An alternative would be for the compiler supply an entry point that accepts a delegate parameter. Thus: // internal (in runtime code) extern (C) void compilerSuppliedEntryPoint(void* p) { // do whatever needs to be done (cast(void delegate()) p)(); } // in standard library extern (C) void compilerSuppliedEntryPoint(void*); class Thread { void start() { // call compiler routine with run method as parameter beginthread( &compilerSuppliedEntryPoint, 0, &run ); } private void run() { // user thread entry point } }I don't wish to confuse the waters, but isn't it far simpler to just extend the Thread class for such things? I use thread-locals a /lot/, and find the strategy of subclassing Thread to add thread-specific attributes to be perfectly suited. It does not require further support from the compiler, and is perfectly type-safe (no need to go cast()ing anywhere). True, one cannot subclass the initial 'main' thread, but I don't see that as much of an impediment? Does the subclassing strategy not satisfy the need, or not do so in a manner that's both convenient and non-fugly? - Kris
Jan 03 2006
Kris wrote:I don't wish to confuse the waters, but isn't it far simpler to just extend the Thread class for such things?Typically, yes. Though there are times when I think it's nice to have non-OO code that can manipulate thread local data, and I'd prefer to avoid library calls if possible. But I grant that this may not be sufficient reason to argue for a language addition.I use thread-locals a /lot/, and find the strategy of subclassing Thread to add thread-specific attributes to be perfectly suited. It does not require further support from the compiler, and is perfectly type-safe (no need to go cast()ing anywhere). True, one cannot subclass the initial 'main' thread, but I don't see that as much of an impediment?It really isn't. There are a few cases where the inheritance method simply doesn't serve--typically when the main thread needs to access the data--but this perhaps isn't a huge issue.Does the subclassing strategy not satisfy the need, or not do so in a manner that's both convenient and non-fugly?I suppose my motivation for this is perhaps drawn from a desire to offer equivalent support for both OO and non-OO programming in D--this is largely why I added the TLS library calls in Ares as well. But whether such a desire warrants language support is questionable. Sean
Jan 03 2006
"Sean Kelly" <sean f4.ca> wrote ..Kris wrote:I now see what you're getting at. Thanks!Does the subclassing strategy not satisfy the need, or not do so in a manner that's both convenient and non-fugly?I suppose my motivation for this is perhaps drawn from a desire to offer equivalent support for both OO and non-OO programming in D--this is largely why I added the TLS library calls in Ares as well.
Jan 03 2006