source: NonGTP/Boost/boost/signals/slot.hpp @ 857

Revision 857, 5.1 KB checked in by igarcia, 18 years ago (diff)
Line 
1// Boost.Signals library
2
3// Copyright Douglas Gregor 2001-2004. Use, modification and
4// distribution is subject to the Boost Software License, Version
5// 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6// http://www.boost.org/LICENSE_1_0.txt)
7
8// For more information, see http://www.boost.org
9
10#ifndef BOOST_SIGNALS_SLOT_HEADER
11#define BOOST_SIGNALS_SLOT_HEADER
12
13#include <boost/signals/detail/signals_common.hpp>
14#include <boost/signals/connection.hpp>
15#include <boost/signals/trackable.hpp>
16#include <boost/visit_each.hpp>
17#include <boost/shared_ptr.hpp>
18#include <cassert>
19
20#ifdef BOOST_HAS_ABI_HEADERS
21#  include BOOST_ABI_PREFIX
22#endif
23
24namespace boost {
25  namespace BOOST_SIGNALS_NAMESPACE {
26    namespace detail {
27      class BOOST_SIGNALS_DECL slot_base {
28        // We would have to enumerate all of the signalN classes here as
29        // friends to make this private (as it otherwise should be). We can't
30        // name all of them because we don't know how many there are.
31      public:
32        struct data_t {
33          std::vector<const trackable*> bound_objects;
34          connection watch_bound_objects;
35        };
36        shared_ptr<data_t> get_data() const { return data; }
37
38        // Get the set of bound objects
39        std::vector<const trackable*>& get_bound_objects() const
40        { return data->bound_objects; }
41
42        // Determine if this slot is still "active", i.e., all of the bound
43        // objects still exist
44        bool is_active() const
45        { return data->watch_bound_objects.connected(); }
46
47      protected:
48        // Create a connection for this slot
49        void create_connection();
50
51        shared_ptr<data_t> data;
52
53      private:
54        static void bound_object_destructed(void*, void*) {}
55      };
56    } // end namespace detail
57
58    // Get the slot so that it can be copied
59    template<typename F>
60    reference_wrapper<const F>
61    get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag)
62      { return reference_wrapper<const F>(f); }
63
64    template<typename F>
65    const F&
66    get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag)
67      { return f; }
68
69    template<typename F>
70    const F&
71    get_invocable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag)
72      { return f; }
73
74    // Get the slot so that it can be inspected for trackable objects
75    template<typename F>
76    const F&
77    get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::signal_tag)
78      { return f; }
79
80    template<typename F>
81    const F&
82    get_inspectable_slot(const reference_wrapper<F>& f, BOOST_SIGNALS_NAMESPACE::detail::reference_tag)
83      { return f.get(); }
84
85    template<typename F>
86    const F&
87    get_inspectable_slot(const F& f, BOOST_SIGNALS_NAMESPACE::detail::value_tag)
88      { return f; }
89
90    // Determines the type of the slot - is it a signal, a reference to a
91    // slot or just a normal slot.
92    template<typename F>
93    typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag<F>::type
94    tag_type(const F&)
95    {
96      typedef typename BOOST_SIGNALS_NAMESPACE::detail::get_slot_tag<F>::type
97        the_tag_type;
98      the_tag_type tag = the_tag_type();
99      return tag;
100    }
101
102  } // end namespace BOOST_SIGNALS_NAMESPACE
103
104  template<typename SlotFunction>
105  class slot : public BOOST_SIGNALS_NAMESPACE::detail::slot_base {
106    typedef BOOST_SIGNALS_NAMESPACE::detail::slot_base inherited;
107    typedef typename inherited::data_t data_t;
108
109  public:
110    template<typename F>
111    slot(const F& f) : slot_function(BOOST_SIGNALS_NAMESPACE::get_invocable_slot(f, BOOST_SIGNALS_NAMESPACE::tag_type(f)))
112    {
113      this->data.reset(new data_t);
114
115      // Visit each of the bound objects and store them for later use
116      // An exception thrown here will allow the basic_connection to be
117      // destroyed when this goes out of scope, and no other connections
118      // have been made.
119      BOOST_SIGNALS_NAMESPACE::detail::bound_objects_visitor
120        do_bind(this->data->bound_objects);
121      visit_each(do_bind,
122                 BOOST_SIGNALS_NAMESPACE::get_inspectable_slot
123                   (f, BOOST_SIGNALS_NAMESPACE::tag_type(f)));
124      create_connection();
125    }
126
127#ifdef __BORLANDC__
128    template<typename F>
129    slot(F* f) : slot_function(f)
130    {
131      this->data.reset(new data_t);
132      create_connection();
133    }
134#endif // __BORLANDC__
135
136    // We would have to enumerate all of the signalN classes here as friends
137    // to make this private (as it otherwise should be). We can't name all of
138    // them because we don't know how many there are.
139  public:
140    // Get the slot function to call the actual slot
141    const SlotFunction& get_slot_function() const { return slot_function; }
142
143    void release() const { data->watch_bound_objects.set_controlling(false); }
144
145  private:
146    slot(); // no default constructor
147    slot& operator=(const slot&); // no assignment operator
148
149    SlotFunction slot_function;
150  };
151} // end namespace boost
152
153#ifdef BOOST_HAS_ABI_HEADERS
154#  include BOOST_ABI_SUFFIX
155#endif
156
157#endif // BOOST_SIGNALS_SLOT_HEADER
Note: See TracBrowser for help on using the repository browser.