-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
322 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// | ||
// Created by Levalup. | ||
// L.eval: Let programmer get rid of only work jobs. | ||
// | ||
|
||
#include <iostream> | ||
#include <cassert> | ||
|
||
#include "uvcxx/thread.h" | ||
#include "uvcxx/key.h" | ||
#include "uvcxx/utility.h" | ||
|
||
int main() { | ||
// create thread local storage key | ||
// key_t is not copyable | ||
uv::key_t tls; | ||
|
||
uv::thread_t t1([&]() { | ||
auto v = new int(1); | ||
|
||
tls.set(v); | ||
|
||
uv::sleep(1000); // wait thread-2 set value | ||
std::cout << "Thread-1 got " << tls.ref<int>() << std::endl; | ||
|
||
assert(tls.ref<int>() == 1); | ||
|
||
delete v; | ||
}); | ||
uv::thread_t t2([&]() { | ||
auto v = new int(2); | ||
|
||
uv::sleep(500); // wait thread-1 set value | ||
tls.set(v); | ||
|
||
uv::sleep(1000); // wait thread-1 get value | ||
std::cout << "Thread-2 got " << tls.ref<int>() << std::endl; | ||
|
||
assert(tls.ref<int>() == 2); | ||
|
||
delete v; | ||
}); | ||
|
||
t1.join(); | ||
t2.join(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// | ||
// Created by Levalup. | ||
// L.eval: Let programmer get rid of only work jobs. | ||
// | ||
|
||
#include <iostream> | ||
|
||
#include "uvcxx/thread.h" | ||
|
||
int main() { | ||
// create thread with work callback function | ||
uv::thread_t t([&]() { | ||
for (int i = 0; i < 10; ++i) { | ||
std::cout << i << " "; | ||
} | ||
std::cout << std::endl; | ||
}); | ||
|
||
// Explicit call to `join`. | ||
// It will be implicitly called during the destruction. | ||
t.join(); | ||
// Repeated calls are also acceptable. | ||
t.join(); | ||
|
||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
// | ||
// Created by Levalup. | ||
// L.eval: Let programmer get rid of only work jobs. | ||
// | ||
|
||
#ifndef LIBUVCXX_KEY_H | ||
#define LIBUVCXX_KEY_H | ||
|
||
#include <uv.h> | ||
|
||
#include "cxx/except.h" | ||
#include "inner/base.h" | ||
|
||
namespace uv { | ||
class key_t : public uvcxx::extend_raw_base_t<uv_key_t> { | ||
public: | ||
using self = key_t; | ||
using supper = uvcxx::extend_raw_base_t<uv_key_t>; | ||
|
||
key_t(const key_t &) = delete; | ||
|
||
key_t &operator=(const key_t &) = delete; | ||
|
||
key_t(key_t &&that) noexcept = default; | ||
|
||
key_t &operator=(key_t &&that) noexcept = default; | ||
|
||
key_t() { | ||
auto err = uv_key_create(*this); | ||
if (err < 0) throw uvcxx::errcode(err, "can not create key"); | ||
} | ||
|
||
~key_t() { | ||
uv_key_delete(*this); | ||
} | ||
|
||
void set(void *value) { | ||
uv_key_set(*this, value); | ||
} | ||
|
||
[[nodiscard]] | ||
void *get() const { | ||
return uv_key_get(*this); | ||
} | ||
|
||
template<typename T> | ||
[[nodiscard]] | ||
T *get() const { | ||
return (T *) uv_key_get(*this); | ||
} | ||
|
||
template<typename T> | ||
[[nodiscard]] | ||
T &ref() const { | ||
return *((T *) uv_key_get(*this)); | ||
} | ||
}; | ||
} | ||
|
||
#endif //LIBUVCXX_KEY_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,174 @@ | ||
// | ||
// Created by Levalup. | ||
// L.eval: Let programmer get rid of only work jobs. | ||
// | ||
|
||
#ifndef LIBUVCXX_THREAD_H | ||
#define LIBUVCXX_THREAD_H | ||
|
||
#include <functional> | ||
|
||
#include "uv.h" | ||
|
||
#include "uvcxx/cxx/except.h" | ||
#include "uvcxx/cxx/version.h" | ||
#include "uvcxx/inner/base.h" | ||
|
||
namespace uv { | ||
namespace inner { | ||
class thread_t { | ||
public: | ||
using self = thread_t; | ||
using raw_t = uv_thread_t; | ||
|
||
using entry_t = std::function<void(void)>; | ||
|
||
raw_t tid{}; | ||
std::atomic<bool> m_joined{false}; | ||
|
||
thread_t(const thread_t &) = delete; | ||
|
||
thread_t &operator=(const thread_t &) = delete; | ||
|
||
explicit thread_t(entry_t entry) | ||
: m_entry(std::move(entry)) { | ||
auto err = uv_thread_create(&tid, raw_entry, this); | ||
if (err < 0) throw uvcxx::errcode(err); | ||
} | ||
|
||
#if UVCXX_SATISFY_VERSION(1, 26, 0) | ||
|
||
explicit thread_t(entry_t entry, const uv_thread_options_t *params) | ||
: m_entry(std::move(entry)) { | ||
auto err = uv_thread_create_ex(&tid, params, raw_entry, this); | ||
if (err < 0) throw uvcxx::errcode(err); | ||
} | ||
|
||
#endif | ||
|
||
int join() { | ||
bool joined = false; | ||
if (!m_joined.compare_exchange_strong(joined, true)) { return 0; } | ||
|
||
auto err = uv_thread_join(&tid); | ||
if (err < 0) UVCXX_THROW_OR_RETURN(err, err); | ||
return err; | ||
} | ||
|
||
|
||
private: | ||
entry_t m_entry; | ||
|
||
static void raw_entry(void *arg) { | ||
try { | ||
((self *) arg)->m_entry(); | ||
} catch (...) { | ||
} | ||
} | ||
}; | ||
} | ||
|
||
class thread_t final : public uvcxx::base_t { | ||
public: | ||
using self = thread_t; | ||
using raw_t = uv_thread_t; | ||
|
||
using inner_t = inner::thread_t; | ||
using entery_t = inner_t::entry_t; | ||
|
||
thread_t(const thread_t &) = delete; | ||
|
||
thread_t &operator=(const thread_t &) = delete; | ||
|
||
thread_t(thread_t &&that) noexcept = default; | ||
|
||
thread_t &operator=(thread_t &&that) noexcept = default; | ||
|
||
thread_t(std::nullptr_t) {} | ||
|
||
explicit thread_t(entery_t entry) | ||
: m_thread(new inner_t(std::move(entry))) {} | ||
|
||
#if UVCXX_SATISFY_VERSION(1, 26, 0) | ||
|
||
explicit thread_t(entery_t entry, const uv_thread_options_t *params) | ||
: m_thread(new inner_t(std::move(entry), params)) {} | ||
|
||
#endif | ||
|
||
~thread_t() { | ||
join(); | ||
delete m_thread; | ||
} | ||
|
||
int join() { | ||
if (m_thread) return m_thread->join(); | ||
return 0; | ||
} | ||
|
||
#if UVCXX_SATISFY_VERSION(1, 45, 0) | ||
|
||
int setaffinity(char *cpumask, char *oldmask, size_t mask_size) { | ||
return uv_thread_setaffinity(*this, cpumask, oldmask, mask_size); | ||
} | ||
|
||
int getaffinity(char *cpumask, size_t mask_size) const { | ||
return uv_thread_getaffinity(*this, cpumask, mask_size); | ||
} | ||
|
||
#endif | ||
|
||
[[nodiscard]] | ||
bool equal(const self &other) const { | ||
return uv_thread_equal(*this, other); | ||
} | ||
|
||
int setpriority(int priority) { | ||
auto err = uv_thread_setpriority(m_thread->tid, priority); | ||
if (err < 0) UVCXX_THROW_OR_RETURN(err, err); | ||
return err; | ||
} | ||
|
||
int getpriority(int *priority) const { | ||
auto err = uv_thread_getpriority(m_thread->tid, priority); | ||
if (err < 0) UVCXX_THROW_OR_RETURN(err, err); | ||
return err; | ||
} | ||
|
||
[[nodiscard]] | ||
int getpriority() const { | ||
int priority = 0; | ||
auto err = uv_thread_getpriority(m_thread->tid, &priority); | ||
if (err < 0) UVCXX_THROW_OR_RETURN(err, 0); | ||
return priority; | ||
} | ||
|
||
bool operator==(const self &other) const { | ||
return equal(other); | ||
} | ||
|
||
bool operator!=(const self &other) const { | ||
return !equal(other); | ||
} | ||
|
||
public: | ||
explicit operator bool() const { return m_thread; } | ||
|
||
operator raw_t *() { return &m_thread->tid; } | ||
|
||
operator raw_t *() const { return &m_thread->tid; } | ||
|
||
private: | ||
inner::thread_t *m_thread = nullptr; | ||
}; | ||
|
||
namespace thread { | ||
#if UVCXX_SATISFY_VERSION(1, 45, 0) | ||
|
||
inline int getcpu() { return uv_thread_getcpu(); } | ||
|
||
#endif | ||
} | ||
} | ||
|
||
#endif //LIBUVCXX_THREAD_H |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters