summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libadhocutil/scopeExit.cpp22
-rw-r--r--libadhocutil/scopeExit.h24
-rw-r--r--libadhocutil/unittests/Jamfile.jam10
-rw-r--r--libadhocutil/unittests/testScopeExit.cpp27
4 files changed, 83 insertions, 0 deletions
diff --git a/libadhocutil/scopeExit.cpp b/libadhocutil/scopeExit.cpp
new file mode 100644
index 0000000..fa914c5
--- /dev/null
+++ b/libadhocutil/scopeExit.cpp
@@ -0,0 +1,22 @@
+#include "scopeExit.h"
+
+ScopeExit::ScopeExit(const Event & onexitpre, const Event & onsuccess, const Event & onfailure, const Event & onexitpost) :
+ onExitPre(onexitpre),
+ onSuccess(onsuccess),
+ onFailure(onfailure),
+ onExitPost(onexitpost)
+{
+}
+
+ScopeExit::~ScopeExit()
+{
+ if (onExitPre) onExitPre();
+ if (std::uncaught_exception()) {
+ if (onFailure) onFailure();
+ }
+ else {
+ if (onSuccess) onSuccess();
+ }
+ if (onExitPost) onExitPost();
+}
+
diff --git a/libadhocutil/scopeExit.h b/libadhocutil/scopeExit.h
new file mode 100644
index 0000000..d9854d5
--- /dev/null
+++ b/libadhocutil/scopeExit.h
@@ -0,0 +1,24 @@
+#ifndef LIBADHOC_SCOPEEXIT_H
+#define LIBADHOC_SCOPEEXIT_H
+
+#include <boost/function.hpp>
+#include "visibility.h"
+
+class DLL_PUBLIC ScopeExit {
+ public:
+ typedef boost::function<void()> Event;
+ ScopeExit(const Event &, const Event & = Event(), const Event & = Event(), const Event & = Event());
+ ~ScopeExit();
+
+ ScopeExit(const ScopeExit &) = delete;
+ void operator=(const ScopeExit &) = delete;
+
+ private:
+ const Event onExitPre;
+ const Event onSuccess;
+ const Event onFailure;
+ const Event onExitPost;
+};
+
+#endif
+
diff --git a/libadhocutil/unittests/Jamfile.jam b/libadhocutil/unittests/Jamfile.jam
index c8abcb9..610a3c4 100644
--- a/libadhocutil/unittests/Jamfile.jam
+++ b/libadhocutil/unittests/Jamfile.jam
@@ -63,3 +63,13 @@ run
testMapFinds
;
+run
+ testScopeExit.cpp
+ : : :
+ <define>BOOST_TEST_DYN_LINK
+ <library>..//adhocutil
+ <library>boost_utf
+ :
+ testScopeExit
+ ;
+
diff --git a/libadhocutil/unittests/testScopeExit.cpp b/libadhocutil/unittests/testScopeExit.cpp
new file mode 100644
index 0000000..80574f9
--- /dev/null
+++ b/libadhocutil/unittests/testScopeExit.cpp
@@ -0,0 +1,27 @@
+#define BOOST_TEST_MODULE ScopeExit
+#include <boost/test/unit_test.hpp>
+
+#include "scopeExit.h"
+#include <string>
+
+BOOST_AUTO_TEST_CASE ( cleanexit )
+{
+ std::string log;
+ {
+ ScopeExit se([&log]{ log += "before"; }, [&log]{ log += "clean"; }, [&log]{ log += "error"; }, [&log]{ log += "after"; });
+ }
+ BOOST_REQUIRE_EQUAL(log, "beforecleanafter");
+}
+
+BOOST_AUTO_TEST_CASE ( uncaught )
+{
+ BOOST_REQUIRE_THROW({
+ std::string log;
+ {
+ ScopeExit se([&log]{ log += "before"; }, [&log]{ log += "clean"; }, [&log]{ log += "error"; }, [&log]{ log += "after"; });
+ throw std::runtime_error("test unclean exit");
+ }
+ BOOST_REQUIRE_EQUAL(log, "beforeerrorafter");
+ }, std::runtime_error);
+}
+