CIRCT  20.0.0git
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 
26 namespace esi {
27 namespace utils {
28 // Very basic base64 encoding.
29 void 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.
32 inline 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.
38 template <typename T>
39 class 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 
52 public:
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
std::optional< T > pop()
Pop something off the queue but return nullopt if the queue is empty.
Definition: Utils.h:62
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
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