Zth (libzth)
winfiber.h
Go to the documentation of this file.
1 #ifndef ZTH_CONTEXT_WINFIBER_H
2 #define ZTH_CONTEXT_WINFIBER_H
3 /*
4  * Zth (libzth), a cooperative userspace multitasking library.
5  * Copyright (C) 2019-2022 Jochem Rutgers
6  *
7  * This Source Code Form is subject to the terms of the Mozilla Public
8  * License, v. 2.0. If a copy of the MPL was not distributed with this
9  * file, You can obtain one at https://mozilla.org/MPL/2.0/.
10  */
11 
12 #ifndef ZTH_CONTEXT_CONTEXT_H
13 # error This file must be included by libzth/context/context.h.
14 #endif
15 
16 #ifdef __cplusplus
17 
18 # include <windows.h>
19 
20 namespace zth {
21 
22 class Context : public impl::ContextArch<Context> {
24 public:
26 
27  constexpr explicit Context(ContextAttr const& attr) noexcept
28  : base(attr)
29  , m_fiber()
30  {}
31 
32  static int init() noexcept
33  {
34  int res = 0;
35  if(ConvertThreadToFiber(nullptr))
36  return 0;
37  else if((res = -(int)GetLastError()))
38  return res;
39  else
40  return EINVAL;
41  }
42 
43  int initStack(Stack& UNUSED_PAR(stack), Stack& UNUSED_PAR(usable)) noexcept
44  {
45  // Stack is managed by Windows.
46  usable = stack;
47  return 0;
48  }
49 
50  void deinitStack(Stack& UNUSED_PAR(stack)) noexcept {}
51 
52  int stackGuardInit() noexcept
53  {
54  // There is no stack to guard.
55  return 0;
56  }
57 
58  void stackGuardDeinit() noexcept {}
59 
60  void valgrindRegister() noexcept
61  {
62  // There is no stack to register.
63  }
64 
65  void valgrindDeregister() noexcept {}
66 
67  int create() noexcept
68  {
69  int res = 0;
70  if((res = base::create()))
71  return res;
72 
73  if(unlikely(!stack().size)) {
74  // Stackless fiber only saves current context.
75  if((m_fiber = GetCurrentFiber()))
76  return 0;
77  } else if((m_fiber = CreateFiber(
79  reinterpret_cast<LPFIBER_START_ROUTINE>(&context_entry),
80  (LPVOID)this))) {
81  zth_dbg(context, "[%s] Created fiber %p", currentWorker().id_str(),
82  m_fiber);
83  return 0;
84  }
85 
86  if((res = -(int)GetLastError()))
87  return res;
88  else
89  return EINVAL;
90  }
91 
92  void destroy() noexcept
93  {
94  if(!m_fiber)
95  return;
96 
97  // If the current fiber is the one to delete, it is probably not created by us.
98  if(likely(m_fiber != GetCurrentFiber())) {
99  zth_dbg(context, "[%s] Delete fiber %p", currentWorker().id_str(), m_fiber);
100  DeleteFiber(m_fiber);
101  }
102 
103  m_fiber = nullptr;
104  }
105 
106  void context_switch(Context& to) noexcept
107  {
108  zth_assert(to.m_fiber && to.m_fiber != GetCurrentFiber());
109  SwitchToFiber(to.m_fiber);
110  }
111 
112 private:
113  LPVOID m_fiber;
114 };
115 
116 } // namespace zth
117 #endif // __cplusplus
118 #endif // ZTH_CONTEXT_WINFIBER_H
void destroy() noexcept
Definition: winfiber.h:92
void valgrindRegister() noexcept
Definition: winfiber.h:60
void stackGuardDeinit() noexcept
Definition: winfiber.h:58
int create() noexcept
Definition: winfiber.h:67
void deinitStack(Stack &UNUSED_PAR(stack)) noexcept
Definition: winfiber.h:50
impl::ContextArch< Context > base
Definition: winfiber.h:25
static int init() noexcept
Definition: winfiber.h:32
void valgrindDeregister() noexcept
Definition: winfiber.h:65
void context_switch(Context &to) noexcept
Definition: winfiber.h:106
int stackGuardInit() noexcept
Definition: winfiber.h:52
constexpr Context(ContextAttr const &attr) noexcept
Definition: sigaltstack.h:65
int initStack(Stack &UNUSED_PAR(stack), Stack &UNUSED_PAR(usable)) noexcept
Definition: winfiber.h:43
Stack const & stack() const noexcept
Return the stack address.
Definition: context.h:252
int create() noexcept
Create context.
Definition: context.h:162
ContextAttr & attr() noexcept
Return the context attributes, requested by the user.
Definition: context.h:146
Worker & currentWorker() noexcept
Return the (thread-local) singleton Worker instance.
Definition: worker.h:388
#define zth_dbg(group, fmt, a...)
Debug printf()-like function.
Definition: util.h:210
#define ZTH_CLASS_NEW_DELETE(T)
Define new/delete operators for a class, which are allocator-aware.
Definition: allocator.h:114
#define UNUSED_PAR(name)
Definition: macros.h:79
Definition: allocator.h:23
void context_entry(Context *context)
static size_t const DefaultFiberStackSize
Default fiber stack size in bytes.
Definition: config.h:133
Stack information.
Definition: context.h:110
#define zth_assert(expr)
assert(), but better integrated in Zth.
Definition: util.h:236
#define likely(expr)
Marks the given expression to likely be evaluated to true.
Definition: util.h:42
#define unlikely(expr)
Marks the given expression to likely be evaluated to true.
Definition: util.h:56