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
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file Sim/Fitting/FitObserver.h
//! @brief Defines class FitObserver.
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#ifdef SWIG
#error no need to expose this header to Swig
#endif // SWIG
#ifndef BORNAGAIN_SIM_FITTING_FITOBSERVER_H
#define BORNAGAIN_SIM_FITTING_FITOBSERVER_H
#include "Sim/Fitting/FitTypes.h"
#include <functional>
#include <vector>
//! Contains collection of observers and call them at specified intervals.
//! Each observer will be called at first iteration and every-nth iterations.
template <typename T> class FitObserver {
public:
using observer_t = std::function<void(const T&)>;
FitObserver();
//! Adds observer to the list.
//! @param every_nth: An observer function will be called every_nth iterations.
//! @param observer: Observer function to be called.
void addObserver(int every_nth, observer_t&& observer);
//! Notifies all observers at their personally specified intervals.
//! @param data: The data which will be passed to the observer.
void notify(const T& data);
void notify_all(const T& data);
private:
class ObserverData {
public:
ObserverData()
: m_every_nth(0)
{
}
ObserverData(int every_nth, observer_t observer)
: m_every_nth(every_nth)
, m_observer(observer)
{
}
int m_every_nth;
observer_t m_observer;
};
bool need_notify(int every_nth);
std::vector<ObserverData> m_observers;
int m_notify_count; //! Total number of notify calls
};
template <typename T>
FitObserver<T>::FitObserver()
: m_notify_count(0)
{
}
template <typename T>
void FitObserver<T>::addObserver(int every_nth, FitObserver<T>::observer_t&& observer)
{
m_observers.emplace_back(ObserverData(every_nth, observer));
}
template <typename T> void FitObserver<T>::notify(const T& data)
{
for (const auto& observer : m_observers) {
if (need_notify(observer.m_every_nth))
observer.m_observer(data);
}
m_notify_count++;
}
template <typename T> void FitObserver<T>::notify_all(const T& data)
{
for (const auto& observer : m_observers)
observer.m_observer(data);
m_notify_count++;
}
template <typename T> bool FitObserver<T>::need_notify(int every_nth)
{
return every_nth && m_notify_count % every_nth == 0;
}
#endif // BORNAGAIN_SIM_FITTING_FITOBSERVER_H
|