summaryrefslogtreecommitdiffstats
blob: b4ed8b4736c06341d75bc8ee50403e19e3340775 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
// Boost.Signals library

// Copyright Douglas Gregor 2001-2004. Use, modification and
// distribution is subject to the Boost Software License, Version
// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

// For more information, see http://www.boost.org

#define BOOST_SIGNALS_SOURCE

#include <boost/signals/connection.hpp>
#include <cassert>

namespace boost {
  namespace BOOST_SIGNALS_NAMESPACE {

    connection::connection(const connection& other) :
      con(other.con), controlling_connection(other.controlling_connection)
    {
    }

    connection::~connection()
    {
      if (controlling_connection) {
        disconnect();
      }
    }

    void
    connection::reset(BOOST_SIGNALS_NAMESPACE::detail::basic_connection* new_con)
    {
      con.reset(new_con);
    }

    bool connection::operator==(const connection& other) const
    {
      return con.get() == other.con.get();
    }

    bool connection::operator<(const connection& other) const
    {
      return con.get() < other.con.get();
    }

    connection& connection::operator=(const connection& other)
    {
      connection(other).swap(*this);
      return *this;
    }

    void connection::swap(connection& other)
    {
      this->con.swap(other.con);
      std::swap(this->controlling_connection, other.controlling_connection);
    }

    void swap(connection& c1, connection& c2)
    {
      c1.swap(c2);
    }

    scoped_connection::scoped_connection(const connection& other) :
      connection(other),
      released(false)
    {
    }

    scoped_connection::scoped_connection(const scoped_connection& other) :
      connection(other),
      released(other.released)
    {
    }

    scoped_connection::~scoped_connection()
    {
      if (!released) {
        this->disconnect();
      }
    }

    connection scoped_connection::release()
    {
      released = true;
      return *this;
    }

    void scoped_connection::swap(scoped_connection& other)
    {
      this->connection::swap(other);
      bool other_released = other.released;
      other.released = this->released;
      this->released = other_released;
    }

    void swap(scoped_connection& c1, scoped_connection& c2)
    {
      c1.swap(c2);
    }

    scoped_connection&
    scoped_connection::operator=(const connection& other)
    {
      scoped_connection(other).swap(*this);
      return *this;
    }

    scoped_connection&
    scoped_connection::operator=(const scoped_connection& other)
    {
      scoped_connection(other).swap(*this);
      return *this;
    }

    void
    connection::add_bound_object(const BOOST_SIGNALS_NAMESPACE::detail::bound_object& b)
    {
      assert(con.get() != 0);
      con->bound_objects.push_back(b);
    }


    void connection::disconnect() const
    {
      if (this->connected()) {
        // Make sure we have a reference to the basic_connection object,
        // because 'this' may disappear
        shared_ptr<detail::basic_connection> local_con = con;

        void (*signal_disconnect)(void*, void*) = local_con->signal_disconnect;

        // Note that this connection no longer exists
        // Order is important here: we could get into an infinite loop if this
        // isn't cleared before we try the disconnect.
        local_con->signal_disconnect = 0;

        // Disconnect signal
        signal_disconnect(local_con->signal, local_con->signal_data);

        // Disconnect all bound objects
        typedef std::list<BOOST_SIGNALS_NAMESPACE::detail::bound_object>::iterator iterator;
        for (iterator i = local_con->bound_objects.begin();
             i != local_con->bound_objects.end(); ++i) {
          assert(i->disconnect != 0);
          i->disconnect(i->obj, i->data);
        }
      }
    }
  } // end namespace boost
} // end namespace boost

#ifndef BOOST_MSVC
// Explicit instantiations to keep everything in the library
template class std::list<boost::BOOST_SIGNALS_NAMESPACE::detail::bound_object>;
#endif