From 3b6051393d2f5902b2337d593da21eca5059b8c6 Mon Sep 17 00:00:00 2001 From: LoRd_MuldeR Date: Sat, 4 Nov 2017 21:10:32 +0100 Subject: [PATCH] Changed Lazy to take a lambda-function in its constructor. This avoids the need for sub-classing. --- docs/d0/dce/class_m_utils_1_1_lazy.html | 16 ++++++-------- docs/d8/d4d/_lazy_8h.html | 2 +- docs/d8/d4d/_lazy_8h_source.html | 4 ++-- docs/da/d44/class_m_utils_1_1_lazy-members.html | 2 +- include/MUtils/Lazy.h | 28 +++++++++++++------------ 5 files changed, 25 insertions(+), 27 deletions(-) diff --git a/docs/d0/dce/class_m_utils_1_1_lazy.html b/docs/d0/dce/class_m_utils_1_1_lazy.html index e231d5c..e263478 100644 --- a/docs/d0/dce/class_m_utils_1_1_lazy.html +++ b/docs/d0/dce/class_m_utils_1_1_lazy.html @@ -65,10 +65,9 @@ $(function() {
-
MUtils::Lazy< T > Class Template Referenceabstract
+
MUtils::Lazy< T > Class Template Reference
@@ -79,23 +78,20 @@ $(function() { + + -

Public Member Functions

Lazy (std::function< T *(void)> &&initializer)
 
T & operator* (void)
 
- - -

-Protected Member Functions

-virtual T * create ()=0
 

Detailed Description

template<typename T>
class MUtils::Lazy< T >

Lazy initialization template class.

-

In order to create your own "lazy" initializer, inherit from the Lazy<T> class an implement the create() function. The lazy-initialized value can be obtained from a Lazy<T> instance by using the operator*(). Initialization of the value happens when the operator*() is called for the very first time, by invoking the concrete create() function. The return value of create() is then stored internally, so that any subsequent call to the operator*() immediately returns the previously created value.

-

Note on thread-saftey: This class is thread-safe in the sense that all calls to operator*() on the same Lazy<T> instance, regardless from which thread, are guaranteed to return the exactly same value/object. Still, if the value has not been initialized yet and if multiple threads happen to call operator*() at the same time, then the concrete create() function may be invoked more than once (concurrently and by different threads). In that case, all but one return value of create() are discarded, and all threads eventually receive the same value/object.

+

The lazy-initialized value of type T can be obtained from a Lazy<T> instance by using the operator*(). Initialization of the value happens when the operator*() is called for the very first time, by invoking the initializer lambda-function that was passed to the constructor. The return value of the initializer lambda-function is then stored internally, so that any subsequent call to the operator*() immediately returns the previously created value.

+

Note on thread-saftey: This class is thread-safe in the sense that all calls to operator*() on the same Lazy<T> instance, regardless from which thread, are guaranteed to return the exactly same value/object. Still, if the value has not been initialized yet and if multiple threads happen to call operator*() at the same time, then the initializer lambda-function may be invoked more than once (concurrently and by different threads). In that case, all but one return value of the initializer lambda-function are discarded, and all threads eventually obtain the same value/object.


The documentation for this class was generated from the following file: diff --git a/docs/d8/d4d/_lazy_8h.html b/docs/d8/d4d/_lazy_8h.html index c567536..194cf96 100644 --- a/docs/d8/d4d/_lazy_8h.html +++ b/docs/d8/d4d/_lazy_8h.html @@ -75,8 +75,8 @@ $(function() { More...

#include <MUtils/Global.h>
#include <MUtils/Exception.h>
-#include <QScopedPointer>
#include <QAtomicPointer>
+#include <functional>

Go to the source code of this file.

diff --git a/docs/d8/d4d/_lazy_8h_source.html b/docs/d8/d4d/_lazy_8h_source.html index b9bac8d..45a9600 100644 --- a/docs/d8/d4d/_lazy_8h_source.html +++ b/docs/d8/d4d/_lazy_8h_source.html @@ -67,8 +67,8 @@ $(function() {
Lazy.h
-Go to the documentation of this file.
1 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2017 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
21 
27 #pragma once
28 
29 //MUtils
30 #include <MUtils/Global.h>
31 #include <MUtils/Exception.h>
32 
33 //Qt
34 #include <QScopedPointer>
35 #include <QAtomicPointer>
36 
37 namespace MUtils
38 {
46  template<typename T> class Lazy
47  {
48  public:
49  T& operator*(void)
50  {
51  while (!m_data)
52  {
53  if (T *const initializer = create())
54  {
55  if (m_data.testAndSetOrdered(NULL, initializer))
56  {
57  return *initializer;
58  }
59  }
60  else
61  {
62  MUTILS_THROW("Initializer function returned NULL!");
63  }
64  }
65  return *m_data;
66  }
67 
68  protected:
69  virtual T *create() = 0;
70 
71  private:
72  QAtomicPointer<T> m_data;
73  };
74 }
This file contains miscellaneous functions that are generally useful for Qt-based applications...
-
Lazy initialization template class.
Definition: Lazy.h:46
+Go to the documentation of this file.
1 // MuldeR's Utilities for Qt
3 // Copyright (C) 2004-2017 LoRd_MuldeR <MuldeR2@GMX.de>
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18 //
19 // http://www.gnu.org/licenses/lgpl-2.1.txt
21 
27 #pragma once
28 
29 //MUtils
30 #include <MUtils/Global.h>
31 #include <MUtils/Exception.h>
32 
33 //Qt
34 #include <QAtomicPointer>
35 
36 //CRT
37 #include <functional>
38 
39 namespace MUtils
40 {
48  template<typename T> class Lazy
49  {
50  public:
51  Lazy(std::function<T*(void)> &&initializer) : m_initializer(initializer) { }
52 
53  T& operator*(void)
54  {
55  while (!m_value)
56  {
57  if (T *const value = m_initializer())
58  {
59  if (!m_value.testAndSetOrdered(NULL, value))
60  {
61  delete value; /*too late*/
62  }
63  }
64  else
65  {
66  MUTILS_THROW("Initializer returned NULL!");
67  }
68  }
69  return *m_value;
70  }
71 
72  private:
73  QAtomicPointer<T> m_value;
74  const std::function<T*(void)> m_initializer;
75  };
76 }
This file contains miscellaneous functions that are generally useful for Qt-based applications...
+
Lazy initialization template class.
Definition: Lazy.h:48
Global MUtils namespace.
Definition: CPUFeatures.h:37
diff --git a/docs/da/d44/class_m_utils_1_1_lazy-members.html b/docs/da/d44/class_m_utils_1_1_lazy-members.html index 6f376b7..407b11f 100644 --- a/docs/da/d44/class_m_utils_1_1_lazy-members.html +++ b/docs/da/d44/class_m_utils_1_1_lazy-members.html @@ -70,7 +70,7 @@ $(function() {

This is the complete list of members for MUtils::Lazy< T >, including all inherited members.

- +
create()=0 (defined in MUtils::Lazy< T >)MUtils::Lazy< T >protectedpure virtual
Lazy(std::function< T *(void)> &&initializer) (defined in MUtils::Lazy< T >)MUtils::Lazy< T >inline
operator*(void) (defined in MUtils::Lazy< T >)MUtils::Lazy< T >inline
diff --git a/include/MUtils/Lazy.h b/include/MUtils/Lazy.h index 4c31051..5c2b15f 100644 --- a/include/MUtils/Lazy.h +++ b/include/MUtils/Lazy.h @@ -31,44 +31,46 @@ #include //Qt -#include #include +//CRT +#include + namespace MUtils { /** * \brief Lazy initialization template class * - * In order to create your own "lazy" initializer, inherit from the `Lazy` class an implement the create() function. The lazy-initialized value can be obtained from a `Lazy` instance by using the `operator*()`. Initialization of the value happens when the `operator*()` is called for the very first time, by invoking the concrete create() function. The return value of create() is then stored internally, so that any subsequent call to the `operator*()` immediately returns the previously created value. + * The lazy-initialized value of type T can be obtained from a `Lazy` instance by using the `operator*()`. Initialization of the value happens when the `operator*()` is called for the very first time, by invoking the `initializer` lambda-function that was passed to the constructor. The return value of the `initializer` lambda-function is then stored internally, so that any subsequent call to the `operator*()` *immediately* returns the previously created value. * - * **Note on thread-saftey:** This class is thread-safe in the sense that all calls to `operator*()` on the same `Lazy` instance, regardless from which thread, are guaranteed to return the exactly same value/object. Still, if the value has *not* been initialized yet **and** if multiple threads happen to call `operator*()` at the same time, then the concrete create() function *may* be invoked more than once (concurrently and by different threads). In that case, all but one return value of create() are discarded, and all threads eventually receive the same value/object. + * **Note on thread-saftey:** This class is thread-safe in the sense that all calls to `operator*()` on the same `Lazy` instance, regardless from which thread, are guaranteed to return the exactly same value/object. Still, if the value has *not* been initialized yet **and** if multiple threads happen to call `operator*()` at the same time, then the `initializer` lambda-function *may* be invoked more than once (concurrently and by different threads). In that case, all but one return value of the `initializer` lambda-function are discarded, and all threads eventually obtain the same value/object. */ template class Lazy { public: + Lazy(std::function &&initializer) : m_initializer(initializer) { } + T& operator*(void) { - while (!m_data) + while (!m_value) { - if (T *const initializer = create()) + if (T *const value = m_initializer()) { - if (!m_data.testAndSetOrdered(NULL, initializer)) + if (!m_value.testAndSetOrdered(NULL, value)) { - delete initializer; + delete value; /*too late*/ } } else { - MUTILS_THROW("Initializer function returned NULL!"); + MUTILS_THROW("Initializer returned NULL!"); } } - return *m_data; + return *m_value; } - protected: - virtual T *create() = 0; - private: - QAtomicPointer m_data; + QAtomicPointer m_value; + const std::function m_initializer; }; } -- 2.11.4.GIT