1 //******************************************************************
3 // Copyright 2015 Samsung Electronics All Rights Reserved.
5 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
7 // Licensed under the Apache License, Version 2.0 (the "License");
8 // you may not use this file except in compliance with the License.
9 // You may obtain a copy of the License at
11 // http://www.apache.org/licenses/LICENSE-2.0
13 // Unless required by applicable law or agreed to in writing, software
14 // distributed under the License is distributed on an "AS IS" BASIS,
15 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 // See the License for the specific language governing permissions and
17 // limitations under the License.
19 //-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
21 #ifndef IOTY_GTEST_HELPER_H
22 #define IOTY_GTEST_HELPER_H
26 #include <condition_variable>
36 * Simple implementation of a deadman's timer that can be used to
37 * terminate a test that hangs.
39 * Since there is no standard way to terminate an individual thread,
40 * the entire process will be killed once time has been exceeded.
42 * @note provisions for watchdog thread cleanup are not currently added.
43 * Testing has not yet shown any need for such complexity.
50 * Creates an instance of a timer set to kill the running process
51 * after the specified timeout.
53 * If the destructor is invoked before time is up (aka this instance
54 * goes out of scope) the timeout will not cause the program to be
57 * @param time to wait before assuming the process is hung and must be
59 * Examples of values that can be passed include
60 * std::chrono::milliseconds(250), std::chrono::seconds(5),
61 * std::chrono::minutes(3).
63 DeadmanTimer(std::chrono::milliseconds timeout) :
64 m_ctx(new DeadmanCtx(timeout)),
67 m_thread = std::thread([this](){run(m_ctx);});
69 std::unique_lock<std::mutex> lock(m_ctx->m_mutex);
70 while (!m_ctx->m_isArmed)
72 m_ctx->m_cond.wait(lock);
75 // Now that the thread is live, we can stop tracking it.
80 * Destructor that also will cancel the termination of the
85 std::unique_lock<std::mutex> lock(m_ctx->m_mutex);
86 m_ctx->m_isArmed = false;
92 * Shared data that main and child thread might both need to
95 * Avoids referencing data in class instances that have been
102 DeadmanCtx(std::chrono::milliseconds timeout) :
111 std::condition_variable m_cond;
113 std::chrono::milliseconds m_timeout;
116 // Explicitly block assignment and copy ctor
117 DeadmanTimer &operator=(const DeadmanTimer &rhs);
118 DeadmanTimer(const iotivity::test::DeadmanTimer &rhs);
120 std::shared_ptr<DeadmanCtx> m_ctx;
121 std::thread m_thread;
124 static void run(std::shared_ptr<DeadmanCtx> ctx)
126 // Let the calling thread know it can stop waiting:
128 std::unique_lock<std::mutex> lock(ctx->m_mutex);
129 ctx->m_isArmed = true;
130 ctx->m_cond.notify_all();
133 std::this_thread::sleep_for(ctx->m_timeout);
135 std::unique_lock<std::mutex> lock(ctx->m_mutex);
139 throw std::runtime_error("deadman timer expired");
141 catch (std::exception&)
149 } // namespace iotivity
151 #endif // IOTY_GTEST_HELPER_H