<commit_before>//===--- Context.cpp -----------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include "Context.h"
#include "llvm/Config/config.h"
#include <cassert>

// The thread-local Context is scoped in a function to avoid init-order issues.
// It's created by currentContext() when first needed.

#ifdef HAVE_PTHREAD_GETSPECIFIC
// We'd love to use thread_local everywhere.
// It requires support from the runtime: __cxa_thread_atexit.
// Rather than detect this, we use the pthread API where available.
#include <pthread.h>
#include <cstring>
static clang::clangd::Context &currentContext() {
  using clang::clangd::Context;
  static pthread_key_t CtxKey;

  // Once (across threads), set up pthread TLS for Context, and its destructor.
  static int Dummy = [] { // Create key only once, for all threads.
    if (auto Err = pthread_key_create(&CtxKey, /*destructor=*/+[](void *Ctx) {
          delete reinterpret_cast<Context *>(Ctx);
        }))
      llvm_unreachable(strerror(Err));
    return 0;
  }();
  (void)Dummy;

  // Now grab the current context from TLS, and create it if it doesn't exist.
  void *Ctx = pthread_getspecific(CtxKey);
  if (!Ctx) {
    Ctx = new Context();
    if (auto Err = pthread_setspecific(CtxKey, Ctx))
      llvm_unreachable(strerror(Err));
  }
  return *reinterpret_cast<Context *>(Ctx);
}
#else
// Only supported platform without pthread is windows, and thread_local works.
static clang::clangd::Context &currentContext() {
  static thread_local auto C = clang::clangd::Context::empty();
  return C;
}
#endif

namespace clang {
namespace clangd {

Context Context::empty() { return Context(/*Data=*/nullptr); }

Context::Context(std::shared_ptr<const Data> DataPtr)
    : DataPtr(std::move(DataPtr)) {}

Context Context::clone() const { return Context(DataPtr); }

const Context &Context::current() { return currentContext(); }

Context Context::swapCurrent(Context Replacement) {
  std::swap(Replacement, currentContext());
  return Replacement;
}

} // namespace clangd
} // namespace clang<commit_msg>[clangd] Don't try pthread, just use thread_local. Reverts r323949.<commit_after>//===--- Context.cpp -----------------------------------------*- C++-*-===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include "Context.h"
#include <cassert>

namespace clang {
namespace clangd {

Context Context::empty() { return Context(/*Data=*/nullptr); }

Context::Context(std::shared_ptr<const Data> DataPtr)
    : DataPtr(std::move(DataPtr)) {}

Context Context::clone() const { return Context(DataPtr); }

static Context &currentContext() {
  static thread_local auto C = Context::empty();
  return C;
}

const Context &Context::current() { return currentContext(); }

Context Context::swapCurrent(Context Replacement) {
  std::swap(Replacement, currentContext());
  return Replacement;
}

} // namespace clangd
} // namespace clang
{'fraction_non_alphanumeric': 0.19874476987447698, 'fraction_numerical': 0.0020920502092050207, 'mean_word_length': 2.96094674556213, 'pattern_counts': {'":': 0, '<': 11, '<?xml version=': 0, '>': 11, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2083947', 'n_tokens_mistral': 958, 'n_tokens_neox': 950, 'n_words': 284}