~unity-system-compositor-team/unity-system-compositor/no-change-rebuild-0.2

« back to all changes in this revision

Viewing changes to tests/unit-tests/advanceable_timer.cpp

  • Committer: Tarmac
  • Author(s): Alexandros Frantzis
  • Date: 2015-09-25 13:24:13 UTC
  • mfrom: (252.1.2 fix-1491566-deadlock)
  • Revision ID: tarmac-20150925132413-tbj9h3q8bpcd7iss
Fix deadlock by ensuring our alarm handlers acquire locks in the correct order. Fixes: https://bugs.launchpad.net/bugs/1491566.

Approved by Andreas Pokorny, PS Jenkins bot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 */
18
18
 
19
19
#include "advanceable_timer.h"
 
20
#include <mir/lockable_callback.h>
20
21
#include <algorithm>
21
22
 
22
23
namespace
59
60
{
60
61
    AdvanceableAlarm(
61
62
        mir::time::Timestamp now,
62
 
        std::function<void(void)> const& callback)
 
63
        std::shared_ptr<mir::LockableCallback> const& callback)
63
64
        : now{now}, callback{callback}
64
65
    {
65
66
    }
101
102
        {
102
103
            state_ = mir::time::Alarm::triggered;
103
104
            lock.unlock();
104
 
            callback();
 
105
            callback->lock();
 
106
            (*callback)();
 
107
            callback->unlock();
105
108
        }
106
109
    }
107
110
 
113
116
 
114
117
private:
115
118
    mir::time::Timestamp now;
116
 
    std::function<void()> const callback;
 
119
    std::shared_ptr<mir::LockableCallback> const callback;
117
120
    mir::time::Timestamp next_trigger_;
118
121
    mutable std::mutex mutex;
119
122
    mir::time::Alarm::State state_ = mir::time::Alarm::triggered;
123
126
std::unique_ptr<mir::time::Alarm> AdvanceableTimer::create_alarm(
124
127
    std::function<void()> const& callback)
125
128
{
 
129
    struct SimpleLockableCallback : public mir::LockableCallback
 
130
    {
 
131
        SimpleLockableCallback(std::function<void()> const& callback)
 
132
            : callback{callback}
 
133
        {
 
134
        }
 
135
 
 
136
        void operator()() override { callback(); }
 
137
        void lock() override {}
 
138
        void unlock() override {}
 
139
 
 
140
        std::function<void()> const callback;
 
141
    };
 
142
 
 
143
    return create_alarm(std::make_shared<SimpleLockableCallback>(callback));
 
144
}
 
145
 
 
146
std::unique_ptr<mir::time::Alarm> AdvanceableTimer::create_alarm(
 
147
    std::shared_ptr<mir::LockableCallback> const& callback)
 
148
{
126
149
    auto const adv_alarm =
127
150
        std::make_shared<detail::AdvanceableAlarm>(now(), callback);
128
151
 
131
154
    return std::unique_ptr<AlarmWrapper>(new AlarmWrapper{adv_alarm});
132
155
}
133
156
 
134
 
std::unique_ptr<mir::time::Alarm> AdvanceableTimer::create_alarm(
135
 
    std::shared_ptr<mir::LockableCallback> const&)
136
 
{
137
 
    throw std::runtime_error("Not implemented");
138
 
}
139
 
 
140
157
void AdvanceableTimer::advance_by(std::chrono::milliseconds advance)
141
158
{
142
159
    {