/* * Copyright © 2013 Canonical Ltd. * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License version 3, * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see . * * Authored by: Thomas Voß */ #ifndef WAITABLE_STATE_TRANSITION_H_ #define WAITABLE_STATE_TRANSITION_H_ #include #include #include #include namespace core { namespace testing { template struct WaitableStateTransition { WaitableStateTransition(const T& initial_state) : last_state(initial_state) { } bool wait_for_state_for(const T& expected_final_state, const std::chrono::milliseconds& duration) { std::unique_lock ul{mutex}; while (last_state != expected_final_state) { auto status = cv.wait_for(ul, duration); if (status == std::cv_status::timeout) return false; // In theory, this is not required. However, if executing under // valgrind and together with its single-threaded execution model, we // need to give up the timeslice here. // FIXME(tvoss): GCC 4.7 does not implement yield. // std::this_thread::yield(); } return true; } void trigger(const T& new_state) { std::lock_guard lg{mutex}; last_state = new_state; cv.notify_all(); } T last_state; std::mutex mutex; std::condition_variable cv; }; } } #endif // WAITABLE_STATE_TRANSITION_H_