~alan-griffiths/mir/fix-1654023

« back to all changes in this revision

Viewing changes to src/common/dispatch/action_queue.cpp

  • Committer: Daniel van Vugt
  • Date: 2015-04-28 07:54:10 UTC
  • mfrom: (2517 development-branch)
  • mto: This revision was merged to the branch mainline in revision 2673.
  • Revision ID: daniel.van.vugt@canonical.com-20150428075410-rwskshfuar7voesp
Merge latest trunk and fix conflicts.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2015 Canonical Ltd.
 
3
 *
 
4
 * This program is free software: you can redistribute it and/or modify it
 
5
 * under the terms of the GNU Lesser General Public License version 3,
 
6
 * as 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 Lesser General Public License for more details.
 
12
 *
 
13
 * You should have received a copy of the GNU Lesser General Public License
 
14
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
15
 *
 
16
 * Authored by: Andreas Pokorny <andreas.pokorny@canonical.com>
 
17
 */
 
18
 
 
19
#include "mir/dispatch/action_queue.h"
 
20
 
 
21
#include <boost/throw_exception.hpp>
 
22
#include <sys/eventfd.h>
 
23
 
 
24
mir::dispatch::ActionQueue::ActionQueue()
 
25
    : event_fd{eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK)}
 
26
{
 
27
    if (event_fd < 0)
 
28
        BOOST_THROW_EXCEPTION((std::system_error{errno,
 
29
                                                 std::system_category(),
 
30
                                                 "Failed to create event fd for action queue"}));
 
31
}
 
32
 
 
33
mir::Fd mir::dispatch::ActionQueue::watch_fd() const
 
34
{
 
35
    return event_fd;
 
36
}
 
37
 
 
38
void mir::dispatch::ActionQueue::enqueue(std::function<void()> const& action)
 
39
{
 
40
    std::unique_lock<std::mutex> lock(list_lock);
 
41
    actions.push_back(action);
 
42
    wake();
 
43
}
 
44
 
 
45
bool mir::dispatch::ActionQueue::dispatch(FdEvents events)
 
46
{
 
47
    if (events&FdEvent::error)
 
48
        return false;
 
49
 
 
50
    std::list<std::function<void()>> actions_to_process;
 
51
 
 
52
    {
 
53
        std::unique_lock<std::mutex> lock(list_lock);
 
54
        consume();
 
55
        std::swap(actions_to_process, actions);
 
56
    }
 
57
 
 
58
    while(!actions_to_process.empty())
 
59
    {
 
60
        actions_to_process.front()();
 
61
        actions_to_process.pop_front();
 
62
    }
 
63
    return true;
 
64
}
 
65
 
 
66
mir::dispatch::FdEvents mir::dispatch::ActionQueue::relevant_events() const
 
67
{
 
68
    return FdEvent::readable;
 
69
}
 
70
 
 
71
void mir::dispatch::ActionQueue::consume()
 
72
{
 
73
    uint64_t num_actions;
 
74
    if (read(event_fd, &num_actions, sizeof num_actions) != sizeof num_actions)
 
75
        BOOST_THROW_EXCEPTION((std::system_error{errno,
 
76
                                                 std::system_category(),
 
77
                                                 "Failed to consume action queue notification"}));
 
78
}
 
79
 
 
80
void mir::dispatch::ActionQueue::wake()
 
81
{
 
82
    uint64_t one_more{1};
 
83
    if (write(event_fd, &one_more, sizeof one_more) != sizeof one_more)
 
84
        BOOST_THROW_EXCEPTION((std::system_error{errno,
 
85
                                                 std::system_category(),
 
86
                                                 "Failed to wake action queue"}));
 
87
}