TYPE3
[iec.git] / src / type3_AndroidCloud / anbox-master / external / process-cpp-minimal / src / core / testing / cross_process_sync.cpp
1 /*
2  * Copyright © 2013 Canonical Ltd.
3  *
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 3 as
6  * published by the Free Software Foundation.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15  *
16  * Authored by: Thomas Voss <thomas.voss@canonical.com>
17  */
18
19 #include <core/testing/cross_process_sync.h>
20
21 #include <system_error>
22
23 #include <poll.h>
24 #include <unistd.h>
25
26 namespace
27 {
28 const int read_fd = 0;
29 const int write_fd = 1;
30 }
31
32 core::testing::CrossProcessSync::CrossProcessSync() : counter(0)
33 {
34     if (::pipe(fds) < 0)
35         throw std::system_error(errno, std::system_category());
36 }
37
38 core::testing::CrossProcessSync::CrossProcessSync(const CrossProcessSync& rhs) : counter(rhs.counter)
39 {
40     fds[0] = ::dup(rhs.fds[0]);
41     fds[1] = ::dup(rhs.fds[1]);
42 }
43
44 core::testing::CrossProcessSync::~CrossProcessSync() noexcept
45 {
46     ::close(fds[0]);
47     ::close(fds[1]);
48 }
49
50 core::testing::CrossProcessSync& core::testing::CrossProcessSync::operator=(const core::testing::CrossProcessSync& rhs)
51 {
52     ::close(fds[0]);
53     ::close(fds[1]);
54     fds[0] = ::dup(rhs.fds[0]);
55     fds[1] = ::dup(rhs.fds[1]);
56
57     counter = rhs.counter;
58
59     return *this;
60 }
61
62 void core::testing::CrossProcessSync::try_signal_ready_for(const std::chrono::milliseconds& duration)
63 {
64     static const short empty_revents = 0;
65     pollfd poll_fd[1] = { { fds[write_fd], POLLOUT, empty_revents } };
66     int rc = -1;
67
68     if ((rc = ::poll(poll_fd, 1, duration.count())) < 0)
69         throw std::system_error(errno, std::system_category());
70     else if (rc == 0)
71         throw Error::Timeout{};
72
73     static const std::uint32_t value = 1;
74     if (sizeof(value) != write(fds[write_fd], std::addressof(value), sizeof(value)))
75         throw std::system_error(errno, std::system_category());
76 }
77
78 std::uint32_t core::testing::CrossProcessSync::wait_for_signal_ready_for(const std::chrono::milliseconds& duration)
79 {
80     static const short empty_revents = 0;
81     pollfd poll_fd[1] = { { fds[read_fd], POLLIN, empty_revents } };
82     int rc = -1;
83
84     if ((rc = ::poll(poll_fd, 1, duration.count())) < 0)
85         throw std::system_error(errno, std::system_category());
86     else if (rc == 0)
87         throw Error::Timeout{};
88
89     std::uint32_t value = 0;
90     if (sizeof(value) != read(fds[read_fd], std::addressof(value), sizeof(value)))
91         throw std::system_error(errno, std::system_category());
92
93     if (value != 1)
94         throw std::system_error(errno, std::system_category());
95
96     counter += value;
97
98     return counter;
99 }