PLaSK library

Loading...
Searching...
No Matches
provider.hpp
Go to the documentation of this file.
1/*
2 * This file is part of PLaSK (https://plask.app) by Photonics Group at TUL
3 * Copyright (c) 2022 Lodz University of Technology
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14#ifndef PLASK__PROVIDER_H
15#define PLASK__PROVIDER_H
16
165#include <set>
166#include <vector>
167#include <functional> // std::function
168#include <type_traits> // std::is_same
169#include "../optional.hpp"
170#include <boost/signals2.hpp>
171
172
173#include "../exceptions.hpp"
174#include "../utils/stl.hpp"
175#include "../mesh/mesh.hpp"
176#include "../mesh/interpolation.hpp"
177
178 namespace plask {
179
190 struct PLASK_API Provider {
191
192 static constexpr const char* NAME = "undefined";
193 virtual const char* name() const { return NAME; }
194
195 Provider & operator=(const Provider&) = delete;
196 Provider(const Provider&) = delete;
197 Provider() = default;
198
203 boost::signals2::signal<void(Provider&, bool)> changed;
204
206 virtual ~Provider() {
207 changed(*this, true);
208 }
209
214 void fireChanged() {
215 changed(*this, false);
216 }
217
218};
219
224 struct PLASK_API ReceiverBase {
225
227 enum class ChangeReason {
228 REASON_DELETE,
229 REASON_VALUE,
230 REASON_PROVIDER
231 };
232
233 virtual ~ReceiverBase() {}
234};
235
249 template <typename ProviderT>
250 class Receiver: public ReceiverBase {
251
252 boost::signals2::connection providerConnection;
253
254 protected:
255
257 bool _hasPrivateProvider;
258
259 public:
260
261 typedef Receiver<ProviderT> Base;
262
264 static constexpr const char* PROVIDER_NAME = ProviderT::NAME;
265 virtual const char* providerName() const { return PROVIDER_NAME; }
266
268 boost::signals2::signal<void(ReceiverBase& src, ChangeReason reason)> providerValueChanged;
269
270 Receiver& operator=(const Receiver&) = delete;
271 Receiver(const Receiver&) = delete;
272
274 typedef ProviderT ProviderType;
275
277 ProviderT* provider;
278
280 Receiver(): _hasPrivateProvider(false), provider(0) {}
281
283 virtual ~Receiver() {
284 providerConnection.disconnect();
285 if (_hasPrivateProvider) {
286 delete this->provider;
287 this->provider = nullptr;
288 }
289 fireChanged(ChangeReason::REASON_DELETE);
290 }
291
296 void fireChanged(ChangeReason reason) {
297 providerValueChanged(*this, reason);
298 }
299
305 void setProvider(ProviderT* provider, bool newProviderIsPrivate = false) {
306 if (this->provider == provider) {
307 this->_hasPrivateProvider = newProviderIsPrivate;
308 return;
309 }
310 providerConnection.disconnect();
311 if (_hasPrivateProvider) delete this->provider;
312 if (provider) providerConnection = provider->changed.connect(
313 [&](Provider& PLASK_UNUSED(which), bool isDeleted) {
314 if (isDeleted) {
315 providerConnection.disconnect(); //TODO do we need this line?
316 this->provider = 0;
317 }
318 this->fireChanged(isDeleted ? ChangeReason::REASON_PROVIDER : ChangeReason::REASON_VALUE);
319 });
320 this->provider = provider;
321 this->_hasPrivateProvider = newProviderIsPrivate;
322 this->fireChanged(ChangeReason::REASON_PROVIDER);
323 }
324
329 void setProvider(ProviderT &provider) {
330 setProvider(&provider);
331 }
332
337 void setProvider(std::unique_ptr<ProviderT>&& provider) {
338 setProvider(provider->release(), true);
339 }
340
341 /*
342 * Change provider. If new provider is different from current one then changed flag is set.
343 * @param provider new provider, can be @c nullptr to only disconnect from current provider.
344 */
345 /*void operator=(ProviderT *provider) {
346 setProvider(provider);
347 }*/
348
349 /*
350 * Change provider. If new provider is different from current one then changed flag is set.
351 * @param provider new provider
352 */
353 /*void operator=(ProviderT &provider) {
354 setProvider(&provider);
355 }*/
356
361 ProviderT* getProvider() { return provider; }
362
367 const ProviderT* getProvider() const { return provider; }
368
370 bool hasProvider() const {
371 return provider;
372 }
373
375 void ensureHasProvider() const {
376 if (provider == nullptr)
377 throw NoProvider(providerName());
378 }
379
386 template<typename ...Args> auto
387 operator()(const Args&... params) const -> decltype((*provider)(params...)) {
388 beforeGetValue();
389 return (*provider)(params...);
390 }
391
397 template<typename ...Args> auto
398 optional(const Args&... params) const -> plask::optional<decltype((*provider)(params...))> {
399 try {
400 return plask::optional<decltype((*provider)(params...))>(this->operator()(params...));
401 } catch (std::exception&) {
402 return plask::optional<decltype((*provider)(params...))>();
403 }
404 }
405
412 template <typename ...ConstProviderConstructorArgs>
413 void setConstValue(ConstProviderConstructorArgs&&... constProviderConstructorArgs) {
414 setProvider(new typename ProviderT::ConstProviderType(std::forward<ConstProviderConstructorArgs>(constProviderConstructorArgs)...), true);
415 }
416
424 template <typename ClassT, typename methodT>
425 boost::signals2::connection changedConnectMethod(ClassT* obj, methodT method, boost::signals2::connect_position at=boost::signals2::at_back) {
426 return providerValueChanged.connect(boost::bind(method, obj, _1, _2), at);
427 }
428
430 template <typename ClassT, typename methodT>
431 void changedDisconnectMethod(ClassT* obj, methodT method) {
432 providerValueChanged.disconnect(boost::bind(method, obj, _1, _2));
433 }
434
435 protected:
436
445 void beforeGetValue() const {
446 ensureHasProvider();
447 }
448
449};
450
456 template <typename ValueT, typename... ArgsT>
457 struct SingleValueProvider: public Provider {
458
459 static constexpr const char* NAME = "undefined value";
460 const char* name() const override { return NAME; }
461
463 typedef ValueT ProvidedType;
464
469 virtual ProvidedType operator()(ArgsT...) const = 0;
470
471};
472
478 template <typename ValueT, typename EnumT, typename... ArgsT>
479 struct MultiValueProvider: public Provider {
480
481 static constexpr const char* NAME = "undefined value";
482 const char* name() const override { return NAME; }
483
485 typedef ValueT ProvidedType;
486
488 typedef EnumT EnumType;
489
494 virtual ProvidedType operator()(EnumT num, ArgsT...) const = 0;
495
500 virtual size_t size() const = 0;
501
502};
503
504//TODO typedef for SingleValueReceiver (GCC 4.7 needed)
505
510 template <typename ValueT, typename SpaceT, typename... ExtraArgs>
511 struct FieldProvider: public Provider {
512
513 static constexpr const char* NAME = "undefined field";
514 const char* name() const override { return NAME; }
515
517 typedef LazyData<ValueT> ProvidedType;
518 typedef SpaceT SpaceType;
519
526 virtual ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
527
534 inline ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args) const {
535 return this->operator()(dst_mesh, extra_args..., INTERPOLATION_DEFAULT);
536 }
537
544 inline ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, std::tuple<ExtraArgs...> extra_args, InterpolationMethod method = INTERPOLATION_DEFAULT) const {
545 typedef std::tuple<ExtraArgs...> Tuple;
546 return apply_tuple(dst_mesh, method, std::forward<Tuple>(extra_args), make_seq_indices<0, sizeof...(ExtraArgs)>{});
547 }
548
549 private:
550 template <typename T, template <std::size_t...> class I, std::size_t... Indices>
551 inline ProvidedType apply_tuple(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, InterpolationMethod method, T&& t, I<Indices...>) const {
552 return this->operator()(dst_mesh, std::get<Indices>(std::forward<T>(t))..., method);
553 }
554
555};
556
561 template <typename ValueT, typename SpaceT, typename EnumT, typename... ExtraArgs>
562 struct MultiFieldProvider: public Provider {
563
564 static constexpr const char* NAME = "undefined field";
565 const char* name() const override { return NAME; }
566
568 typedef LazyData<ValueT> ProvidedType;
569
571 typedef EnumT EnumType;
572
577 virtual size_t size() const = 0;
578
586 virtual ProvidedType operator()(EnumT num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const = 0;
587
595 inline ProvidedType operator()(EnumT num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args) const {
596 return this->operator()(num, dst_mesh, extra_args..., INTERPOLATION_DEFAULT);
597 }
598
606 inline ProvidedType operator()(EnumT num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, std::tuple<ExtraArgs...>&& extra_args, InterpolationMethod method = INTERPOLATION_DEFAULT) const {
607 typedef std::tuple<ExtraArgs...> Tuple;
608 return apply_tuple(num, dst_mesh, method, std::forward<Tuple>(extra_args), make_seq_indices<0, sizeof...(ExtraArgs)>{});
609 }
610
618 inline ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args, InterpolationMethod method) const {
619 return this->operator()(EnumT(0), dst_mesh, extra_args..., method);
620 }
621
628 inline ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, ExtraArgs... extra_args) const {
629 return this->operator()(EnumT(0), dst_mesh, extra_args..., INTERPOLATION_DEFAULT);
630 }
631
639 inline ProvidedType operator()(shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, std::tuple<ExtraArgs...>&& extra_args, InterpolationMethod method = INTERPOLATION_DEFAULT) const {
640 typedef std::tuple<ExtraArgs...> Tuple;
641 return apply_tuple(EnumT(0), dst_mesh, method, std::forward<Tuple>(extra_args), make_seq_indices<0, sizeof...(ExtraArgs)>{});
642 }
643
644 private:
645 template <typename T, template <std::size_t...> class I, std::size_t... Indices>
646 inline ProvidedType apply_tuple(size_t num, shared_ptr<const MeshD<SpaceT::DIM>> dst_mesh, InterpolationMethod method, T&& t, I<Indices...>) {
647 return this->operator()(num, dst_mesh, std::get<Indices>(std::forward<T>(t))..., method);
648 }
649
650};
651
652
653 template<typename _Signature> struct DelegateProvider;
654
660 template<typename _Res, typename... _ArgTypes>
661 struct DelegateProvider<_Res(_ArgTypes...)>: public Provider {
662
664 std::function<_Res(_ArgTypes...)> valueGetter;
665
670 template<typename ...Args>
671 DelegateProvider<_Res(_ArgTypes...)>(Args&&... params)
672 : valueGetter(std::forward<Args>(params)...) {
673 }
674
680 virtual _Res operator()(_ArgTypes&&... params) const {
681 return valueGetter(std::forward<_ArgTypes>(params)...);
682 }
683};
684
685 template<typename _BaseClass, typename _Signature> struct PolymorphicDelegateProvider;
686
692 template<typename _BaseClass, typename _Res, typename... _ArgTypes>
693 struct PolymorphicDelegateProvider<_BaseClass, _Res(_ArgTypes...)>: public _BaseClass {
694
695
697 std::function<_Res(_ArgTypes...)> valueGetter;
698
699 PolymorphicDelegateProvider() = delete;
700
705 template<typename Functor>
706 PolymorphicDelegateProvider<_BaseClass, _Res(_ArgTypes...)>(Functor functor)
707 : valueGetter(functor)
708 {}
709
715 template<typename ClassType, typename MemberType>
716 PolymorphicDelegateProvider<_BaseClass, _Res(_ArgTypes...)>(ClassType* object, MemberType member)
717 : valueGetter(
718 [object, member](_ArgTypes&&... params) {
719 return (object->*member)(std::forward<_ArgTypes>(params)...);
720 })
721 {}
722
727 template<typename ...Args>
728 PolymorphicDelegateProvider<_BaseClass, _Res(_ArgTypes...)>(Args&&... params)
729 : valueGetter(std::forward<Args>(params)...) {
730 }
731
737 _Res operator()(_ArgTypes... params) const override {
738 return valueGetter(std::forward<_ArgTypes>(params)...);
739 }
740};
741
742}; //namespace plask
743
744#endif //PLASK__PROVIDER_H