1 //  Copyright (c)      2014 Thomas Heller
2 //  Copyright (c) 2007-2017 Hartmut Kaiser
3 //  Copyright (c) 2007 Richard D. Guidry Jr.
4 //
5 //  Distributed under the Boost Software License, Version 1.0. (See accompanying
6 //  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 
8 #if !defined(HPX_PARCELSET_LOCALITY_HPP)
9 #define HPX_PARCELSET_LOCALITY_HPP
10 
11 #include <hpx/config.hpp>
12 
13 #include <hpx/exception.hpp>
14 #include <hpx/runtime/parcelset_fwd.hpp>
15 #include <hpx/runtime/serialization/serialization_fwd.hpp>
16 #include <hpx/runtime/serialization/map.hpp>
17 #include <hpx/traits/is_iterator.hpp>
18 #include <hpx/util/assert.hpp>
19 
20 #include <map>
21 #include <memory>
22 #include <string>
23 #include <type_traits>
24 #include <utility>
25 
26 #include <hpx/config/warnings_prefix.hpp>
27 
28 ///////////////////////////////////////////////////////////////////////////////
29 namespace hpx { namespace parcelset
30 {
31     class HPX_EXPORT locality
32     {
33         template <typename Impl>
34         class impl;
35 
36         class impl_base
37         {
38         public:
~impl_base()39             virtual ~impl_base() {}
40 
41             virtual bool equal(impl_base const & rhs) const = 0;
42             virtual bool less_than(impl_base const & rhs) const = 0;
43             virtual bool valid() const = 0;
44             virtual const char *type() const = 0;
45             virtual std::ostream & print(std::ostream & os) const = 0;
46             virtual void save(serialization::output_archive & ar) const = 0;
47             virtual void load(serialization::input_archive & ar) = 0;
48             virtual impl_base * clone() const = 0;
49             virtual impl_base * move() = 0;
50 
51             template <typename Impl>
get()52             Impl & get()
53             {
54                 HPX_ASSERT(Impl::type() == type());
55                 return static_cast<impl<Impl>*>(this)->impl_;
56             }
57 
58             template <typename Impl>
get() const59             Impl const & get() const
60             {
61                 HPX_ASSERT(Impl::type() == type());
62                 return static_cast<const impl<Impl>*>(this)->impl_;
63             }
64         };
65 
66     public:
locality()67         locality()
68         {}
69 
70         template <typename Impl, typename Enable =
71             typename std::enable_if<
72                !std::is_same<locality, typename util::decay<Impl>::type>::value &&
73                !traits::is_iterator<Impl>::value
74             >::type
75         >
locality(Impl && i)76         locality(Impl && i)
77           : impl_(new impl<typename util::decay<Impl>::type>(std::forward<Impl>(i)))
78         {}
79 
locality(locality const & other)80         locality(locality const & other)
81           : impl_(other.impl_ ? other.impl_->clone() : nullptr)
82         {
83         }
84 
locality(locality && other)85         locality(locality && other)
86           : impl_(other.impl_ ? other.impl_->move() : nullptr)
87         {
88         }
89 
operator =(locality const & other)90         locality & operator=(locality const & other)
91         {
92             if(this != &other)
93             {
94                 if(other.impl_)
95                 {
96                     impl_.reset(other.impl_->clone());
97                 }
98                 else
99                 {
100                     impl_.reset();
101                 }
102             }
103             return *this;
104         }
105 
operator =(locality && other)106         locality & operator=(locality && other)
107         {
108             if(this != &other)
109             {
110                 if(other.impl_)
111                 {
112                     impl_.reset(other.impl_->move());
113                 }
114                 else
115                 {
116                     impl_.reset();
117                 }
118             }
119             return *this;
120         }
121 
122         ///////////////////////////////////////////////////////////////////////
operator bool() const123         explicit operator bool() const noexcept
124         {
125             return impl_ ? impl_->valid(): false;
126         }
127 
type() const128         const char *type() const
129         {
130             return impl_ ? impl_->type() : "";
131         }
132 
133         template <typename Impl>
get()134         Impl & get()
135         {
136             HPX_ASSERT(impl_);
137             return impl_->get<Impl>();
138         }
139 
140         template <typename Impl>
get() const141         Impl const & get() const
142         {
143             HPX_ASSERT(impl_);
144             return impl_->get<Impl>();
145         }
146 
147     private:
operator ==(locality const & lhs,locality const & rhs)148         friend bool operator==(locality const& lhs, locality const& rhs)
149         {
150             if(lhs.impl_ == rhs.impl_) return true;
151             if(!lhs.impl_ || !rhs.impl_) return false;
152             return lhs.impl_->equal(*rhs.impl_);
153         }
154 
operator !=(locality const & lhs,locality const & rhs)155         friend bool operator!=(locality const& lhs, locality const& rhs)
156         {
157             return !(lhs == rhs);
158         }
159 
operator <(locality const & lhs,locality const & rhs)160         friend bool operator< (locality const& lhs, locality const& rhs)
161         {
162             if(lhs.impl_ == rhs.impl_) return false;
163             if(!lhs.impl_ || ! rhs.impl_) return false;
164             return lhs.impl_->less_than(*rhs.impl_);
165         }
166 
operator >(locality const & lhs,locality const & rhs)167         friend bool operator> (locality const& lhs, locality const& rhs)
168         {
169             if(lhs.impl_ == rhs.impl_) return false;
170             if(!lhs.impl_ || ! rhs.impl_) return false;
171             return !(lhs < rhs) && !(lhs == rhs);
172         }
173 
operator <<(std::ostream & os,locality const & l)174         friend std::ostream& operator<< (std::ostream& os, locality const& l)
175         {
176             if(!l.impl_) return os;
177             return l.impl_->print(os);
178         }
179 
180         // serialization support
181         friend class hpx::serialization::access;
182 
183         void save(serialization::output_archive& ar, const unsigned int version) const;
184 
185         void load(serialization::input_archive& ar, const unsigned int version);
186 
187         HPX_SERIALIZATION_SPLIT_MEMBER();
188 
189         std::unique_ptr<impl_base> impl_;
190 
191         template <typename Impl>
192         class impl : public impl_base
193         {
194         public:
impl(Impl && i)195             explicit impl(Impl && i) : impl_(std::move(i)) {}
impl(Impl const & i)196             explicit impl(Impl const & i) : impl_(i) {}
197 
equal(impl_base const & rhs) const198             bool equal(impl_base const & rhs) const
199             {
200                 if(type() != rhs.type()) return false;
201                 return impl_ == rhs.get<Impl>();
202             }
203 
less_than(impl_base const & rhs) const204             bool less_than(impl_base const & rhs) const
205             {
206                 return type() < rhs.type() ||
207                     (type() == rhs.type() && impl_ < rhs.get<Impl>());
208             }
209 
valid() const210             bool valid() const
211             {
212                 return !!impl_;
213             }
214 
type() const215             const char *type() const
216             {
217                 return Impl::type();
218             }
219 
print(std::ostream & os) const220             std::ostream & print(std::ostream & os) const
221             {
222                 os << impl_;
223                 return os;
224             }
225 
save(serialization::output_archive & ar) const226             void save(serialization::output_archive & ar) const
227             {
228                 impl_.save(ar);
229             }
230 
load(serialization::input_archive & ar)231             void load(serialization::input_archive & ar)
232             {
233                 impl_.load(ar);
234             }
235 
clone() const236             impl_base * clone() const
237             {
238                 return new impl<Impl>(impl_);
239             }
240 
move()241             impl_base * move()
242             {
243                 return new impl<Impl>(std::move(impl_));
244             }
245 
246             Impl impl_;
247         };
248     };
249 
250     typedef std::map<std::string, locality> endpoints_type;
251 
252     std::ostream& operator<< (std::ostream& os, endpoints_type const& endpoints);
253 }}
254 
255 #include <hpx/config/warnings_suffix.hpp>
256 
257 #endif
258