]>
Commit | Line | Data |
---|---|---|
11fdf7f2 TL |
1 | /* |
2 | * This file is open source software, licensed to you under the terms | |
3 | * of the Apache License, Version 2.0 (the "License"). See the NOTICE file | |
4 | * distributed with this work for additional information regarding copyright | |
5 | * ownership. You may not use this file except in compliance with the License. | |
6 | * | |
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, | |
12 | * software distributed under the License is distributed on an | |
13 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | |
14 | * KIND, either express or implied. See the License for the | |
15 | * specific language governing permissions and limitations | |
16 | * under the License. | |
17 | */ | |
18 | /* | |
19 | * Copyright (C) 2015 Cloudius Systems, Ltd. | |
20 | */ | |
21 | ||
22 | #pragma once | |
23 | ||
24 | #include <mutex> | |
25 | #include <condition_variable> | |
26 | #include <seastar/util/std-compat.hh> | |
27 | ||
28 | namespace seastar { | |
29 | ||
30 | namespace testing { | |
31 | ||
f67539c2 TL |
32 | class exchanger_base { |
33 | protected: | |
34 | exchanger_base(); | |
35 | ~exchanger_base(); | |
11fdf7f2 TL |
36 | std::mutex _mutex; |
37 | std::condition_variable _cv; | |
11fdf7f2 | 38 | std::exception_ptr _exception; |
11fdf7f2 TL |
39 | void interrupt_ptr(std::exception_ptr e) { |
40 | std::unique_lock<std::mutex> lock(_mutex); | |
41 | if (!_exception) { | |
42 | _exception = e; | |
43 | _cv.notify_all(); | |
44 | } | |
45 | // FIXME: log if already interrupted | |
46 | } | |
f67539c2 TL |
47 | }; |
48 | ||
49 | // Single-element blocking queue | |
50 | template <typename T> | |
51 | class exchanger : public exchanger_base { | |
52 | private: | |
53 | std::optional<T> _element; | |
54 | ||
11fdf7f2 TL |
55 | public: |
56 | template <typename Exception> | |
57 | void interrupt(Exception e) { | |
58 | try { | |
59 | throw e; | |
60 | } catch (...) { | |
61 | interrupt_ptr(std::current_exception()); | |
62 | } | |
63 | } | |
64 | void give(T value) { | |
65 | std::unique_lock<std::mutex> lock(_mutex); | |
66 | _cv.wait(lock, [this] { return !_element || _exception; }); | |
67 | if (_exception) { | |
68 | std::rethrow_exception(_exception); | |
69 | } | |
70 | _element = value; | |
71 | _cv.notify_one(); | |
72 | } | |
73 | T take() { | |
74 | std::unique_lock<std::mutex> lock(_mutex); | |
75 | _cv.wait(lock, [this] { return bool(_element) || _exception; }); | |
76 | if (_exception) { | |
77 | std::rethrow_exception(_exception); | |
78 | } | |
79 | auto v = *_element; | |
80 | _element = {}; | |
81 | _cv.notify_one(); | |
82 | return v; | |
83 | } | |
84 | }; | |
85 | ||
86 | } | |
87 | ||
f67539c2 | 88 | } |