~ubuntu-branches/ubuntu/wily/mir/wily-proposed

« back to all changes in this revision

Viewing changes to src/common/thread/recursive_read_write_mutex.cpp

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-10-10 14:01:26 UTC
  • mto: This revision was merged to the branch mainline in revision 84.
  • Revision ID: package-import@ubuntu.com-20141010140126-n1czko8na1kuz4ll
Tags: upstream-0.8.0+14.10.20141010
Import upstream version 0.8.0+14.10.20141010

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright © 2014 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: Alan Griffiths <alan@octopull.co.uk>
 
17
 */
 
18
 
 
19
#include "mir/recursive_read_write_mutex.h"
 
20
 
 
21
#include <algorithm>
 
22
 
 
23
void mir::RecursiveReadWriteMutex::read_lock()
 
24
{
 
25
    auto const my_id = std::this_thread::get_id();
 
26
 
 
27
    std::unique_lock<decltype(mutex)> lock{mutex};
 
28
    cv.wait(lock, [&]{
 
29
        return !write_locking_thread.count ||
 
30
            write_locking_thread.id == my_id; });
 
31
 
 
32
    auto const my_count = std::find_if(
 
33
        read_locking_threads.begin(),
 
34
        read_locking_threads.end(),
 
35
        [my_id](ThreadLockCount const& candidate) { return my_id == candidate.id; });
 
36
 
 
37
    if (my_count == read_locking_threads.end())
 
38
    {
 
39
        read_locking_threads.push_back(ThreadLockCount(my_id, 1U));
 
40
    }
 
41
    else
 
42
    {
 
43
        ++(my_count->count);
 
44
    }
 
45
}
 
46
 
 
47
void mir::RecursiveReadWriteMutex::read_unlock()
 
48
{
 
49
    auto const my_id = std::this_thread::get_id();
 
50
 
 
51
    std::lock_guard<decltype(mutex)> lock{mutex};
 
52
    auto const my_count = std::find_if(
 
53
        read_locking_threads.begin(),
 
54
        read_locking_threads.end(),
 
55
        [my_id](ThreadLockCount const& candidate) { return my_id == candidate.id; });
 
56
 
 
57
    --(my_count->count);
 
58
 
 
59
    cv.notify_all();
 
60
}
 
61
 
 
62
void mir::RecursiveReadWriteMutex::write_lock()
 
63
{
 
64
    auto const my_id = std::this_thread::get_id();
 
65
 
 
66
    std::unique_lock<decltype(mutex)> lock{mutex};
 
67
    cv.wait(lock, [&]
 
68
        {
 
69
            if (write_locking_thread.count &&
 
70
                write_locking_thread.id != my_id) return false;
 
71
            for (auto const& candidate : read_locking_threads)
 
72
            {
 
73
                if (candidate.id != my_id && candidate.count != 0) return false;
 
74
            }
 
75
            return true;
 
76
        });
 
77
 
 
78
    ++write_locking_thread.count;
 
79
    write_locking_thread.id = my_id;
 
80
}
 
81
 
 
82
void mir::RecursiveReadWriteMutex::write_unlock()
 
83
{
 
84
    std::lock_guard<decltype(mutex)> lock{mutex};
 
85
    --write_locking_thread.count;
 
86
    cv.notify_all();
 
87
}