Make ThreadLocalBuffer a class rather than a macro.

Bug: 19995392
Change-Id: I497c512648fbe66257da3fb3bcd5c9911f983705
diff --git a/libc/private/ThreadLocalBuffer.h b/libc/private/ThreadLocalBuffer.h
index cc47317..5e43665 100644
--- a/libc/private/ThreadLocalBuffer.h
+++ b/libc/private/ThreadLocalBuffer.h
@@ -32,32 +32,30 @@
 #include <malloc.h>
 #include <pthread.h>
 
-// libstdc++ currently contains __cxa_guard_acquire and __cxa_guard_release,
-// so we make do with macros instead of a C++ class.
-// TODO: move __cxa_guard_acquire and __cxa_guard_release into libc.
+// TODO: use __thread instead?
 
-// We used to use pthread_once to initialize the keys, but life is more predictable
-// if we allocate them all up front when the C library starts up, via __constructor__.
-#define BIONIC_PTHREAD_KEY_WITH_CONSTRUCTOR(key_name, key_destructor) \
-  static pthread_key_t key_name; \
-  __attribute__((constructor)) static void __bionic_tls_ ## key_name ## _key_init() { \
-    pthread_key_create(&key_name, key_destructor); \
+template <typename T, size_t Size = sizeof(T)>
+class ThreadLocalBuffer {
+ public:
+  ThreadLocalBuffer() {
+    // We used to use pthread_once to initialize the keys, but life is more predictable
+    // if we allocate them all up front when the C library starts up, via __constructor__.
+    pthread_key_create(&key_, free);
   }
 
-#define GLOBAL_INIT_THREAD_LOCAL_BUFFER(name) \
-  static void __bionic_tls_ ## name ## _key_destroy(void* buffer) { \
-    free(buffer); \
-  } \
-  BIONIC_PTHREAD_KEY_WITH_CONSTRUCTOR(__bionic_tls_ ## name ## _key, __bionic_tls_ ## name ## _key_destroy)
+  T* get() {
+    T* result = reinterpret_cast<T*>(pthread_getspecific(key_));
+    if (result == nullptr) {
+      result = reinterpret_cast<T*>(calloc(1, Size));
+      pthread_setspecific(key_, result);
+    }
+    return result;
+  }
 
-// Leaves "name_tls_buffer" and "name_tls_buffer_size" defined and initialized.
-#define LOCAL_INIT_THREAD_LOCAL_BUFFER(type, name, byte_count) \
-  type name ## _tls_buffer = \
-      reinterpret_cast<type>(pthread_getspecific(__bionic_tls_ ## name ## _key)); \
-  if (name ## _tls_buffer == NULL) { \
-    name ## _tls_buffer = reinterpret_cast<type>(calloc(1, byte_count)); \
-    pthread_setspecific(__bionic_tls_ ## name ## _key, name ## _tls_buffer); \
-  } \
-  const size_t name ## _tls_buffer_size __attribute__((unused)) = byte_count
+  size_t size() { return Size; }
+
+ private:
+  pthread_key_t key_;
+};
 
 #endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included
diff --git a/libc/private/bionic_tls.h b/libc/private/bionic_tls.h
index 1ab8d4a..414d171 100644
--- a/libc/private/bionic_tls.h
+++ b/libc/private/bionic_tls.h
@@ -72,22 +72,26 @@
 
 /*
  * Bionic uses some pthread keys internally. All pthread keys used internally
- * should be created in constructors, except for keys that may be used in or before constructors.
+ * should be created in constructors, except for keys that may be used in or
+ * before constructors.
+ *
  * We need to manually maintain the count of pthread keys used internally, but
  * pthread_test should fail if we forget.
- * Following are current pthread keys used internally by libc:
- *  basename               libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  dirname                libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
+ *
+ * These are the pthread keys currently used internally by libc:
+ *
+ *  basename               libc (ThreadLocalBuffer)
+ *  dirname                libc (ThreadLocalBuffer)
  *  uselocale              libc (can be used in constructors)
- *  getmntent_mntent       libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  getmntent_strings      libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  ptsname                libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  ttyname                libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  strerror               libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  strsignal              libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  passwd                 libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  group                  libc (GLOBAL_INIT_THREAD_LOCAL_BUFFER)
- *  _res_key               libc (BIONIC_PTHREAD_KEY_WITH_CONSTRUCTOR)
+ *  getmntent_mntent       libc (ThreadLocalBuffer)
+ *  getmntent_strings      libc (ThreadLocalBuffer)
+ *  ptsname                libc (ThreadLocalBuffer)
+ *  ttyname                libc (ThreadLocalBuffer)
+ *  strerror               libc (ThreadLocalBuffer)
+ *  strsignal              libc (ThreadLocalBuffer)
+ *  passwd                 libc (ThreadLocalBuffer)
+ *  group                  libc (ThreadLocalBuffer)
+ *  _res_key               libc (constructor in BSD code)
  */
 
 #define LIBC_PTHREAD_KEY_RESERVED_COUNT 12