22#if defined(__cplusplus) && __cplusplus >= 201703L
24# include <type_traits>
31#define ZTH_STRINGIFY_(x) #x
35#define ZTH_STRINGIFY(x) ZTH_STRINGIFY_(x)
45# define likely(expr) \
46 __builtin_expect(!!(expr) , 1)
48# define likely(expr) (expr)
60# define unlikely(expr) \
61 __builtin_expect(!!(expr) , 0)
63# define unlikely(expr) (expr)
70#define ZTH_GET_MACRO_ARGN( \
71 _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, NAME, ...) \
75# define FOREACH_0(WHAT)
76# define FOREACH_1(WHAT, X) WHAT(X)
77# define FOREACH_2(WHAT, X, ...) \
78 WHAT(X) FOREACH_1(WHAT, __VA_ARGS__)
79# define FOREACH_3(WHAT, X, ...) \
80 WHAT(X) FOREACH_2(WHAT, __VA_ARGS__)
81# define FOREACH_4(WHAT, X, ...) \
82 WHAT(X) FOREACH_3(WHAT, __VA_ARGS__)
83# define FOREACH_5(WHAT, X, ...) \
84 WHAT(X) FOREACH_4(WHAT, __VA_ARGS__)
85# define FOREACH_6(WHAT, X, ...) \
86 WHAT(X) FOREACH_5(WHAT, __VA_ARGS__)
87# define FOREACH_7(WHAT, X, ...) \
88 WHAT(X) FOREACH_6(WHAT, __VA_ARGS__)
89# define FOREACH_8(WHAT, X, ...) \
90 WHAT(X) FOREACH_7(WHAT, __VA_ARGS__)
91# define FOREACH_9(WHAT, X, ...) \
92 WHAT(X) FOREACH_8(WHAT, __VA_ARGS__)
93# define FOREACH_10(WHAT, X, ...) \
94 WHAT(X) FOREACH_9(WHAT, __VA_ARGS__)
95# define FOREACH_11(WHAT, X, ...) \
96 WHAT(X) FOREACH_10(WHAT, __VA_ARGS__)
97# define FOREACH_12(WHAT, X, ...) \
98 WHAT(X) FOREACH_11(WHAT, __VA_ARGS__)
99# define FOREACH_13(WHAT, X, ...) \
100 WHAT(X) FOREACH_12(WHAT, __VA_ARGS__)
101# define FOREACH_14(WHAT, X, ...) \
102 WHAT(X) FOREACH_13(WHAT, __VA_ARGS__)
103# define FOREACH_15(WHAT, X, ...) \
104 WHAT(X) FOREACH_14(WHAT, __VA_ARGS__)
105# define FOREACH_16(WHAT, X, ...) \
106 WHAT(X) FOREACH_15(WHAT, __VA_ARGS__)
112# define FOREACH(action, ...) \
113 ZTH_GET_MACRO_ARGN( \
114 0, ##__VA_ARGS__, FOREACH_16, FOREACH_15, FOREACH_14, FOREACH_13, FOREACH_12, \
115 FOREACH_11, FOREACH_10, FOREACH_9, FOREACH_8, FOREACH_7, FOREACH_6, FOREACH_5, \
116 FOREACH_4, FOREACH_3, FOREACH_2, FOREACH_1, FOREACH_0) \
117 (action, ##__VA_ARGS__)
122# define REVERSE_1(a) a
123# define REVERSE_2(a, ...) REVERSE_1(__VA_ARGS__), a
124# define REVERSE_3(a, ...) REVERSE_2(__VA_ARGS__), a
125# define REVERSE_4(a, ...) REVERSE_3(__VA_ARGS__), a
126# define REVERSE_5(a, ...) REVERSE_4(__VA_ARGS__), a
127# define REVERSE_6(a, ...) REVERSE_5(__VA_ARGS__), a
128# define REVERSE_7(a, ...) REVERSE_6(__VA_ARGS__), a
129# define REVERSE_8(a, ...) REVERSE_7(__VA_ARGS__), a
130# define REVERSE_9(a, ...) REVERSE_8(__VA_ARGS__), a
131# define REVERSE_10(a, ...) REVERSE_9(__VA_ARGS__), a
132# define REVERSE_11(a, ...) REVERSE_10(__VA_ARGS__), a
133# define REVERSE_12(a, ...) REVERSE_11(__VA_ARGS__), a
134# define REVERSE_13(a, ...) REVERSE_12(__VA_ARGS__), a
135# define REVERSE_14(a, ...) REVERSE_13(__VA_ARGS__), a
136# define REVERSE_15(a, ...) REVERSE_14(__VA_ARGS__), a
137# define REVERSE_16(a, ...) REVERSE_15(__VA_ARGS__), a
138# define REVERSE(...) \
139 ZTH_GET_MACRO_ARGN( \
140 0, ##__VA_ARGS__, REVERSE_16, REVERSE_15, REVERSE_14, REVERSE_13, REVERSE_12, \
141 REVERSE_11, REVERSE_10, REVERSE_9, REVERSE_8, REVERSE_7, REVERSE_6, REVERSE_5, \
142 REVERSE_4, REVERSE_3, REVERSE_2, REVERSE_1, REVERSE_0) \
157# if __cplusplus >= 201103L
160# include <inttypes.h>
163# ifdef ZTH_HAVE_PTHREAD
167# ifdef ZTH_OS_WINDOWS
170# include <sys/types.h>
175zth_logv(
char const* fmt, va_list arg);
182# define ZTH_DBG_PREFIX " > "
194# define zth_dbg(group, fmt, a...) \
196 if(::zth::Config::SupportDebugPrint && ::zth::Config::Print_##group > 0 \
197 && zth_config(EnableDebugPrint)) { \
198 if(::zth::Config::EnableColorLog) \
200 ::zth::Config::Print_##group, \
201 ZTH_DBG_PREFIX "zth::" ZTH_STRINGIFY(group) ": " fmt \
206 ZTH_DBG_PREFIX "zth::" ZTH_STRINGIFY(group) ": " fmt \
217# define zth_assert(expr) \
219 if(unlikely(::zth::Config::EnableAssert && !(expr))) \
220 ::zth::assert_handler( \
221 __FILE__, __LINE__, \
222 ::zth::Config::EnableFullAssert ? ZTH_STRINGIFY(expr) \
226# define zth_assert(...) \
232# ifndef ZTH_CLASS_NOCOPY
233# if __cplusplus >= 201103L
234# define ZTH_CLASS_NOCOPY(Class) \
236 Class(Class const&) = delete; \
240 Class& operator=(Class const&) noexcept = delete; \
241 Class& operator=(Class&&) noexcept = \
246# define ZTH_CLASS_NOCOPY(Class) \
248 Class(Class const&); \
249 Class& operator=(Class const&);
257ZTH_EXPORT
char const* banner()
noexcept;
259ZTH_EXPORT __attribute__((format(
ZTH_ATTR_PRINTF, 1, 2), noreturn))
void
260abort(
char const* fmt, ...)
noexcept;
262ZTH_EXPORT __attribute__((format(
ZTH_ATTR_PRINTF, 1, 0), noreturn))
void
263abortv(
char const* fmt, va_list args)
noexcept;
265ZTH_EXPORT __attribute__((noreturn))
void
266assert_handler(
char const* file,
int line,
char const* expr);
268ZTH_EXPORT
bool log_supports_ansi_colors()
noexcept;
271log_colorv(
int color,
char const* fmt, va_list args);
279log_color(
int color,
char const* fmt, ...)
283 log_colorv(color, fmt, args);
294logv(
char const* fmt, va_list arg)
305ZTH_EXPORT __attribute__((format(
ZTH_ATTR_PRINTF, 1, 2)))
inline void log(
char const* fmt, ...)
317typedef std::basic_string<char, std::char_traits<char>, Config::Allocator<char>::type> string;
369# if __cplusplus >= 201103L
376 , m_str(
std::move(s))
382 m_str = std::move(s);
389 return std::move(
local());
398 char const*
c_str()
const
400 return m_cstr ? m_cstr : m_str.c_str();
403 operator string const&()
const
408 char const&
at(
size_t pos)
const
410 return str().at(pos);
415 return m_cstr ? m_cstr[pos] :
str()[pos];
423 char const*
data()
const
428 bool empty() const noexcept
430 return m_cstr ? *m_cstr == 0 : m_str.empty();
433 size_t size() const noexcept
438 size_t length() const noexcept
440 return str().length();
443 void clear() noexcept
451 return m_cstr !=
nullptr;
456 return m_cstr ==
nullptr;
460 string const&
local()
const
476 mutable char const* m_cstr;
477 mutable string m_str;
485__attribute__((format(
ZTH_ATTR_PRINTF, 1, 2))) inline
string format(
char const* fmt, ...)
489 string res =
formatv(fmt, args);
499inline cow_string
str(T value)
501 return cow_string(value);
507 return format(
"%c", value);
511inline cow_string str<signed char>(
signed char value)
513 if(Config::UseLimitedFormatSpecifiers)
514 return format(
"%d", (
int)value);
516 return format(
"%hhd", value);
520inline cow_string str<unsigned char>(
unsigned char value)
522 if(Config::UseLimitedFormatSpecifiers)
523 return format(
"%u", (
unsigned int)value);
525 return format(
"%hhu", value);
531 if(Config::UseLimitedFormatSpecifiers)
532 return format(
"%d", (
int)value);
534 return format(
"%hd", value);
538inline cow_string str<unsigned short>(
unsigned short value)
540 if(Config::UseLimitedFormatSpecifiers)
541 return format(
"%u", (
unsigned int)value);
543 return format(
"%hu", value);
549 return format(
"%d", value);
553inline cow_string str<unsigned int>(
unsigned int value)
555 return format(
"%u", value);
559ZTH_EXPORT
ZTH_INLINE cow_string strull(
unsigned long long value)
562 if(value > (
unsigned long long)std::numeric_limits<int>::max())
564 "0x%x%08x", (
unsigned)(value >> 32U),
565 (
unsigned)(value & 0xFFFFFFFFU));
567 return format(
"%d", (
int)value);
569 return format(
"%llu", value);
577 if(Config::UseLimitedFormatSpecifiers) {
578 if(
sizeof(
long) ==
sizeof(
int)
579 || (value <= std::numeric_limits<int>::max()
580 && value >= std::numeric_limits<int>::min()))
581 return format(
"%d", (
int)value);
583 return impl::strull((
unsigned long long)value);
585 return format(
"%ld", value);
590inline cow_string str<unsigned long>(
unsigned long value)
592 if(Config::UseLimitedFormatSpecifiers) {
593 if(
sizeof(
unsigned long) ==
sizeof(
unsigned int)
594 || value <= std::numeric_limits<unsigned int>::max())
595 return format(
"%u", (
unsigned int)value);
597 return impl::strull((
unsigned long long)value);
599 return format(
"%lu", value);
604inline cow_string str<long long>(
long long value)
606 if(Config::UseLimitedFormatSpecifiers) {
607 if(value > std::numeric_limits<int>::max()
608 || value < std::numeric_limits<int>::min())
609 return impl::strull((
unsigned long long)value);
611 return format(
"%d", (
int)value);
613 return format(
"%lld", value);
618inline cow_string str<unsigned long long>(
unsigned long long value)
620 return impl::strull(value);
624ZTH_EXPORT
ZTH_INLINE cow_string strf(
float value)
627 if(!(value < (
float)std::numeric_limits<int>::max()
628 && value > (
float)-std::numeric_limits<int>::max()))
633 if(std::abs(fi - value) < 0.0005F)
636 int f = std::min(std::abs((
int)((value - fi) * 1000.0F + 0.5F)), 999);
637 return format(
"%d.%03d", i, f);
639 return format(
"%g", (
double)value);
647 if(Config::UseLimitedFormatSpecifiers)
648 return impl::strf(value);
650 return format(
"%g", (
double)value);
656 if(Config::UseLimitedFormatSpecifiers)
657 return impl::strf((
float)value);
659 return format(
"%g", value);
663inline cow_string str<long double>(
long double value)
665 if(Config::UseLimitedFormatSpecifiers)
666 return impl::strf((
float)value);
668 return format(
"%Lg", value);
674 return format(
"%p", value);
677# if __cplusplus >= 201103L
679inline cow_string str<string&&>(
string&& value)
688inline string err(
int e)
690# ifdef ZTH_OS_BAREMETAL
692 return format(
"error %d", e);
693# elif defined(ZTH_HAVE_LIBZMQ)
694 return format(
"%s (error %d)", zmq_strerror(e), e);
695# elif ZTH_THREADS && !defined(ZTH_OS_WINDOWS)
697# if !defined(ZTH_OS_LINUX) || (_POSIX_C_SOURCE >= 200112L) && !defined(_GNU_SOURCE)
699 return format(
"%s (error %d)", strerror_r(e, buf,
sizeof(buf)) ?
"Unknown error" : buf, e);
702 return format(
"%s (error %d)", strerror_r(e, buf,
sizeof(buf)), e);
706 return format(
"%s (error %d)", strerror(e), e);
712 virtual char const*
id_str() const noexcept = 0;
724template <
bool Named = Config::NamedObjects>
737# if __cplusplus >= 201103L
739 : m_name(
std::move(name))
743 virtual uint64_t id_() const noexcept = 0;
748 string const& name() const noexcept
753 void setName(
string const& name)
762 changedName(this->name());
765# if __cplusplus >= 201103L
768 m_name = std::move(name);
770 changedName(this->name());
774 virtual char const* id_str() const noexcept
override
779# ifdef ZTH_OS_BAREMETAL
782 format(
"%s #%u", name().empty() ?
"Object" : name().c_str(),
783 (
unsigned int)id_());
786 name().empty() ?
"Object" : name().c_str(),
787# ifdef ZTH_OS_WINDOWS
788 (
unsigned int)_getpid(),
790 (
unsigned int)getpid(),
803 return m_id_str.c_str();
807 virtual void changedName(
string const&
UNUSED_PAR(name)) {}
811 string mutable m_id_str;
821 virtual uint64_t id_() const noexcept = 0;
825 string const& name() const noexcept
827 static string const null;
833 changedName(this->name());
838 changedName(this->name());
841# if __cplusplus >= 201103L
844 changedName(this->name());
848 virtual char const* id_str() const noexcept
override
850 return name().c_str();
854 virtual void changedName(
string const&
UNUSED_PAR(name)) {}
861template <
typename T,
bool ThreadSafe = Config::EnableThreads>
862class UniqueID :
public NamedUniqueID<> {
863# if __cplusplus < 201103L
869# if __cplusplus >= 201103L
876 *
this = std::move(u);
883 base::operator=(std::move(u));
888 static uint64_t getID() noexcept
891# if GCC_VERSION < 40802L
892 __sync_add_and_fetch(&m_nextId, 1)
894 __atomic_add_fetch(&m_nextId, 1, __ATOMIC_RELAXED)
899 explicit UniqueID(
string const& name)
904# if __cplusplus >= 201103L
911 explicit UniqueID(
char const* name =
nullptr)
918 void const* normptr() const noexcept
923 __attribute__((pure)) uint64_t id() const noexcept
929 virtual uint64_t id_() const noexcept final
938 static uint64_t m_nextId;
941template <
typename T,
bool ThreadSafe>
958 zth_assert(m_count < std::numeric_limits<size_t>::max());
962 bool unused() noexcept
972 size_t refs() const noexcept
978 virtual void cleanup() noexcept
987template <
typename T,
typename WhenTIsVo
id>
992template <
typename WhenTIsVo
id>
994 typedef WhenTIsVoid
type;
997# if __cplusplus >= 201103L
1001template <
size_t N,
size_t... S>
1002struct SequenceGenerator : SequenceGenerator<N - 1, N - 1, S...> {};
1004template <
size_t... S>
1005struct SequenceGenerator<0, S...> {
1006 typedef Sequence<S...> type;
1014template <
typename T>
1025 constexpr operator pointer_type*()
const noexcept
1030 constexpr operator bool() const noexcept
1035 constexpr14 pointer_type* operator->() const noexcept
1041 constexpr14 pointer_type& operator*() const noexcept
1060template <
typename T>
1089template <
typename T>
1115 if(m_instance ==
static_cast<singleton_type*
>(
this))
1116 m_instance =
nullptr;
1124 __attribute__((pure))
constexpr14 static typename safe_ptr<singleton_type>::type
1132 static singleton_type* m_instance;
1135template <
typename T>
1147template <
typename T>
1148class ThreadLocalSingleton {
1174 if(
ZTH_TLS_GET(m_instance) ==
static_cast<singleton_type*
>(
this))
1183 __attribute__((pure))
static typename safe_ptr<singleton_type>::type instance() noexcept
1193template <
typename T>
1214template <typename T, int8_t Prealloc = 1, typename Allocator = typename Config::Allocator<T>::type>
1219 typedef std::vector<value_type, allocator_type>
vector_type;
1222 prealloc_request = Prealloc > 0 ? Prealloc : 0,
1223 prealloc_request_size = prealloc_request *
sizeof(
value_type),
1226 prealloc_request_size > vector_size ? prealloc_request_size : vector_size,
1237 static_assert(prealloc < std::numeric_limits<uint8_t>::max(),
"");
1248 vector().~vector_type();
1254 value_type& operator[](
size_t index)
noexcept
1257 return data()[index];
1263 value_type
const& operator[](
size_t index)
const noexcept
1266 return data()[index];
1274 value_type& front() noexcept
1284 value_type
const& front() const noexcept
1294 value_type& back() noexcept
1297 return (*
this)[size() - 1U];
1305 value_type
const& back() const noexcept
1308 return (*
this)[size() - 1U];
1314 value_type* data() noexcept
1316 return is_small() ? array() : vector().data();
1322 value_type
const* data() const noexcept
1324 return is_small() ? array() : vector().data();
1330 bool empty() const noexcept
1332 return is_small() ? m_size == 0 : vector().empty();
1338 size_t size() const noexcept
1340 return is_small() ? m_size : vector().size();
1348 void reserve(
size_t new_cap)
1350 if(is_small() && new_cap <= prealloc)
1354 make_vector(new_cap);
1356 vector().reserve(new_cap);
1363 size_t capacity() const noexcept
1365 return is_small() ? (size_t)prealloc : vector().capacity();
1373 void clear() noexcept
1384 void clear_and_release() noexcept
1398 void push_back(value_type
const& v)
1400 reserve(size() + 1U);
1402 if(m_size < prealloc) {
1403 new(&array()[m_size]) value_type(v);
1406 vector().push_back(v);
1409# if __cplusplus >= 201103L
1414 template <
class... Args>
1415 void emplace_back(Args&&... args)
1417 reserve(size() + 1U);
1419 if(m_size < prealloc) {
1420 new(&array()[m_size]) value_type(std::forward<Args>(args)...);
1423 vector().emplace_back(std::forward<Args>(args)...);
1432 void pop_back() noexcept
1436 array()[--m_size].~value_type();
1438 vector().pop_back();
1446 void resize(
size_t count, value_type
const& x = value_type())
1449 while(count < m_size)
1450 array()[--m_size].~value_type();
1452 if(count <= prealloc) {
1453 while(count > m_size) {
1454 new(&array()[m_size]) value_type(x);
1459 vector().resize(count, x);
1462 vector().resize(count, x);
1469 bool is_small() const noexcept
1471 return m_size <= prealloc;
1477 value_type* array() noexcept
1480 return reinterpret_cast<value_type*
>(m_buffer);
1486 value_type
const* array() const noexcept
1489 return reinterpret_cast<value_type const*
>(m_buffer);
1495 vector_type& vector() noexcept
1498 void* buffer = m_buffer;
1499 return *
reinterpret_cast<vector_type*
>(buffer);
1505 vector_type
const& vector() const noexcept
1508 void const* buffer = m_buffer;
1509 return *
reinterpret_cast<vector_type const*
>(buffer);
1515 void make_vector(
size_t new_cap)
1521 v.reserve(std::max(new_cap, (
size_t)m_size));
1523 for(
size_t i = 0; i < m_size; i++) {
1524# if __cplusplus >= 201103L
1525 v.emplace_back(std::move(array()[i]));
1527 v.push_back(array()[i]);
1529 array()[i].~value_type();
1532 m_size = prealloc + 1U;
1533 new(m_buffer) vector_type;
1542 alignas(vector_type)
alignas(value_type)
char m_buffer[buffer_size];
1554template <
size_t size>
1559 x >= 0x100000000ULL ? 8U
1560 : x >= 0x10000U ? 4U
1563struct smallest_uint {
1564 typedef uint64_t
type;
1567template <u
int64_t x>
1569 typedef uint8_t
type;
1572template <u
int64_t x>
1574 typedef uint16_t
type;
1577template <u
int64_t x>
1579 typedef uint32_t
type;
1583# if __cplusplus >= 201703L
1586template <
class T,
class... TArgs>
1589template <
class,
class...>
1592template <
class T,
class... TArgs>
1598 constexpr operator T();
1605 using type = std::decay_t<T>;
1611 auto&& [p1, p2, p3, p4] = std::forward<T>(
object);
1612 return std::make_tuple(p1, p2, p3, p4);
1615 auto&& [p1, p2, p3] = std::forward<T>(
object);
1616 return std::make_tuple(p1, p2, p3);
1618 auto&& [p1, p2] = std::forward<T>(
object);
1619 return std::make_tuple(p1, p2);
1621 auto&& [p1] = std::forward<T>(
object);
1622 return std::make_tuple(p1);
1624 return std::make_tuple();
1628# define ZTH_STRUCTURED_BINDING_FORWARDING(Class) \
1629 template <typename T> \
1630 struct std::tuple_size<Class<T>> : std::tuple_size<T> {}; \
1632 template <size_t N, typename T> \
1633 struct std::tuple_element<N, Class<T>> : std::tuple_element<N, T> {}; \
1635 template <size_t N, typename T> \
1636 decltype(auto) get(Class<T>& f) noexcept \
1638 auto& x = to_tuple(*f); \
1641# define ZTH_STRUCTURED_BINDING_FORWARDING_NS(Class) \
1643 ZTH_STRUCTURED_BINDING_FORWARDING(zth::Class) \
1646# define ZTH_STRUCTURED_BINDING_FORWARDING(Class)
1647# define ZTH_STRUCTURED_BINDING_FORWARDING_NS(Class)
1687 va_start(args, fmt);
1706 va_start(args, fmt);
1714#ifdef ZTH_OS_BAREMETAL
1717EXTERN_C __attribute__((
format(gnu_printf, 2, 0))) int asprintf(
char** strp, const
char* fmt, ...);
1718EXTERN_C __attribute__((format(gnu_printf, 2, 0)))
int
1719vasprintf(
char** strp, const
char* fmt, va_list ap);
T singleton_type
Alias of the T template parameter.
Singleton pattern, but only per-thread.
T singleton_type
Alias of the T template parameter.
virtual char const * id_str() const noexcept=0
friend cow_string str(UniqueIDBase const &)
Keeps track of a process-wide unique ID within the type T.
char operator[](size_t pos) const
bool isConst() const noexcept
string const & local() const
char const & at(size_t pos) const
char const * c_str() const
size_t length() const noexcept
cow_string & operator=(cow_string const &s)
size_t size() const noexcept
char const * data() const
bool empty() const noexcept
bool isLocal() const noexcept
Wrapper for a pointer, which checks validity of the pointer upon dereference.
A simple std::vector, which can contain Prealloc without heap allocation.
std::vector< value_type, allocator_type > vector_type
void zth_banner()
Prints a banner line with version and configuration information.
void zth_log(char const *fmt,...)
Logs a given printf()-like formatted string.
void zth_abort(char const *fmt,...)
Aborts the process after printing the given printf() formatted message.
void zth_log_color(int color, char const *fmt,...)
Logs a given printf()-like formatted string using an ANSI color code.
void zth_logv(char const *fmt, va_list arg)
Prints the given printf()-like formatted string to stdout.
void log_colorv(int color, char const *fmt, va_list args)
Logs a given printf()-like formatted string using an ANSI color code.
char const * banner() noexcept
Prints a banner line with version and configuration information.
void logv(char const *fmt, va_list arg)
Logs a given printf()-like formatted string.
#define ZTH_TLS_DEFINE(type, var, init)
#define ZTH_TLS_MEMBER(type, var)
#define ZTH_TLS_SET(var, value)
decltype(test_is_braces_constructible< T, TArgs... >(0)) is_braces_constructible
decltype(void(T{std::declval< TArgs >()...}), std::true_type{}) test_is_braces_constructible(int)
auto to_tuple(T &&object) noexcept
cow_string str(T value)
Returns an zth::string representation of the given value.
string formatv(char const *fmt, va_list args)
Format like vsprintf(), but save the result in an zth::string.
string format(char const *fmt,...)
Format like sprintf(), but save the result in an zth::string.
static bool const UseLimitedFormatSpecifiers
Use limited formatting specifiers.
Change the name of a fiber returned by zth_async.
#define zth_assert(expr)
assert(), but better integrated in Zth.
#define ZTH_CLASS_NOCOPY(Class)
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.