summaryrefslogtreecommitdiff
path: root/src/bindings/cxx/eo_cxx/eo_wref.hh
blob: aed6d699d0afb073db3c9465838966ca185d9a0c (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
167
168

///
/// @file eo_wref.hh
///

#ifndef EFL_CXX_WREF_HH
#define EFL_CXX_WREF_HH

#include <eina_optional.hh>

#include "eo_ops.hh"

namespace efl { namespace eo {

/// @addtogroup Efl_Cxx_API
/// @{

/// @brief Weak references to an <em>EO Object</em>.
///
template<typename T>
struct wref
{
   /// @brief Default constructor.
   ///
   /// Create a empty weak reference.
   ///
   wref() : _eo_wref(nullptr)
   {
   }

   /// @brief Empty constructor on nullptr.
   ///
   /// Create a empty weak reference.
   ///
   wref(std::nullptr_t) : _eo_wref(nullptr)
   {
   }
  
   /// @brief Class constructor.
   ///
   /// @param obj The <em>EO Object</em> to be referenced.
   ///
   /// Create a weak reference to @p obj.
   ///
   explicit wref(Eo* obj) : _eo_wref(obj)
   {
      _add();
   }

   /// @brief Class constructor.
   ///
   /// @param obj The <em>EO C++ Object</em> to be referenced.
   ///
   /// Create a weak reference to @p obj.
   ///
   wref(T obj) : _eo_wref(obj._eo_ptr())
   {
      _add();
   }

   /// @brief Class destructor.
   ///
   ~wref()
   {
      if(_eo_wref)
        if(eina::optional<T> p = lock())
          _del();
   }

   /// @brief Try to acquire a strong reference to the underlying
   /// <em>EO Object</em>.
   ///
   /// This function checks whether the weak reference still points to
   /// a valid <em>EO Object</em>. If the reference is still valid it
   /// increments the reference counter of the object and returns a
   /// pointer to it.
   ///
   /// @return If the lock was successfully acquired it returns a
   /// strong reference to the <em>EO Object</em>. Otherwise it returns
   /// an empty eina::optional.
   ///
   eina::optional<T> lock() const
   {
      if(_eo_wref) // XXX eo_ref() should work on multi-threaded environments
        {
           detail::ref(_eo_wref);
        }
      else
        {
           return nullptr;
        }
      return T(_eo_wref);
   }

   /// @brief Copy constructor.
   ///
   wref(wref const& other)
     : _eo_wref(other._eo_wref)
   {
      if(eina::optional<T> p = lock())
        {
           _add();
        }
      else
        {
           _eo_wref = 0;
        }
   }

   /// @brief Assignment operator.
   ///
   wref& operator=(wref const& other)
   {
      _eo_wref = other._eo_wref;
      if(eina::optional<T> p = lock())
        {
           _add();
        }
      else
        {
           _eo_wref = 0;
        }
      return *this;
   }

#ifdef EFL_CXXPERIMENTAL
   T operator->() const {
      if (!_eo_wref) return T(nullptr);
      return T(detail::ref(_eo_wref));
   }

   T operator*() const {
      if (!_eo_wref) return T(nullptr);
      return T(detail::ref(_eo_wref));
   }
#endif

   template <typename U>
   bool operator == (U const &other) const
   {
      return other._eo_ptr() == _eo_wref;
   }

   template <typename U>
   friend bool operator == (U const &other, wref<T> const &thiz)
   {
      return other._eo_ptr() == thiz._eo_wref;
   }

private:
   void _add()
   {
      detail::wref_add(_eo_wref, &_eo_wref);
   }

   void _del()
   {
      detail::wref_del(_eo_wref, &_eo_wref);
   }

   Eo* _eo_wref; ///< The weak reference.
};

/// @}

} } // namespace efl { namespace eo {

#endif // EFL_CXX_WREF_HH