summaryrefslogtreecommitdiff
path: root/libs/signals2/test/track_test.cpp
blob: a19c1e105eb76492f924dcc43be2686d63086b2f (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
156
157
158
159
160
161
162
163
164
165
166
// Boost.Signals library

// Copyright Douglas Gregor 2001-2006
// Copyright Frank Mori Hess 2007
// 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

#include <memory>
#include <boost/optional.hpp>
#include <boost/ref.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/test/minimal.hpp>
#include <boost/signals2.hpp>
#include <boost/bind.hpp>

struct swallow {
  typedef int result_type;
  template<typename T> result_type operator()(const T*, int i) { return i; }
};

template<typename T>
struct max_or_default {
  typedef T result_type;

  template<typename InputIterator>
  T operator()(InputIterator first, InputIterator last) const
  {
    boost::optional<T> max;
    for(; first != last; ++first)
    {
      T value = *first;
      if(!max)
      {
        max = value;
      }else if(value > *max)
      {
        max = value;
      }
    }
    if(max) return *max;
    else return T();
  }
};

static int myfunc(int i, double z)
{
  return i;
}

int test_main(int, char*[])
{
  typedef boost::signals2::signal<int (int), max_or_default<int> > sig_type;
  sig_type s1;
  boost::signals2::connection connection;

  // Test auto-disconnection
  BOOST_CHECK(s1(5) == 0);
  {
    boost::shared_ptr<int> shorty(new int());
    s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track(shorty));
    BOOST_CHECK(s1(5) == 5);
  }
  BOOST_CHECK(s1(5) == 0);

  // Test auto-disconnection of slot before signal connection
  {
    boost::shared_ptr<int> shorty(new int(1));
// doesn't work on gcc 3.3.5, it says: error: type specifier omitted for parameter `shorty'
// does work on gcc 4.1.2
//    sig_type::slot_type slot(swallow(), shorty.get(), _1);
    swallow myswallow;
    sig_type::slot_type slot(myswallow, shorty.get(), _1);

    slot.track(shorty);
    shorty.reset();
    s1.connect(slot);
    BOOST_CHECK(s1(5) == 0);
  }

  // Test binding of a slot to another slot
  {
    boost::shared_ptr<int> shorty(new int(2));
    boost::signals2::slot<int (double)> other_slot(&myfunc, boost::cref(*shorty.get()), _1);
    other_slot.track(shorty);
    connection = s1.connect(sig_type::slot_type(other_slot, 0.5).track(other_slot));
    BOOST_CHECK(s1(3) == 2);
  }
  BOOST_CHECK(connection.connected() == false);
  BOOST_CHECK(s1(3) == 0);

  // Test binding of a signal as a slot
  {
    sig_type s2;
    s1.connect(s2);
    s2.connect(sig_type::slot_type(&myfunc, _1, 0.7));
    BOOST_CHECK(s1(4) == 4);
  }
  BOOST_CHECK(s1(4) == 0);

  // Test tracking of null but not empty shared_ptr
  BOOST_CHECK(s1(2) == 0);
  {
    boost::shared_ptr<int> shorty((int*)(0));
    s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track(shorty));
    BOOST_CHECK(s1(2) == 2);
  }
  BOOST_CHECK(s1(2) == 0);

#ifndef BOOST_NO_CXX11_SMART_PTR
  // Test tracking through std::shared_ptr/weak_ptr
  BOOST_CHECK(s1(5) == 0);
  {
    std::shared_ptr<int> shorty(new int());
    s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track_foreign(shorty));
    BOOST_CHECK(s1(5) == 5);
  }
  BOOST_CHECK(s1(5) == 0);
  {
    std::shared_ptr<int> shorty(new int());
    s1.connect
    (
      sig_type::slot_type
      (
        swallow(),
        shorty.get(),
        _1
      ).track_foreign
      (
        std::weak_ptr<int>(shorty)
      )
    );
    BOOST_CHECK(s1(5) == 5);
  }
  BOOST_CHECK(s1(5) == 0);
  // make sure tracking foreign shared_ptr<const void> works
  {
    std::shared_ptr<const void> shorty(new int());
    s1.connect(sig_type::slot_type(swallow(), shorty.get(), _1).track_foreign(shorty));
    BOOST_CHECK(s1(5) == 5);
  }
  {
    std::shared_ptr<int> shorty(new int());
    s1.connect
    (
      sig_type::slot_type
      (
        swallow(),
        shorty.get(),
        _1
      ).track_foreign
      (
        std::weak_ptr<const void>(shorty)
      )
    );
    BOOST_CHECK(s1(5) == 5);
  }
  BOOST_CHECK(s1(5) == 0);
  BOOST_CHECK(s1(5) == 0);
#endif

  return 0;
}