116 lines
3.6 KiB
C++
116 lines
3.6 KiB
C++
// Copyright (2019-2023) Paul Scherrer Institute
|
|
|
|
// Based on hls_stream.h from Xilinx VITIS HLS 2023.1
|
|
|
|
// (c) Copyright 2011-2022 Xilinx, Inc.
|
|
// All Rights Reserved.
|
|
//
|
|
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
#ifndef JUNGFRAUJOCH_PARALLEL_STREAM_H
|
|
#define JUNGFRAUJOCH_PARALLEL_STREAM_H
|
|
|
|
#include <cstddef>
|
|
#include <queue>
|
|
#include <mutex>
|
|
#include <condition_variable>
|
|
#include <chrono>
|
|
|
|
namespace hls {
|
|
template<class T, int DEPTH=0> class stream;
|
|
|
|
template<class T> class stream<T, 0> {
|
|
private:
|
|
mutable std::mutex m;
|
|
std::condition_variable c_empty;
|
|
std::condition_variable c_full;
|
|
std::queue<T> data;
|
|
std::chrono::seconds timeout;
|
|
size_t max_elements;
|
|
|
|
void internal_read(T& head) {
|
|
head = data.front();
|
|
data.pop();
|
|
c_full.notify_one();
|
|
}
|
|
void internal_write(const T& tail) {
|
|
data.push(tail);
|
|
c_empty.notify_one();
|
|
}
|
|
public:
|
|
explicit stream(size_t nelem = UINT64_MAX, std::chrono::seconds blocking_timeout = std::chrono::minutes(15))
|
|
: max_elements(nelem), data(), timeout(blocking_timeout) {};
|
|
|
|
void write(const T& tail) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
while (data.size() >= max_elements) {
|
|
if (c_full.wait_for(ul, timeout)
|
|
== std::cv_status::timeout)
|
|
throw std::runtime_error("Likely deadlock");
|
|
}
|
|
internal_write(tail);
|
|
}
|
|
|
|
bool write_nb(const T& tail) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (data.size() >= max_elements) return false;
|
|
internal_write(tail);
|
|
return true;
|
|
}
|
|
|
|
bool read_nb(T& head) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
if (data.empty()) return false;
|
|
internal_read(head);
|
|
return true;
|
|
}
|
|
|
|
void read(T& head) {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
while (data.empty()) {
|
|
if (c_empty.wait_for(ul, timeout)
|
|
== std::cv_status::timeout)
|
|
throw std::runtime_error("Likely deadlock");
|
|
}
|
|
internal_read(head);
|
|
}
|
|
|
|
bool full() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
return (data.size() >= max_elements);
|
|
}
|
|
|
|
bool empty() const {
|
|
std::unique_lock<std::mutex> ul(m);
|
|
return data.empty();
|
|
};
|
|
|
|
size_t size() const { return data.size(); };
|
|
void operator >> (T& rval) { read(rval); }
|
|
void operator << (const T& rval) { write(rval); }
|
|
T read() { T ret; read(ret); return ret; }
|
|
};
|
|
|
|
template<class T, int DEPTH> class stream : public stream<T> {
|
|
public:
|
|
stream() : stream<T>(DEPTH) {}
|
|
};
|
|
}
|
|
|
|
#endif //JUNGFRAUJOCH_PARALLEL_STREAM_H
|