1 /*
2  * Copyright 2019 by its authors. See AUTHORS.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 ///
18 /// @file eo_wref.hh
19 ///
20 
21 #ifndef EFL_CXX_WREF_HH
22 #define EFL_CXX_WREF_HH
23 
24 #include <eina_optional.hh>
25 
26 #include "eo_ops.hh"
27 
28 namespace efl { namespace eo {
29 
30 /// @addtogroup Efl_Cxx_API
31 /// @{
32 
33 /// @brief Weak references to an <em>EO Object</em>.
34 ///
35 template<typename T>
36 struct wref
37 {
38    /// @brief Default constructor.
39    ///
40    /// Create a empty weak reference.
41    ///
wrefefl::eo::wref42    wref() : _eo_wref(nullptr)
43    {
44    }
45 
46    /// @brief Empty constructor on nullptr.
47    ///
48    /// Create a empty weak reference.
49    ///
wrefefl::eo::wref50    wref(std::nullptr_t) : _eo_wref(nullptr)
51    {
52    }
53 
54    /// @brief Class constructor.
55    ///
56    /// @param obj The <em>EO Object</em> to be referenced.
57    ///
58    /// Create a weak reference to @p obj.
59    ///
wrefefl::eo::wref60    explicit wref(Eo* obj) : _eo_wref(obj)
61    {
62       _add();
63    }
64 
65    /// @brief Class constructor.
66    ///
67    /// @param obj The <em>EO C++ Object</em> to be referenced.
68    ///
69    /// Create a weak reference to @p obj.
70    ///
wrefefl::eo::wref71    wref(T obj) : _eo_wref(obj._eo_ptr())
72    {
73       _add();
74    }
75 
76    /// @brief Class destructor.
77    ///
~wrefefl::eo::wref78    ~wref()
79    {
80       if(_eo_wref)
81         if(eina::optional<T> p = lock())
82           _del();
83    }
84 
85    /// @brief Try to acquire a strong reference to the underlying
86    /// <em>EO Object</em>.
87    ///
88    /// This function checks whether the weak reference still points to
89    /// a valid <em>EO Object</em>. If the reference is still valid it
90    /// increments the reference counter of the object and returns a
91    /// pointer to it.
92    ///
93    /// @return If the lock was successfully acquired it returns a
94    /// strong reference to the <em>EO Object</em>. Otherwise it returns
95    /// an empty eina::optional.
96    ///
lockefl::eo::wref97    eina::optional<T> lock() const
98    {
99       if(_eo_wref) // XXX eo_ref() should work on multi-threaded environments
100         {
101            detail::ref(_eo_wref);
102         }
103       else
104         {
105            return nullptr;
106         }
107       return T(_eo_wref);
108    }
109 
110    /// @brief Copy constructor.
111    ///
wrefefl::eo::wref112    wref(wref const& other)
113      : _eo_wref(other._eo_wref)
114    {
115       if(eina::optional<T> p = lock())
116         {
117            _add();
118         }
119       else
120         {
121            _eo_wref = 0;
122         }
123    }
124 
125    /// @brief Assignment operator.
126    ///
operator =efl::eo::wref127    wref& operator=(wref const& other)
128    {
129       _eo_wref = other._eo_wref;
130       if(eina::optional<T> p = lock())
131         {
132            _add();
133         }
134       else
135         {
136            _eo_wref = 0;
137         }
138       return *this;
139    }
140 
141 #ifdef EFL_CXXPERIMENTAL
operator ->efl::eo::wref142    T operator->() const {
143       if (!_eo_wref) return T(nullptr);
144       return T(detail::ref(_eo_wref));
145    }
146 
operator *efl::eo::wref147    T operator*() const {
148       if (!_eo_wref) return T(nullptr);
149       return T(detail::ref(_eo_wref));
150    }
151 #endif
152 
153    template <typename U>
operator ==efl::eo::wref154    bool operator == (U const &other) const
155    {
156       return other._eo_ptr() == _eo_wref;
157    }
158 
159    template <typename U>
operator ==(U const & other,wref<T> const & thiz)160    friend bool operator == (U const &other, wref<T> const &thiz)
161    {
162       return other._eo_ptr() == thiz._eo_wref;
163    }
164 
165 private:
_addefl::eo::wref166    void _add()
167    {
168       detail::wref_add(_eo_wref, &_eo_wref);
169    }
170 
_delefl::eo::wref171    void _del()
172    {
173       detail::wref_del(_eo_wref, &_eo_wref);
174    }
175 
176    Eo* _eo_wref; ///< The weak reference.
177 };
178 
179 /// @}
180 
181 } } // namespace efl { namespace eo {
182 
183 #endif // EFL_CXX_WREF_HH
184