Realm
A distributed, event-based tasking library
Loading...
Searching...
No Matches
utils.h
Go to the documentation of this file.
1/*
2 * Copyright 2025 Stanford University, NVIDIA Corporation
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// little helper utilities for Realm code
19// none of this is Realm-specific, but it's put in the Realm namespace to
20// reduce the chance of conflicts
21
22#ifndef REALM_UTILS_H
23#define REALM_UTILS_H
24
25#include "realm/realm_config.h"
26
27#include <string>
28#include <ostream>
29#include <vector>
30#include <map>
31#include <cassert>
32#include <cstdint>
33#include <sstream>
34
35#if defined(REALM_ON_WINDOWS)
36#ifndef WIN32_LEAN_AND_MEAN
37#define WIN32_LEAN_AND_MEAN 1
38#endif
39#include <windows.h>
40#endif
41
42// Define the intrinsic for yielding a core's resources temporarily in order to
43// relieve some pressure on the memory bus and give other threads a chance to
44// make some forward progress to unblock us. This does *not* yield the thread
45// to the OS.
46#if defined(__SSE__)
47// Same as "pause", but is more compatible for older intel cpus
48#define REALM_SPIN_YIELD() asm volatile("rep; nop" :::)
49#elif defined(__aarch64__) || defined(__arm__)
50#define REALM_SPIN_YIELD() asm volatile("yield" :::)
51#elif defined(__PPC64__) || defined(__PPC__)
52#define REALM_SPIN_YIELD() asm volatile("yield" :::)
53#else
54#define REALM_SPIN_YIELD()
55#endif
56
57#define REALM_HASH_TOKEN(x) Realm::hash_fnv1a(#x, sizeof(#x) - 1)
58
59namespace Realm {
60
61 // While this is recurisve, this is a compile-time
62 constexpr uint64_t hash_fnv1a(const char *s, size_t n,
63 const uint64_t value = 0xcbf29ce484222325ULL) noexcept
64 {
65 return n == 0 ? value
66 : hash_fnv1a(s + 1, n - 1, ((value ^ uint64_t(*s)) * 0x100000001b3ULL));
67 }
68
69 // Based on boost::hash_combine
70 constexpr size_t hash_combine(size_t lhs, size_t rhs) noexcept
71 {
72#if SIZE_MAX == UINT64_MAX
73 constexpr size_t seed = size_t{0x517cc1b727220a95ULL};
74#else
75 constexpr size_t seed = size_t{0x9e3779b9UL};
76#endif
77 return lhs ^ (rhs + seed + (lhs << 6) + (lhs >> 2));
78 }
79
80 // TODO: actually use C++20 version if available
81 const size_t dynamic_extent = size_t(-1);
82
83 template <typename T, size_t Extent = dynamic_extent>
84 class span;
85
86 // helpers for deleting contents STL containers of pointers-to-things
87
88 template <typename T>
89 void delete_container_contents(std::vector<T *> &v, bool clear_cont = true)
90 {
91 for(typename std::vector<T *>::iterator it = v.begin(); it != v.end(); it++)
92 delete(*it);
93
94 if(clear_cont)
95 v.clear();
96 }
97
98 template <typename K, typename V>
99 void delete_container_contents(std::map<K, V *> &m, bool clear_cont = true)
100 {
101 for(typename std::map<K, V *>::iterator it = m.begin(); it != m.end(); it++)
102 delete it->second;
103
104 if(clear_cont)
105 m.clear();
106 }
107
108 template <typename K, typename V>
109 void delete_container_contents_free(std::map<K, V *> &m, bool clear_cont = true)
110 {
111 for(typename std::map<K, V *>::iterator it = m.begin(); it != m.end(); it++)
112 free(it->second);
113
114 if(clear_cont)
115 m.clear();
116 }
117
118 // streambuf that holds most messages in an internal buffer
119 template <size_t _INTERNAL_BUFFER_SIZE, size_t _INITIAL_EXTERNAL_SIZE>
120 class shortstringbuf : public std::streambuf {
121 public:
124
125 const char *data() const;
126 size_t size() const;
127
128 protected:
129 virtual int_type overflow(int_type c);
130
131 static const size_t INTERNAL_BUFFER_SIZE = _INTERNAL_BUFFER_SIZE;
132 static const size_t INITIAL_EXTERNAL_BUFFER_SIZE = _INITIAL_EXTERNAL_SIZE;
136 };
137
138 // helper class that lets you build a formatted std::string as a single expression:
139 // /*std::string s =*/ stringbuilder() << ... << ... << ...;
140
142 public:
144 : os(&strbuf)
145 {}
146 operator std::string(void) const { return std::string(strbuf.data(), strbuf.size()); }
147 template <typename T>
149 {
150 os << data;
151 return *this;
152 }
153
154 protected:
156 std::ostream os;
157 };
158
159 // behaves like static_cast, but uses dynamic_cast+assert when DEBUG_REALM
160 // is defined
161 template <typename T, typename T2>
162 inline T checked_cast(T2 *ptr)
163 {
164#ifdef DEBUG_REALM
165 T result = dynamic_cast<T>(ptr);
166 assert(result != 0);
167 return result;
168#else
169 return static_cast<T>(ptr);
170#endif
171 }
172
173 // a wrapper class that defers construction of the underlying object until
174 // explicitly requested
175 template <typename T>
177 public:
180
181 // zero and one argument constructors for now
183
184 template <typename T1>
185 T *construct(T1 arg1);
186
187 // object must have already been explicitly constructed to dereference
190
191 const T &operator*() const;
192 const T *operator->() const;
193
194 protected:
195 T *ptr; // needed to avoid type-punning complaints
196 typedef char Storage_unaligned[sizeof(T)];
198 Storage_aligned raw_storage;
199 };
200
201 template <unsigned _BITS, unsigned _SHIFT>
202 struct bitfield {
203 static const unsigned BITS = _BITS;
204 static const unsigned SHIFT = _SHIFT;
205
206 template <typename T>
207 static T extract(T source);
208
209 template <typename T>
210 static T insert(T target, T field);
211
212 template <typename T>
213 static T bit_or(T target, T field);
214 };
215
216 template <typename T>
217 class bitpack {
218 public:
219 bitpack(); // no initialization
220 bitpack(const bitpack<T> &copy_from);
221 bitpack(T init_val);
222
223 bitpack<T> &operator=(const bitpack<T> &copy_from);
225
226 operator T() const;
227
228 template <typename BITFIELD>
230 public:
231 bitsliceref(T &_target);
232
233 operator T() const;
236
237 static const T MAXVAL = ~(~T(0) << BITFIELD::BITS);
238
239 protected:
241 };
242
243 template <typename BITFIELD>
245 public:
246 constbitsliceref(const T &_target);
247
248 operator T() const;
249
250 static const T MAXVAL = ~(~T(0) << BITFIELD::BITS);
251
252 protected:
253 const T &target;
254 };
255
256 template <typename BITFIELD>
258 template <typename BITFIELD>
260
261 template <typename BITFIELD>
263 template <typename BITFIELD>
265
266 protected:
268 };
269
270 // helpers to pretty-print containers
271
272 template <typename T>
274 public:
275 explicit PrettyVector(const T *_data, size_t _size, const char *_delim = ", ",
276 const char *_pfx = "[", const char *_sfx = "]");
277 template <typename Container = std::vector<T>>
278 explicit PrettyVector(const Container &_v, const char *_delim = ", ",
279 const char *_pfx = "[", const char *_sfx = "]");
280
281 void print(std::ostream &os) const;
282
283 protected:
284 const T *data;
285 size_t size;
286 const char *delim;
287 const char *pfx;
288 const char *sfx;
289 };
290
291 template <typename T>
292 std::ostream &operator<<(std::ostream &os, const PrettyVector<T> &pv);
293
294 // metaprogramming stuff that's standard in c++11 and beyond
295 using std::enable_if;
296 using std::is_integral;
297 using std::make_signed;
298 using std::make_unsigned;
299 using std::remove_const;
300
301 template <typename T>
303 public:
304 typedef typename remove_const<T>::type value_type;
305 static const size_t extent = dynamic_extent;
306
308 : base(0)
309 , length(0)
310 {}
311 span(T *_base, size_t _length)
312 : base(_base)
313 , length(_length)
314 {}
315
316 // from another span
317 template <size_t Extent2>
319 : base(copy_from.data())
320 , length(copy_from.size())
321 {}
322
323 // from a vector
324 span(const std::vector<typename remove_const<T>::type> &v)
325 : base(v.data())
326 , length(v.size())
327 {}
328
329 // from a scalar
330 span(T &v)
331 : base(&v)
332 , length(1)
333 {}
334
335 T &operator[](size_t idx) const { return base[idx]; }
336
337 T *data() const { return base; }
338 size_t size() const { return length; }
339 bool empty() const { return (length == 0); }
340
341 protected:
343 size_t length;
344 };
345
347 public:
348 template <typename T>
349 operator span<T, dynamic_extent>() const
350 {
352 }
353 };
354
355 template <typename T>
356 span<T, dynamic_extent> make_span(T *base, size_t length)
357 {
358 return span<T, dynamic_extent>(base, length);
359 }
360
361 // accumulates a crc32c checksum
362 // initialization (traditionally to 0xFFFFFFFF) and finalization (by
363 // inverting) the accumulator is left to the caller
364 REALM_PUBLIC_API uint32_t crc32c_accumulate(uint32_t accum_in, const void *data,
365 size_t len);
366
367 // helper class to make something non-copy/moveable
369 protected:
372
373 private:
374 noncopyable(const noncopyable &) = delete;
375 noncopyable(noncopyable &&) = delete;
376 noncopyable &operator=(const noncopyable &) = delete;
377 noncopyable &operator=(noncopyable &&) = delete;
378 };
379
380 // explicitly calls the destructor on an object, working around issues
381 // with some compilers and typedefs
382 template <typename T>
383 void call_destructor(T *obj)
384 {
385 obj->~T();
386 }
387
388 // Provide support for a generic function realm_strerror that converts
389 // OS error codes back to strings in portable way across OSes
390 REALM_PUBLIC_API const char *realm_strerror(int err);
391
392 // Finds first-bit-set
393 unsigned ctz(uint64_t v);
394
395#ifdef REALM_ON_WINDOWS
396 typedef HANDLE OsHandle;
397 static const OsHandle INVALID_OS_HANDLE = 0;
398#else
399 typedef int OsHandle;
400 static const OsHandle INVALID_OS_HANDLE = -1;
401#endif
402
408 OsHandle ipc_mailbox_create(const std::string &name);
409
419 bool ipc_mailbox_send(OsHandle mailbox, const std::string &to,
420 const std::vector<OsHandle> &handles, const void *data,
421 size_t data_sz);
422
433 bool ipc_mailbox_recv(OsHandle mailbox, const std::string &from,
434 std::vector<OsHandle> &handles, void *data, size_t &data_sz,
435 size_t max_data_sz);
436
440
441 class Logger;
442
444 public:
445 RealmEntryExitRAII(Logger &_logger, const char *_func);
447
448 private:
449 Logger &logger;
450 const char *func = nullptr;
451 };
452
453#if REALM_DEFAULT_LOG_LEVEL > REALM_SPEW
454#define REALM_ENTRY_EXIT(logger) \
455 Realm::RealmEntryExitRAII __entry_exit(logger, __FUNCTION__)
456#else
457#define REALM_ENTRY_EXIT(logger)
458#endif
459
460}; // namespace Realm
461
462#include "realm/utils.inl"
463
464#endif // ifndef REALM_UTILS_H
bootstrap_handle_t * handle
Definition bootstrap.h:61
Definition utils.h:176
REALM_ALIGNED_TYPE_SAMEAS(Storage_aligned, Storage_unaligned, T)
const T & operator*() const
T * ptr
Definition utils.h:195
const T * operator->() const
Storage_aligned raw_storage
Definition utils.h:198
char Storage_unaligned[sizeof(T)]
Definition utils.h:196
Definition logging.h:52
Definition utils.h:273
const char * delim
Definition utils.h:286
PrettyVector(const T *_data, size_t _size, const char *_delim=", ", const char *_pfx="[", const char *_sfx="]")
size_t size
Definition utils.h:285
const T * data
Definition utils.h:284
const char * sfx
Definition utils.h:288
void print(std::ostream &os) const
const char * pfx
Definition utils.h:287
PrettyVector(const Container &_v, const char *_delim=", ", const char *_pfx="[", const char *_sfx="]")
Definition utils.h:443
RealmEntryExitRAII(Logger &_logger, const char *_func)
Definition utils.h:229
static const T MAXVAL
Definition utils.h:237
T & target
Definition utils.h:240
bitsliceref< BITFIELD > & operator=(T field)
bitsliceref< BITFIELD > & operator|=(T field)
Definition utils.h:244
const T & target
Definition utils.h:253
static const T MAXVAL
Definition utils.h:250
constbitsliceref(const T &_target)
Definition utils.h:217
bitsliceref< BITFIELD > slice()
T value
Definition utils.h:267
bitpack< T > & operator=(const bitpack< T > &copy_from)
bitpack< T > & operator=(T new_val)
constbitsliceref< BITFIELD > slice() const
bitpack(T init_val)
bitsliceref< BITFIELD > operator[](const BITFIELD &bitfield)
bitpack(const bitpack< T > &copy_from)
constbitsliceref< BITFIELD > operator[](const BITFIELD &bitfield) const
Definition utils.h:346
Definition utils.h:368
~noncopyable()
Definition utils.h:371
noncopyable()
Definition utils.h:370
Definition utils.h:120
static const size_t INTERNAL_BUFFER_SIZE
Definition utils.h:131
size_t size() const
char internal_buffer[INTERNAL_BUFFER_SIZE]
Definition utils.h:133
size_t external_buffer_size
Definition utils.h:135
virtual int_type overflow(int_type c)
const char * data() const
static const size_t INITIAL_EXTERNAL_BUFFER_SIZE
Definition utils.h:132
char * external_buffer
Definition utils.h:134
remove_const< T >::type value_type
Definition utils.h:304
T * data() const
Definition utils.h:337
T * base
Definition utils.h:342
span(T *_base, size_t _length)
Definition utils.h:311
span(T &v)
Definition utils.h:330
span()
Definition utils.h:307
T & operator[](size_t idx) const
Definition utils.h:335
span(const std::vector< typename remove_const< T >::type > &v)
Definition utils.h:324
size_t length
Definition utils.h:343
bool empty() const
Definition utils.h:339
span(span< T, Extent2 > copy_from)
Definition utils.h:318
size_t size() const
Definition utils.h:338
Definition utils.h:84
Definition utils.h:141
stringbuilder & operator<<(T data)
Definition utils.h:148
std::ostream os
Definition utils.h:156
stringbuilder()
Definition utils.h:143
shortstringbuf< 32, 64 > strbuf
Definition utils.h:155
#define REALM_INTERNAL_API_EXTERNAL_LINKAGE
Definition compiler_support.h:218
#define REALM_PUBLIC_API
Definition compiler_support.h:217
Definition activemsg.h:38
void delete_container_contents_free(std::map< K, V * > &m, bool clear_cont=true)
Definition utils.h:109
constexpr size_t hash_combine(size_t lhs, size_t rhs) noexcept
Definition utils.h:70
REALM_PUBLIC_API const char * realm_strerror(int err)
T checked_cast(T2 *ptr)
Definition utils.h:162
constexpr uint64_t hash_fnv1a(const char *s, size_t n, const uint64_t value=0xcbf29ce484222325ULL) noexcept
Definition utils.h:62
OsHandle ipc_mailbox_create(const std::string &name)
Creates an ipc mailbox useful for sending and receiving other OSHandles between ranks on the same phy...
bool ipc_mailbox_send(OsHandle mailbox, const std::string &to, const std::vector< OsHandle > &handles, const void *data, size_t data_sz)
Send the handles and data given via the mailbox created by ipc_mailbox_create to the receiving mailbo...
REALM_PUBLIC_API uint32_t crc32c_accumulate(uint32_t accum_in, const void *data, size_t len)
int OsHandle
Definition utils.h:399
void delete_container_contents(std::vector< T * > &v, bool clear_cont=true)
Definition utils.h:89
bool ipc_mailbox_recv(OsHandle mailbox, const std::string &from, std::vector< OsHandle > &handles, void *data, size_t &data_sz, size_t max_data_sz)
Receive in handles and data via the mailbox created by ipc_mailbox_create from the sending mailbox gi...
void call_destructor(T *obj)
Definition utils.h:383
const size_t dynamic_extent
Definition utils.h:81
unsigned ctz(uint64_t v)
std::ostream & operator<<(std::ostream &os, const DenseRectangleList< N, T > &drl)
void close_handle(OsHandle handle)
Close the given OS handle.
span< T, dynamic_extent > make_span(T *base, size_t length)
Definition utils.h:356
Definition utils.h:202
static const unsigned BITS
Definition utils.h:203
static const unsigned SHIFT
Definition utils.h:204
static T bit_or(T target, T field)
static T extract(T source)
static T insert(T target, T field)