1b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea/*
2b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * Copyright (C) 2012 The Android Open Source Project
3b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * All rights reserved.
4b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *
5b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * Redistribution and use in source and binary forms, with or without
6b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * modification, are permitted provided that the following conditions
7b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * are met:
8b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *  * Redistributions of source code must retain the above copyright
9b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *    notice, this list of conditions and the following disclaimer.
10b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *  * Redistributions in binary form must reproduce the above copyright
11b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *    notice, this list of conditions and the following disclaimer in
12b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *    the documentation and/or other materials provided with the
13b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *    distribution.
14b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea *
15b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
16b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
18b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
19b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
20b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
21b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
22b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
23b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
24b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea * SUCH DAMAGE.
27b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea */
28b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea
29b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#ifndef _BIONIC_THREAD_LOCAL_BUFFER_H_included
30b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#define _BIONIC_THREAD_LOCAL_BUFFER_H_included
31b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea
32b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <malloc.h>
33b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#include <pthread.h>
34b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea
356170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes// TODO: use __thread instead?
366170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes
376170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughestemplate <typename T, size_t Size = sizeof(T)>
386170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughesclass ThreadLocalBuffer {
396170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes public:
406170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes  ThreadLocalBuffer() {
416170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    // We used to use pthread_once to initialize the keys, but life is more predictable
426170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    // if we allocate them all up front when the C library starts up, via __constructor__.
436170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    pthread_key_create(&key_, free);
446170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes  }
456170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes
466170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes  T* get() {
476170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    T* result = reinterpret_cast<T*>(pthread_getspecific(key_));
486170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    if (result == nullptr) {
496170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes      result = reinterpret_cast<T*>(calloc(1, Size));
506170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes      pthread_setspecific(key_, result);
516170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    }
526170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes    return result;
534a2891d8c8f09a64ea9e1479518b0cc969bd5969Yabin Cui  }
543e898476c7230b60a0f76968e64ff25f475b48c0Elliott Hughes
556170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes  size_t size() { return Size; }
566170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes
576170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes private:
586170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes  pthread_key_t key_;
596170693e28dd72a1517c267f3f62b3f37477b8bbElliott Hughes};
60b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea
61b5f053b5a7deb084e7a052d527e0aa41339ae05cIrina Tirdea#endif // _BIONIC_THREAD_LOCAL_BUFFER_H_included
62