ipc/chromium/src/base/thread_local.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/ipc/chromium/src/base/thread_local.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,121 @@
     1.4 +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
     1.5 +// Use of this source code is governed by a BSD-style license that can be
     1.6 +// found in the LICENSE file.
     1.7 +
     1.8 +// WARNING: Thread local storage is a bit tricky to get right.  Please make
     1.9 +// sure that this is really the proper solution for what you're trying to
    1.10 +// achieve.  Don't prematurely optimize, most likely you can just use a Lock.
    1.11 +//
    1.12 +// These classes implement a warpper around the platform's TLS storage
    1.13 +// mechanism.  On construction, they will allocate a TLS slot, and free the
    1.14 +// TLS slot on destruction.  No memory management (creation or destruction) is
    1.15 +// handled.  This means for uses of ThreadLocalPointer, you must correctly
    1.16 +// manage the memory yourself, these classes will not destroy the pointer for
    1.17 +// you.  There are no at-thread-exit actions taken by these classes.
    1.18 +//
    1.19 +// ThreadLocalPointer<Type> wraps a Type*.  It performs no creation or
    1.20 +// destruction, so memory management must be handled elsewhere.  The first call
    1.21 +// to Get() on a thread will return NULL.  You can update the pointer with a
    1.22 +// call to Set().
    1.23 +//
    1.24 +// ThreadLocalBoolean wraps a bool.  It will default to false if it has never
    1.25 +// been set otherwise with Set().
    1.26 +//
    1.27 +// Thread Safety:  An instance of ThreadLocalStorage is completely thread safe
    1.28 +// once it has been created.  If you want to dynamically create an instance,
    1.29 +// you must of course properly deal with safety and race conditions.  This
    1.30 +// means a function-level static initializer is generally inappropiate.
    1.31 +//
    1.32 +// Example usage:
    1.33 +//   // My class is logically attached to a single thread.  We cache a pointer
    1.34 +//   // on the thread it was created on, so we can implement current().
    1.35 +//   MyClass::MyClass() {
    1.36 +//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() == NULL);
    1.37 +//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(this);
    1.38 +//   }
    1.39 +//
    1.40 +//   MyClass::~MyClass() {
    1.41 +//     DCHECK(Singleton<ThreadLocalPointer<MyClass> >::get()->Get() != NULL);
    1.42 +//     Singleton<ThreadLocalPointer<MyClass> >::get()->Set(NULL);
    1.43 +//   }
    1.44 +//
    1.45 +//   // Return the current MyClass associated with the calling thread, can be
    1.46 +//   // NULL if there isn't a MyClass associated.
    1.47 +//   MyClass* MyClass::current() {
    1.48 +//     return Singleton<ThreadLocalPointer<MyClass> >::get()->Get();
    1.49 +//   }
    1.50 +
    1.51 +#ifndef BASE_THREAD_LOCAL_H_
    1.52 +#define BASE_THREAD_LOCAL_H_
    1.53 +
    1.54 +#include "base/basictypes.h"
    1.55 +
    1.56 +#if defined(OS_POSIX)
    1.57 +#include <pthread.h>
    1.58 +#endif
    1.59 +
    1.60 +namespace base {
    1.61 +
    1.62 +// Helper functions that abstract the cross-platform APIs.  Do not use directly.
    1.63 +struct ThreadLocalPlatform {
    1.64 +#if defined(OS_WIN)
    1.65 +  typedef int SlotType;
    1.66 +#elif defined(OS_POSIX)
    1.67 +  typedef pthread_key_t SlotType;
    1.68 +#endif
    1.69 +
    1.70 +  static void AllocateSlot(SlotType& slot);
    1.71 +  static void FreeSlot(SlotType& slot);
    1.72 +  static void* GetValueFromSlot(SlotType& slot);
    1.73 +  static void SetValueInSlot(SlotType& slot, void* value);
    1.74 +};
    1.75 +
    1.76 +template <typename Type>
    1.77 +class ThreadLocalPointer {
    1.78 + public:
    1.79 +  ThreadLocalPointer() : slot_() {
    1.80 +    ThreadLocalPlatform::AllocateSlot(slot_);
    1.81 +  }
    1.82 +
    1.83 +  ~ThreadLocalPointer() {
    1.84 +    ThreadLocalPlatform::FreeSlot(slot_);
    1.85 +  }
    1.86 +
    1.87 +  Type* Get() {
    1.88 +    return static_cast<Type*>(ThreadLocalPlatform::GetValueFromSlot(slot_));
    1.89 +  }
    1.90 +
    1.91 +  void Set(Type* ptr) {
    1.92 +    ThreadLocalPlatform::SetValueInSlot(slot_, ptr);
    1.93 +  }
    1.94 +
    1.95 + private:
    1.96 +  typedef ThreadLocalPlatform::SlotType SlotType;
    1.97 +
    1.98 +  SlotType slot_;
    1.99 +
   1.100 +  DISALLOW_COPY_AND_ASSIGN(ThreadLocalPointer<Type>);
   1.101 +};
   1.102 +
   1.103 +class ThreadLocalBoolean {
   1.104 + public:
   1.105 +  ThreadLocalBoolean() { }
   1.106 +  ~ThreadLocalBoolean() { }
   1.107 +
   1.108 +  bool Get() {
   1.109 +    return tlp_.Get() != NULL;
   1.110 +  }
   1.111 +
   1.112 +  void Set(bool val) {
   1.113 +    tlp_.Set(reinterpret_cast<void*>(val ? 1 : 0));
   1.114 +  }
   1.115 +
   1.116 + private:
   1.117 +  ThreadLocalPointer<void> tlp_;
   1.118 +
   1.119 +  DISALLOW_COPY_AND_ASSIGN(ThreadLocalBoolean);
   1.120 +};
   1.121 +
   1.122 +}  // namespace base
   1.123 +
   1.124 +#endif  // BASE_THREAD_LOCAL_H_

mercurial