source: mainline/uspace/lib/cpp/include/impl/thread.hpp@ ad403590

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ad403590 was ad403590, checked in by Dzejrou <dzejrou@…>, 7 years ago

cpp: added a basic <thread> implementation

  • Property mode set to 100644
File size: 5.6 KB
Line 
1/*
2 * Copyright (c) 2017 Jaroslav Jindrak
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#ifndef LIBCPP_THREAD
30#define LIBCPP_THREAD
31
32#include <chrono>
33#include <internal/common.hpp>
34#include <ostream>
35
36namespace std
37{
38 extern "C" {
39 #include <fibril.h>
40 #include <fibril_synch.h>
41 }
42
43 /**
44 * 30.3.1, class thread:
45 */
46
47 class thread
48 {
49 public:
50 class id;
51
52 using native_handle_type = fibril_t*;
53
54 /**
55 * 30.3.1.2, thread constructors:
56 * 30.3.1.3, thread destructor:
57 * 30.3.1.4, thread assignment:
58 */
59
60 thread() noexcept;
61
62 ~thread();
63
64 // TODO: check the remark in the standard
65 template<class F, class... Args>
66 explicit thread(F&& f, Args&&... args)
67 {
68 // TODO: create std::function out of f and args,
69 // then use fibril_create with that as
70 // the argument and call it?
71 id_ = fibril_create(f, nullptr);
72 fibril_add_ready(id_);
73 }
74
75 thread(const thread&) = delete;
76 thread& operator=(const thread&) = delete;
77
78 thread(thread&& other) noexcept;
79 thread& operator=(thread&& other) noexcept;
80
81 /**
82 * 30.3.1.5, thread members:
83 */
84
85 void swap(thread& other) noexcept;
86
87 bool joinable() const noexcept;
88
89 void join();
90
91 void detach();
92
93 id get_id() const noexcept;
94
95 native_handle_type native_handle();
96
97 static unsigned hardware_concurrency() noexcept;
98
99 private:
100 fid_t id_;
101 };
102
103 void swap(thread& x, thread& y) noexcept;
104
105 /**
106 * 30.3.2, namespace this_thread:
107 */
108
109 namespace this_thread
110 {
111 thread::id get_id() noexcept;
112
113 void yield() noexcept;
114
115 template<class Clock, class Duration>
116 void sleep_until(const chrono::time_point<Clock, Duration>& abs_time)
117 {
118 auto now = Clock::now();
119 auto usecs = chrono::duration_cast<chrono::duration<typename Duration::rep, micro>>(abs_time - now);
120
121 std::fibril_usleep(usecs.count());
122 }
123
124 template<class Rep, class Period>
125 void sleep_for(const chrono::duration<Rep, Period>& rel_time)
126 {
127 if (rel_time <= chrono::duration<Rep, Period>::zero())
128 return;
129
130 // TODO: timeouts?
131 auto usecs = chrono::duration_cast<chrono::duration<Rep, micro>>(rel_time);
132 std::fibril_usleep(usecs.count());
133 }
134 }
135
136 template<class T>
137 struct hash;
138
139 class thread::id
140 {
141 public:
142 id() noexcept
143 : id_{}
144 { /* DUMMY BODY */ }
145
146 fid_t id_; // For testing atm public.
147 private:
148 id(fid_t id)
149 : id_{id}
150 { /* DUMMY BODY */ }
151
152 friend class thread;
153
154 friend bool operator==(thread::id, thread::id) noexcept;
155 friend bool operator!=(thread::id, thread::id) noexcept;
156 friend bool operator<(thread::id, thread::id) noexcept;
157 friend bool operator<=(thread::id, thread::id) noexcept;
158 friend bool operator>(thread::id, thread::id) noexcept;
159 friend bool operator>=(thread::id, thread::id) noexcept;
160
161 template<class Char, class Traits>
162 friend basic_ostream<Char, Traits>& operator<<(
163 basic_ostream<Char, Traits>&, thread::id);
164
165 friend struct hash<id>;
166
167 friend id this_thread::get_id() noexcept;
168 };
169
170 bool operator==(thread::id lhs, thread::id rhs) noexcept;
171 bool operator!=(thread::id lhs, thread::id rhs) noexcept;
172 bool operator<(thread::id lhs, thread::id rhs) noexcept;
173 bool operator<=(thread::id lhs, thread::id rhs) noexcept;
174 bool operator>(thread::id lhs, thread::id rhs) noexcept;
175 bool operator>=(thread::id lhs, thread::id rhs) noexcept;
176
177 template<class Char, class Traits>
178 basic_ostream<Char, Traits>& operator<<(basic_ostream<Char, Traits>& out, thread::id id)
179 {
180 out << id.id_;
181
182 return out;
183 }
184
185 template<> // TODO: implement
186 struct hash<thread::id>;
187}
188
189#endif
Note: See TracBrowser for help on using the repository browser.