CIRCT 20.0.0git
Loading...
Searching...
No Matches
Utils.h
Go to the documentation of this file.
1//===- Utils.h - ESI runtime utility code -----------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// DO NOT EDIT!
10// This file is distributed as part of an ESI package. The source for this file
11// should always be modified within CIRCT.
12//
13//===----------------------------------------------------------------------===//
14
15// NOLINTNEXTLINE(llvm-header-guard)
16#ifndef ESI_UTILS_H
17#define ESI_UTILS_H
18
19#include <cstdint>
20#include <functional>
21#include <mutex>
22#include <optional>
23#include <queue>
24#include <string>
25
26namespace esi {
27namespace utils {
28// Very basic base64 encoding.
29void encodeBase64(const void *data, size_t size, std::string &out);
30
31/// C++'s stdlib doesn't have a hash_combine function. This is a simple one.
32inline size_t hash_combine(size_t h1, size_t h2) {
33 return h1 + 0x9e3779b9 + (h2 << 6) + (h2 >> 2);
34}
35
36/// Thread safe queue. Just wraps std::queue protected with a lock. Long term,
37/// we need to avoid copying data. It has a lot of data copies currently.
38template <typename T>
39class TSQueue {
40 using Lock = std::lock_guard<std::mutex>;
41
42 /// The queue and its mutex.
43 mutable std::mutex qM;
44 std::queue<T> q;
45
46 /// A mutex to ensure that only one 'pop' operation is happening at a time. It
47 /// is critical that locks be obtained on this and `qM` same order in both pop
48 /// methods. This lock should be obtained first since one of the pop methods
49 /// must unlock `qM` then relock it.
50 std::mutex popM;
51
52public:
53 /// Push onto the queue.
54 template <typename... E>
55 void push(E... t) {
56 Lock l(qM);
57 q.emplace(t...);
58 }
59
60 /// Pop something off the queue but return nullopt if the queue is empty. Why
61 /// doesn't std::queue have anything like this?
62 std::optional<T> pop() {
63 Lock pl(popM);
64 Lock ql(qM);
65 if (q.size() == 0)
66 return std::nullopt;
67 auto t = q.front();
68 q.pop();
69 return t;
70 }
71
72 /// Call the callback for the front of the queue (if anything is there). Only
73 /// pop it off the queue if the callback returns true.
74 void pop(std::function<bool(const T &)> callback) {
75 // Since we need to unlock the mutex to call the callback, the queue
76 // could be pushed on to and its memory layout could thusly change,
77 // invalidating the reference returned by `.front()`. The easy solution here
78 // is to copy the data. TODO: Avoid copying the data.
79 Lock pl(popM);
80 T t;
81 {
82 Lock l(qM);
83 if (q.size() == 0)
84 return;
85 t = q.front();
86 }
87 if (callback(t)) {
88 Lock l(qM);
89 q.pop();
90 }
91 }
92
93 /// Is the queue empty?
94 bool empty() const {
95 Lock l(qM);
96 return q.empty();
97 }
98};
99} // namespace utils
100} // namespace esi
101
102#endif // ESI_UTILS_H
Thread safe queue.
Definition Utils.h:39
std::mutex qM
The queue and its mutex.
Definition Utils.h:43
std::mutex popM
A mutex to ensure that only one 'pop' operation is happening at a time.
Definition Utils.h:50
std::queue< T > q
Definition Utils.h:44
bool empty() const
Is the queue empty?
Definition Utils.h:94
void push(E... t)
Push onto the queue.
Definition Utils.h:55
std::lock_guard< std::mutex > Lock
Definition Utils.h:40
void pop(std::function< bool(const T &)> callback)
Call the callback for the front of the queue (if anything is there).
Definition Utils.h:74
std::optional< T > pop()
Pop something off the queue but return nullopt if the queue is empty.
Definition Utils.h:62
void encodeBase64(const void *data, size_t size, std::string &out)
Definition Utils.cpp:23
size_t hash_combine(size_t h1, size_t h2)
C++'s stdlib doesn't have a hash_combine function. This is a simple one.
Definition Utils.h:32
Definition esi.py:1