aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-05 06:53:56 +0000
committerAvatar Ciaran McCreesh <ciaran.mccreesh@googlemail.com> 2007-01-05 06:53:56 +0000
commit684d9b7a39410886fd6be9719787159a50dd59ba (patch)
treed497a9d7a0f6210a291e29dc400bdbbc01bd73c8
parentc5de7560c18875c13e3cad9e311b6b55b026e9f0 (diff)
downloadpaludis-684d9b7a39410886fd6be9719787159a50dd59ba.tar.gz
paludis-684d9b7a39410886fd6be9719787159a50dd59ba.tar.xz
Catch singleton instantiation loopage.
-rw-r--r--paludis/util/instantiation_policy.hh13
-rw-r--r--paludis/util/instantiation_policy_TEST.cc27
-rw-r--r--paludis/util/save.hh11
3 files changed, 44 insertions, 7 deletions
diff --git a/paludis/util/instantiation_policy.hh b/paludis/util/instantiation_policy.hh
index adf3087..2f5b994 100644
--- a/paludis/util/instantiation_policy.hh
+++ b/paludis/util/instantiation_policy.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -21,6 +21,8 @@
#define PALUDIS_GUARD_PALUDIS_INSTANTIATION_POLICY_HH 1
#include <paludis/util/attributes.hh>
+#include <paludis/util/exception.hh>
+#include <paludis/util/save.hh>
/** \file
* InstantiationPolicy patterns.
@@ -276,9 +278,18 @@ namespace paludis
OurType_ *
InstantiationPolicy<OurType_, instantiation_method::SingletonAsNeededTag>::get_instance()
{
+ static bool recursive(false);
OurType_ * * i(_get_instance_ptr());
+
if (0 == *i)
+ {
+ if (recursive)
+ throw InternalError(PALUDIS_HERE, "Recursive instantiation");
+
+ Save<bool> save_recursive(&recursive, true);
*i = new OurType_;
+ }
+
return *i;
}
diff --git a/paludis/util/instantiation_policy_TEST.cc b/paludis/util/instantiation_policy_TEST.cc
index 550602e..e50767f 100644
--- a/paludis/util/instantiation_policy_TEST.cc
+++ b/paludis/util/instantiation_policy_TEST.cc
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -97,6 +97,21 @@ namespace
};
int MyLoadAtStartupClass::instances = 0;
+
+ class MyRecursiveClass :
+ public InstantiationPolicy<MyRecursiveClass, instantiation_method::SingletonAsNeededTag>
+ {
+ friend class InstantiationPolicy<MyRecursiveClass, instantiation_method::SingletonAsNeededTag>;
+
+ public:
+ std::string s;
+
+ private:
+ MyRecursiveClass() :
+ s(MyRecursiveClass::get_instance()->s)
+ {
+ }
+ };
}
namespace test_cases
@@ -156,6 +171,16 @@ namespace test_cases
}
} test_singleton_pattern_delete;
+ struct SingletonPatternRecursiveTest : TestCase
+ {
+ SingletonPatternRecursiveTest() : TestCase("singleton recursive test") { }
+
+ void run()
+ {
+ TEST_CHECK_THROWS(MyRecursiveClass::get_instance(), InternalError);
+ }
+ } test_singleton_pattern_recurse;
+
/**
* \test Test singleton create at startup behaviour.
*
diff --git a/paludis/util/save.hh b/paludis/util/save.hh
index b276f4e..1ee5679 100644
--- a/paludis/util/save.hh
+++ b/paludis/util/save.hh
@@ -1,7 +1,7 @@
/* vim: set sw=4 sts=4 et foldmethod=syntax : */
/*
- * Copyright (c) 2005, 2006 Ciaran McCreesh <ciaranm@ciaranm.org>
+ * Copyright (c) 2005, 2006, 2007 Ciaran McCreesh <ciaranm@ciaranm.org>
*
* This file is part of the Paludis package manager. Paludis is free software;
* you can redistribute it and/or modify it under the terms of the GNU General
@@ -20,8 +20,6 @@
#ifndef PALUDIS_GUARD_PALUDIS_SAVE_HH
#define PALUDIS_GUARD_PALUDIS_SAVE_HH 1
-#include <paludis/util/instantiation_policy.hh>
-
/** \file
* Declarations for the Save class.
*
@@ -39,13 +37,15 @@ namespace paludis
* \nosubgrouping
*/
template <typename T_>
- class Save :
- private InstantiationPolicy<Save<T_>, instantiation_method::NonCopyableTag>
+ class Save
{
private:
T_ * const _ptr;
const T_ _value;
+ Save(const Save &);
+ void operator= (const Save &);
+
public:
///\name Basic operations
///\{
@@ -82,3 +82,4 @@ namespace paludis
}
#endif
+