feat/support_fiber #6
54
tile/base/thread/thread_local.h
Normal file
54
tile/base/thread/thread_local.h
Normal file
@ -0,0 +1,54 @@
|
||||
#ifndef TILE_BASE_THREAD_THREAD_LOCAL_H
|
||||
#define TILE_BASE_THREAD_THREAD_LOCAL_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tile/base/internal/meta.h"
|
||||
#include "tile/base/thread/mutex.h"
|
||||
#include "tile/base/thread/scoped_lock.h"
|
||||
|
||||
#include <mutex>
|
||||
|
||||
namespace tile {
|
||||
template<typename T>
|
||||
class ThreadLocal {
|
||||
public:
|
||||
ThreadLocal() : ThreadLocal([]() {}) {};
|
||||
|
||||
template<typename F, enable_if_t<eggs::is_invocable_r<std::unique_ptr<T>, F>::value> * = nullptr>
|
||||
explicit ThreadLocal(F &&creator) : creator_(std::forward<F>(creator))
|
||||
{}
|
||||
|
||||
T *Get() const {}
|
||||
|
||||
T *operator->() const { return Get(); }
|
||||
|
||||
T &operator*() const { return *Get(); }
|
||||
|
||||
T *Leak() noexcept
|
||||
{
|
||||
ScopedLock _(init_lock_);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void Reset(std::unique_ptr<T> ptr = nullptr) noexcept { ScopedLock _(init_lock_); }
|
||||
|
||||
template<typename F>
|
||||
void ForEach(F &&f) const
|
||||
{
|
||||
ScopedLock _(init_lock_);
|
||||
}
|
||||
|
||||
ThreadLocal(const ThreadLocal &) = delete;
|
||||
ThreadLocal &operator=(const ThreadLocal &) = delete;
|
||||
|
||||
private:
|
||||
static thread_local T val_;
|
||||
|
||||
private:
|
||||
mutable Mutex init_lock_;
|
||||
std::function<std::unique_ptr<T>()> creator_;
|
||||
};
|
||||
}// namespace tile
|
||||
|
||||
#endif// TILE_BASE_THREAD_THREAD_LOCAL_H
|
148
tile/base/thread/thread_local/object_array.h
Normal file
148
tile/base/thread/thread_local/object_array.h
Normal file
@ -0,0 +1,148 @@
|
||||
#ifndef TILE_BASE_THREAD_THREAD_LOCAL_OBJECT_ARRAY_H
|
||||
#define TILE_BASE_THREAD_THREAD_LOCAL_OBJECT_ARRAY_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "tile/base/align.h"
|
||||
#include "tile/base/logging.h"
|
||||
#include "tile/base/thread/mutex.h"
|
||||
#include "tile/base/thread/scoped_lock.h"
|
||||
|
||||
namespace tile {
|
||||
namespace tls {
|
||||
namespace detail {
|
||||
template<typename T>
|
||||
struct Entry {
|
||||
std::aligned_storage<sizeof(T), alignof(T)> storage;
|
||||
static_assert(sizeof(T) == sizeof(storage), "");
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ObjectArrayCache {
|
||||
std::size_t limit{};
|
||||
T *objects{};
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ObjectArray;
|
||||
|
||||
template<typename T>
|
||||
class LazyInitObjectArray {
|
||||
struct EntryDeleter {
|
||||
void operator()(Entry<T> *ptr) noexcept { operator delete(ptr); }
|
||||
};
|
||||
|
||||
using AlignedArray = std::unique_ptr<Entry<T>[], EntryDeleter>;
|
||||
|
||||
public:
|
||||
LazyInitObjectArray() = default;
|
||||
|
||||
~LazyInitObjectArray()
|
||||
{
|
||||
for (int i = 0; i != initialized_.size(); ++i) {
|
||||
if (initialized_[i]) { reinterpret_cast<T *>(&objects_[i])->~T(); }
|
||||
}
|
||||
}
|
||||
|
||||
LazyInitObjectArray(LazyInitObjectArray &&) = default;
|
||||
LazyInitObjectArray &operator=(LazyInitObjectArray &&) = default;
|
||||
|
||||
template<typename F>
|
||||
void InitializeAt(std::size_t index, F &&f)
|
||||
{
|
||||
TILE_CHECK_LT(index, initialized_.size());
|
||||
TILE_CHECK(!initialized_[index]);
|
||||
|
||||
initialized_[index] = true;
|
||||
std::forward<F>(f)(&objects_[index]);
|
||||
}
|
||||
|
||||
void DestroyAt(std::size_t index)
|
||||
{
|
||||
TILE_CHECK_LT(index, initialized_.size());
|
||||
TILE_CHECK(initialized_[index]);
|
||||
|
||||
initialized_[index] = false;
|
||||
reinterpret_cast<T *>(&objects_[index])->~T();
|
||||
}
|
||||
|
||||
bool IsInitializedAt(std::size_t index) const noexcept
|
||||
{
|
||||
TILE_CHECK_LT(index, initialized_.size());
|
||||
return initialized_[index];
|
||||
}
|
||||
|
||||
T *GetAt(std::size_t index) noexcept
|
||||
{
|
||||
TILE_CHECK_LT(index, initialized_.size());
|
||||
TILE_CHECK(initialized_[index]);
|
||||
return reinterpret_cast<T *>(&objects_[index]);
|
||||
}
|
||||
|
||||
T *GetObjectsMaybeUninitialized() noexcept
|
||||
{
|
||||
static_assert(sizeof(T) == sizeof(Entry<T>), "");
|
||||
return reinterpret_cast<T *>(objects_.get());
|
||||
}
|
||||
|
||||
std::size_t size() const noexcept { return initialized_.size(); }
|
||||
|
||||
private:
|
||||
AlignedArray objects_;
|
||||
std::vector<bool> initialized_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class ObjectArrayRegistry {
|
||||
public:
|
||||
static ObjectArrayRegistry *Instance()
|
||||
{
|
||||
static NeverDestroyedSingleton<ObjectArrayRegistry> instance;
|
||||
return instance.get();
|
||||
}
|
||||
|
||||
void Register(ObjectArray<T> *array)
|
||||
{
|
||||
ScopedLock _(lock_);
|
||||
TILE_DCHECK(std::find(arrays_.begin(), arrays_.end(), array) == arrays_.end());
|
||||
arrays_.push_back(array);
|
||||
}
|
||||
|
||||
void Deregister(ObjectArray<T> *array)
|
||||
{
|
||||
ScopedLock _(lock_);
|
||||
auto iter = std::find(arrays_.begin(), arrays_.end(), array);
|
||||
TILE_CHECK(iter != arrays_.end());
|
||||
arrays_.erase(iter);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void ForEachLocked(std::size_t index, F &&f)
|
||||
{
|
||||
ScopedLock _(lock_);
|
||||
for (auto &&e : arrays_) {
|
||||
ScopedLock _(e->lock);
|
||||
if (index < e->objects.size()) { f(e); }
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Mutex lock_;
|
||||
std::vector<ObjectArray<T> *> arrays_;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct ObjectArray {
|
||||
Mutex lock;
|
||||
LazyInitObjectArray<T> objects_;
|
||||
|
||||
ObjectArray() { ObjectArrayRegistry<T>::Instance()->Register(this); }
|
||||
|
||||
~ObjectArray() { ObjectArrayRegistry<T>::Instance()->Deregister(this); }
|
||||
};
|
||||
|
||||
}// namespace detail
|
||||
}// namespace tls
|
||||
}// namespace tile
|
||||
|
||||
#endif// TILE_BASE_THREAD_THREAD_LOCAL_OBJECT_ARRAY_H
|
@ -11,27 +11,29 @@ namespace tile {
|
||||
namespace testing {
|
||||
|
||||
namespace {
|
||||
int StartBenchmark(int argc, char **argv) {
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
|
||||
return 1;
|
||||
}
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
::benchmark::Shutdown();
|
||||
return 0;
|
||||
int
|
||||
StartBenchmark(int argc, char **argv)
|
||||
{
|
||||
::benchmark::Initialize(&argc, argv);
|
||||
if (::benchmark::ReportUnrecognizedArguments(argc, argv)) { return 1; }
|
||||
::benchmark::RunSpecifiedBenchmarks();
|
||||
::benchmark::Shutdown();
|
||||
return 0;
|
||||
}
|
||||
} // namespace
|
||||
}// namespace
|
||||
|
||||
int InitAndRunAllBenchmarks(int *argc, char **argv) {
|
||||
int
|
||||
InitAndRunAllBenchmarks(int *argc, char **argv)
|
||||
{
|
||||
|
||||
if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) {
|
||||
FLAGS_logtostderr = true;
|
||||
}
|
||||
// if (gflags::GetCommandLineFlagInfoOrDie("logtostderr").is_default) {
|
||||
// FLAGS_logtostderr = true;
|
||||
// }
|
||||
|
||||
return Start(*argc, argv, StartBenchmark, true);
|
||||
return Start(*argc, argv, StartBenchmark, true);
|
||||
}
|
||||
|
||||
} // namespace testing
|
||||
} // namespace tile
|
||||
}// namespace testing
|
||||
}// namespace tile
|
||||
|
||||
TILE_BENCHMARK_MAIN
|
||||
|
31
tile/tile.h
31
tile/tile.h
@ -4,19 +4,46 @@
|
||||
#pragma once
|
||||
|
||||
// base module
|
||||
#include "tile/base/defered.h"
|
||||
#include "tile/base/align.h"
|
||||
#include "tile/base/buffer.h"
|
||||
#include "tile/base/casting.h"
|
||||
#include "tile/base/chrono.h"
|
||||
#include "tile/base/compression.h"
|
||||
#include "tile/base/data.h"
|
||||
#include "tile/base/deferred.h"
|
||||
#include "tile/base/demangle.h"
|
||||
#include "tile/base/dependency_registry.h"
|
||||
#include "tile/base/down_cast.h"
|
||||
#include "tile/base/encoding.h"
|
||||
#include "tile/base/enum.h"
|
||||
#include "tile/base/erased_ptr.h"
|
||||
#include "tile/base/exposed_var.h"
|
||||
#include "tile/base/future.h"
|
||||
#include "tile/base/handle.h"
|
||||
#include "tile/base/id_alloc.h"
|
||||
#include "tile/base/likely.h"
|
||||
#include "tile/base/logging.h"
|
||||
#include "tile/base/make_unique.h"
|
||||
#include "tile/base/maybe_owning.h"
|
||||
#include "tile/base/never_destroyed.h"
|
||||
#include "tile/base/object_pool.h"
|
||||
#include "tile/base/option.h"
|
||||
#include "tile/base/optional.h"
|
||||
#include "tile/base/random.h"
|
||||
#include "tile/base/ref_ptr.h"
|
||||
#include "tile/base/slice.h"
|
||||
#include "tile/base/status.h"
|
||||
#include "tile/base/string.h"
|
||||
#include "tile/base/type_index.h"
|
||||
#include "tile/base/variant.h"
|
||||
#include "tile/base/write_mostly.h"
|
||||
|
||||
// init module
|
||||
#include "tile/init/override_flag.h"
|
||||
|
||||
#include "sigslot/signal.h"
|
||||
|
||||
// Tile Init
|
||||
#include "tile/init.h"
|
||||
|
||||
#endif // _TILE_TILE_H
|
||||
#endif// _TILE_TILE_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user