Merge lp:~michihenning/unity/phablet-unity-api-merge-1 into lp:unity/phablet

Proposed by Michi Henning
Status: Superseded
Proposed branch: lp:~michihenning/unity/phablet-unity-api-merge-1
Merge into: lp:unity/phablet
Diff against target: 3857 lines (+3562/-8)
39 files modified
.bzrignore (+1/-0)
CMakeLists.txt (+39/-1)
debian/control (+17/-0)
debian/libunity-api-dev.install (+1/-0)
debian/libunity-api.install (+1/-0)
include/CMakeLists.txt (+20/-0)
include/unity/CMakeLists.txt (+25/-0)
include/unity/Exception.h (+156/-0)
include/unity/UnityExceptions.h (+258/-0)
include/unity/api/CMakeLists.txt (+27/-0)
include/unity/api/Version.h.cmake (+101/-0)
include/unity/internal/ExceptionImpl.h (+60/-0)
include/unity/internal/UnityExceptionsImpl.h (+95/-0)
include/unity/scopes/CMakeLists.txt (+21/-0)
include/unity/util/CMakeLists.txt (+21/-0)
include/unity/util/Daemon.h (+129/-0)
include/unity/util/DefinesPtrs.h (+89/-0)
include/unity/util/FileIO.h (+38/-0)
include/unity/util/NonCopyable.h (+87/-0)
include/unity/util/ResourcePtr.h (+788/-0)
include/unity/util/internal/DaemonImpl.h (+67/-0)
plugins/HudClient/hudclient.cpp (+17/-7)
src/CMakeLists.txt (+23/-0)
src/unity/CMakeLists.txt (+28/-0)
src/unity/Exception.cpp (+145/-0)
src/unity/UnityExceptions.cpp (+246/-0)
src/unity/api/CMakeLists.txt (+26/-0)
src/unity/api/Version.cpp (+59/-0)
src/unity/api/internal/CMakeLists.txt (+22/-0)
src/unity/api/scopes/CMakeLists.txt (+24/-0)
src/unity/api/scopes/internal/CMakeLists.txt (+22/-0)
src/unity/internal/CMakeLists.txt (+24/-0)
src/unity/internal/ExceptionImpl.cpp (+244/-0)
src/unity/internal/UnityExceptionsImpl.cpp (+126/-0)
src/unity/util/CMakeLists.txt (+26/-0)
src/unity/util/Daemon.cpp (+89/-0)
src/unity/util/FileIO.cpp (+106/-0)
src/unity/util/internal/CMakeLists.txt (+23/-0)
src/unity/util/internal/DaemonImpl.cpp (+271/-0)
To merge this branch: bzr merge lp:~michihenning/unity/phablet-unity-api-merge-1
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Michał Sawicz Needs Fixing
Review via email: mp+156746@code.launchpad.net

This proposal has been superseded by a proposal from 2013-04-05.

Commit message

This is stage one of the merge of the unity-api (skeleton) source tree into the phablet tree. This adds the source and header files from the unity-api tree into the correct spots, and updates the cmake files in minor ways to accommodate that.

There are also a bunch of changes to make the existing C++ code compile without warnings with -Wextra and -Wall.

There are remaining warnings that come from the Unity-6.0 build, caused by include/unity/UnityCore/ResultIterator.h.

I've submitted a separate merge request to fix this-- see https://code.launchpad.net/~michihenning/unity/ResultIterator-1163705 and https://bugs.launchpad.net/unity/+bug/1163705

Description of the change

This is stage one of the merge of the unity-api (skeleton) source tree into the phablet tree. This adds the source and header files from the unity-api tree into the correct spots, and updates the cmake files in minor ways to accommodate that.

There are also a bunch of changes to make the existing C++ code compile without warnings with -Wextra and -Wall.

There are remaining warnings that come from the Unity-6.0 build, caused by include/unity/UnityCore/ResultIterator.h.

I've submitted a separate merge request to fix this-- see https://code.launchpad.net/~michihenning/unity/ResultIterator-1163705 and https://bugs.launchpad.net/unity/+bug/1163705

To post a comment you must log in.
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

You have the CODING change in this branch, too, please revert that.

You also need to add the Boost dependencies in the debian/control file - that's why the build failed.

review: Needs Fixing
Revision history for this message
Michał Sawicz (saviq) wrote :

Didn't we agree that you'd drop the whole of current shell code under "shell" subdir?

Revision history for this message
Michi Henning (michihenning) wrote :

> Didn't we agree that you'd drop the whole of current shell code under "shell" subdir?

I was going to make that the next step. There is lots of other stuff still that needs to be done, such as integrating the tests, etc.

I just figured I'll do it in several smaller steps at a time, rather than as one giant thing.

Thanks for teaching me about launchpad, and my apologies for my ignorance as to proper process. I guess I'll learn as I go.

Is there some document that explains how to do this right for various scenarios, for example, how to correctly do this for a sequence of changes where each change depends on acceptance of the previous one, with the code depending on the previous change? That's probably what I'd like to do here.

If I need to base each change on trunk, we'll end up with a nearly 24 hour turn-around time for things I do here, because of the time zone difference.

Cheers,

Michi.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michael Terry (mterry) wrote :

Michi, one thing you can do is when you file a branch merge request, you can specify that there is a prerequisite branch. So let's say you have branches A and B, where B depends on A.

File branch A.
File branch B, specifying A as a prerequisite.

The diff in launchpad for B will only show the delta between A and B. And it won't be automerged until A lands.

Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for that Michael. Savic has been teaching me the lp ropes, and I'm slowly getting the hang of it :-)

Currently, the build fails because of issues with the debian/control file. About to set up a chroot environment here so I can test this.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Hey, the package name should be libunity-api, and you need a separate libunity-api-dev package for the headers.

Rationale being that you don't want the headers installed just to be able to use the library.

review: Needs Fixing
Revision history for this message
Michał Sawicz (saviq) wrote :
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Needs Fixing (continuous-integration)
Revision history for this message
Michi Henning (michihenning) wrote :

Thanks for that! Will look into the .so versioning issue next week.

Michi.

On 05/04/2013, at 18:24 , Michał Sawicz <email address hidden> wrote:

> Here's some useful info
>
> http://developer.ubuntu.com/packaging/html/libraries.html
> --
> https://code.launchpad.net/~michihenning/unity/phablet-unity-api-merge-1/+merge/156746
> You are the owner of lp:~michihenning/unity/phablet-unity-api-merge-1.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)
Revision history for this message
Michał Sawicz (saviq) wrote :

Resubmitting with lp:~michihenning/unity/fix-c-linkage-1163719 as prerequisite.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2013-01-23 12:22:08 +0000
3+++ .bzrignore 2013-04-05 10:31:25 +0000
4@@ -11,3 +11,4 @@
5 config.h
6 qml-phone-shell
7 qml-phone-shell.desktop
8+install
9
10=== modified file 'CMakeLists.txt'
11--- CMakeLists.txt 2013-04-04 12:41:50 +0000
12+++ CMakeLists.txt 2013-04-05 10:31:25 +0000
13@@ -1,5 +1,11 @@
14+cmake_minimum_required(VERSION 2.8.9)
15+
16+# Default install location. Must be set here, before setting the project.
17+if (NOT DEFINED CMAKE_INSTALL_PREFIX)
18+ set(CMAKE_INSTALL_PREFIX ${CMAKE_BINARY_DIR}/install CACHE PATH "" FORCE)
19+endif()
20+
21 project(qml-phone-shell CXX)
22-cmake_minimum_required(VERSION 2.8.9)
23
24 set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules)
25
26@@ -35,6 +41,7 @@
27 find_package(Qt5Quick)
28 find_package(Qt5Gui)
29 find_package(Qt5DBus)
30+find_package(Boost 1.49.0 COMPONENTS regex REQUIRED)
31
32 # Standard install paths
33 include(GNUInstallDirs)
34@@ -45,10 +52,39 @@
35
36 include_directories(
37 ${CMAKE_CURRENT_BINARY_DIR}
38+ ${CMAKE_CURRENT_BINARY_DIR}/include
39 ${CMAKE_CURRENT_SOURCE_DIR}
40+ ${CMAKE_CURRENT_SOURCE_DIR}/include
41 ${Qt5Gui_PRIVATE_INCLUDE_DIRS}
42 )
43
44+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -fno-permissive -pedantic -Wall -Wextra")
45+
46+if ("${CMAKE_BUILD_TYPE}" STREQUAL "release" OR "${CMAKE_BUILD_TYPE}" STREQUAL "relwithdebinfo")
47+ option(Werror "Treat warnings as errors" ON)
48+else()
49+ option(Werror "Treat warnings as errors" OFF)
50+endif()
51+
52+if (Werror)
53+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
54+endif()
55+
56+# API version
57+set(UNITY_API_MAJOR 0)
58+set(UNITY_API_MINOR 1)
59+set(UNITY_API_MICRO 0)
60+set(UNITY_API_VERSION "${UNITY_API_MAJOR}.${UNITY_API_MINOR}.${UNITY_API_MICRO}")
61+
62+# API library
63+set(UNITY_API_LIB unity-api)
64+
65+# Other libraries we depend on
66+set(OTHER_API_LIBS )
67+
68+# All the libraries we need to link a normal executable that uses the Unity API
69+set(LIBS ${UNITY_API_LIB} ${OTHER_API_LIBS})
70+
71 # Tests
72 enable_testing()
73 add_custom_target(check make test CTEST_OUTPUT_ON_FAILURE=1)
74@@ -92,7 +128,9 @@
75 )
76
77 # add subdirectories to build
78+add_subdirectory(include)
79 add_subdirectory(plugins)
80+add_subdirectory(src)
81
82
83 # install subdirectories
84
85=== modified file 'debian/control'
86--- debian/control 2013-03-27 19:08:01 +0000
87+++ debian/control 2013-04-05 10:31:25 +0000
88@@ -20,6 +20,8 @@
89 libhud-client1-dev,
90 libdee-qt5-dev (>= 3.0),
91 python,
92+ libboost1.49-dev (>= 1.49),
93+ libboost-regex1.49-dev (>= 1.49),
94 Standards-Version: 3.9.3
95 Vcs-Bzr: lp:unity/phablet
96
97@@ -52,3 +54,18 @@
98 libqt5widgets5,
99 Description: Test package for the shell
100 Autopilot tests for the qml-phone-shell package
101+
102+Package: libunity-api
103+Architecture: all
104+Depends: ${shlibs:Depends},
105+ ${misc:Depends},
106+Description: API for shell integration
107+ The Unity API permits integration with the shell, for example, to add indicators or notifications.
108+
109+Package: libunity-api-dev
110+Architecture: all
111+Depends: ${misc:Depends},
112+ libunity-api (= ${binary:Version}),
113+ libboost1.49-dev (>= 1.49),
114+Description: Header files for Unity API
115+ The Unity API permits integration with the shell, for example, to add indicators or notifications.
116
117=== added file 'debian/libunity-api-dev.install'
118--- debian/libunity-api-dev.install 1970-01-01 00:00:00 +0000
119+++ debian/libunity-api-dev.install 2013-04-05 10:31:25 +0000
120@@ -0,0 +1,1 @@
121+usr/include/unity/*
122
123=== added file 'debian/libunity-api.install'
124--- debian/libunity-api.install 1970-01-01 00:00:00 +0000
125+++ debian/libunity-api.install 2013-04-05 10:31:25 +0000
126@@ -0,0 +1,1 @@
127+usr/lib/libunity-api.so
128
129=== added directory 'include'
130=== added file 'include/CMakeLists.txt'
131--- include/CMakeLists.txt 1970-01-01 00:00:00 +0000
132+++ include/CMakeLists.txt 2013-04-05 10:31:25 +0000
133@@ -0,0 +1,20 @@
134+#
135+# Copyright (C) 2013 Canonical Ltd
136+#
137+# This program is free software: you can redistribute it and/or modify
138+# it under the terms of the GNU General Public License version 3 as
139+# published by the Free Software Foundation.
140+#
141+# This program is distributed in the hope that it will be useful,
142+# but WITHOUT ANY WARRANTY; without even the implied warranty of
143+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
144+# GNU General Public License for more details.
145+#
146+# You should have received a copy of the GNU General Public License
147+# along with this program. If not, see <http://www.gnu.org/licenses/>.
148+#
149+# Authored by: Michi Henning <michi.henning@canonical.com>
150+#
151+
152+set(HDR_INSTALL_DIR include)
153+add_subdirectory(unity)
154
155=== added directory 'include/unity'
156=== added file 'include/unity/CMakeLists.txt'
157--- include/unity/CMakeLists.txt 1970-01-01 00:00:00 +0000
158+++ include/unity/CMakeLists.txt 2013-04-05 10:31:25 +0000
159@@ -0,0 +1,25 @@
160+#
161+# Copyright (C) 2013 Canonical Ltd
162+#
163+# This program is free software: you can redistribute it and/or modify
164+# it under the terms of the GNU General Public License version 3 as
165+# published by the Free Software Foundation.
166+#
167+# This program is distributed in the hope that it will be useful,
168+# but WITHOUT ANY WARRANTY; without even the implied warranty of
169+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
170+# GNU General Public License for more details.
171+#
172+# You should have received a copy of the GNU General Public License
173+# along with this program. If not, see <http://www.gnu.org/licenses/>.
174+#
175+# Authored by: Michi Henning <michi.henning@canonical.com>
176+#
177+
178+add_subdirectory(api)
179+add_subdirectory(scopes)
180+add_subdirectory(util)
181+
182+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
183+
184+install(FILES ${headers} DESTINATION ${HDR_INSTALL_DIR}/unity)
185
186=== added file 'include/unity/Exception.h'
187--- include/unity/Exception.h 1970-01-01 00:00:00 +0000
188+++ include/unity/Exception.h 2013-04-05 10:31:25 +0000
189@@ -0,0 +1,156 @@
190+/*
191+ * Copyright (C) 2013 Canonical Ltd
192+ *
193+ * This program is free software: you can redistribute it and/or modify
194+ * it under the terms of the GNU General Public License version 3 as
195+ * published by the Free Software Foundation.
196+ *
197+ * This program is distributed in the hope that it will be useful,
198+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
199+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
200+ * GNU General Public License for more details.
201+ *
202+ * You should have received a copy of the GNU General Public License
203+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
204+ *
205+ * Authored by: Michi Henning <michi.henning@canonical.com>
206+ */
207+
208+#ifndef UNITY_EXCEPTION_H
209+#define UNITY_EXCEPTION_H
210+
211+#include <exception>
212+#include <string>
213+#include <memory>
214+
215+namespace unity
216+{
217+
218+namespace internal
219+{
220+class ExceptionImpl;
221+}
222+
223+// TODO: It probably would be best to split this into a base and ImplBase, with the derived part in the internal
224+// namespace and declaring self(), the constructor, and pimpl(). That's because the Impl for the exception
225+// is in the internal namespace, so public API clients can use Exception instances, but they cannot
226+// create new derived exceptions because the Impl classes are internal to Unity.
227+
228+/**
229+\brief Abstract base class for all Unity exceptions.
230+
231+This class is the base class for all Unity exceptions. Besides providing a common base class for
232+structured exception handling, this class provides features to capture nested exceptions (for
233+exceptions that are re-thrown) and to chain exceptions into an exception history that allows
234+a number of exceptions to be remembered before throwing a new exception.
235+
236+The exception nesting is provided by the derivation from <code>std::nested_exception</code>. If you
237+catch an exception and throw another exception from the catch handler, the caught exception
238+is automatically preserved; you can access nested exceptions by calling the <code>nested_ptr()</code> and
239+<code>rethrow_nested()</code> member functions of <code>nested_exception</code>.
240+
241+In addition, you can remember one or more exceptions by calling remember(). This is useful in situations
242+where you need perform a number of actions that may fail with an error code, and you do not want to
243+throw an exception until all of the actions have been attempted. This is particularly useful in shutdown
244+scenarios, where it is often impossible to recover from an error, but it is still desirable to try to
245+shut down as much as possible before reporting or logging the errors:
246+
247+~~~
248+void
249+shutdown()
250+{
251+ using namespace std;
252+
253+ exception_ptr ep;
254+
255+ try
256+ {
257+ shutdown_action_1();
258+ }
259+ catch (SomeException const&)
260+ {
261+ ep = make_exception_ptr(current_exception());
262+ }
263+
264+ try
265+ {
266+ shutdown_action_2();
267+ }
268+ catch (SomeOtherException const&)
269+ {
270+ ep = e.remember(ep);
271+ }
272+
273+ int err = shutdown_action_3();
274+ if (err != 0)
275+ {
276+ try
277+ {
278+ throw YetAnotherException(err);
279+ }
280+ catch (YetAnotherException const& e)
281+ {
282+ ep = e.remember(ep);
283+ }
284+ }
285+
286+ if (ep)
287+ {
288+ rethrow_exception(ep);
289+ }
290+}
291+~~~
292+
293+Calling to_string() on a caught exception returns a string with the entire exception history (both nested and
294+chained).
295+
296+*/
297+
298+class Exception : public std::exception, public std::nested_exception
299+{
300+public:
301+ //! @cond
302+ Exception(Exception const&);
303+ Exception& operator=(Exception const&);
304+ virtual ~Exception() noexcept;
305+ //! @endcond
306+
307+ /**
308+ \brief Returns the name of the exception.
309+
310+ Derived classes must override what() to return <i>only</i> the (fully-qualified) name of the derived
311+ exception. If the derived class sets a reason string (or contains other details), it should <i>not</i>
312+ include the reason or details as part of the string return returned by what().
313+ */
314+ virtual char const* what() const noexcept = 0;
315+
316+ virtual std::string reason() const;
317+
318+ virtual std::string to_string(std::string const& indent = " ") const;
319+ virtual std::string to_string(int indent_level, std::string const& indent) const;
320+
321+ std::exception_ptr remember(std::exception_ptr earlier_exception);
322+ std::exception_ptr get_earlier() const noexcept;
323+
324+ /**
325+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
326+
327+ \note Derived exceptions must implement this member function so the implemention of remember()
328+ (provided by this abstract base class) can return a <code>std::exception_ptr</code> to its own derived exception.
329+ */
330+ virtual std::exception_ptr self() const = 0;
331+
332+protected:
333+ //! @cond
334+ Exception(std::shared_ptr<internal::ExceptionImpl> const& derived);
335+ internal::ExceptionImpl* pimpl() const noexcept; // No need to reimplement in derived
336+ //! @endcond
337+
338+private:
339+ std::shared_ptr<internal::ExceptionImpl> p_; // shared_ptr instead of unique_ptr because
340+ // exceptions must be copyable
341+};
342+
343+} // namespace unity
344+
345+#endif
346
347=== added file 'include/unity/UnityExceptions.h'
348--- include/unity/UnityExceptions.h 1970-01-01 00:00:00 +0000
349+++ include/unity/UnityExceptions.h 2013-04-05 10:31:25 +0000
350@@ -0,0 +1,258 @@
351+/*
352+ * Copyright (C) 2013 Canonical Ltd
353+ *
354+ * This program is free software: you can redistribute it and/or modify
355+ * it under the terms of the GNU General Public License version 3 as
356+ * published by the Free Software Foundation.
357+ *
358+ * This program is distributed in the hope that it will be useful,
359+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
360+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
361+ * GNU General Public License for more details.
362+ *
363+ * You should have received a copy of the GNU General Public License
364+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
365+ *
366+ * Authored by: Michi Henning <michi.henning@canonical.com>
367+ */
368+
369+#ifndef UNITY_EXCEPTIONS_H
370+#define UNITY_EXCEPTIONS_H
371+
372+#include <unity/Exception.h>
373+
374+namespace unity
375+{
376+
377+namespace internal
378+{
379+class InvalidArgumentExceptionImpl;
380+}
381+
382+/**
383+\brief Exception to indicate that an invalid argument was passed to a function, such as passing <code>nullptr</code>
384+ when the function expects the argument to be non-null.
385+*/
386+
387+class InvalidArgumentException : public Exception
388+{
389+public:
390+ /**
391+ \brief Constructs the exception.
392+ \param reason Further details about the cause of the exception.
393+ */
394+ explicit InvalidArgumentException(std::string const& reason);
395+ //! @cond
396+ InvalidArgumentException(InvalidArgumentException const&);
397+ InvalidArgumentException& operator=(InvalidArgumentException const&);
398+ virtual ~InvalidArgumentException() noexcept;
399+ //! @endcond
400+
401+ /**
402+ \brief Returns the fully-qualified name of the exception.
403+ */
404+ virtual char const* what() const noexcept override;
405+
406+ /**
407+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
408+ */
409+ virtual std::exception_ptr self() const override;
410+};
411+
412+namespace internal
413+{
414+class LogicExceptionImpl;
415+}
416+
417+/**
418+\brief Exception to indicate a logic error, such as driving the API incorrectly, such as calling methods
419+ in the wrong worder.
420+*/
421+
422+class LogicException : public Exception
423+{
424+public:
425+ /**
426+ \brief Constructs the exception.
427+ \param reason Further details about the cause of the exception.
428+ */
429+ explicit LogicException(std::string const& reason);
430+ //! @cond
431+ LogicException(LogicException const&);
432+ LogicException& operator=(LogicException const&);
433+ virtual ~LogicException() noexcept;
434+ //! @endcond
435+
436+ /**
437+ \brief Returns the fully-qualified name of the exception.
438+ */
439+ virtual char const* what() const noexcept override;
440+
441+ /**
442+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
443+ */
444+ virtual std::exception_ptr self() const override;
445+};
446+
447+namespace internal
448+{
449+class ShutdownExceptionImpl;
450+}
451+
452+/**
453+\brief Exception to indicate errors during shutdown.
454+
455+ Usually, it is not possible to handle or recover
456+ from errors that arise during shutdown. This exception is thrown once all possible shutdown actions
457+ have been carried out and provides information about anything that went wrong via the exception
458+ chaining mechanism of the Unity::Exception base class.
459+*/
460+
461+class ShutdownException : public Exception
462+{
463+public:
464+ /**
465+ \brief Constructs the exception.
466+ \param reason Further details about the cause of the exception.
467+ */
468+ explicit ShutdownException(std::string const& reason);
469+ //! @cond
470+ ShutdownException(ShutdownException const&);
471+ ShutdownException& operator=(ShutdownException const&);
472+ virtual ~ShutdownException() noexcept;
473+ //! @endcond
474+
475+ /**
476+ \brief Returns the fully-qualified name of the exception.
477+ */
478+ virtual char const* what() const noexcept override;
479+
480+ /**
481+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
482+ */
483+ virtual std::exception_ptr self() const override;
484+};
485+
486+namespace internal
487+{
488+class FileExceptionImpl;
489+}
490+
491+/**
492+\brief Exception to indicate file I/O errors, such as failure to open or write to a file.
493+*/
494+
495+class FileException : public Exception
496+{
497+public:
498+ /**
499+ \brief Constructs the exception.
500+ */
501+ /**
502+ \brief Constructs the exception from a reason string and and error number.
503+ \param reason Further details about the cause of the exception.
504+ \param err The UNIX <code>errno</code> value for the error.
505+ */
506+ FileException(std::string const& reason, int err);
507+ //! @cond
508+ FileException(FileException const&);
509+ FileException& operator=(FileException const&);
510+ virtual ~FileException() noexcept;
511+ //! @endcond
512+
513+ /**
514+ \brief Returns the fully-qualified name of the exception.
515+ */
516+ virtual char const* what() const noexcept override;
517+
518+ /**
519+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
520+ */
521+ virtual std::exception_ptr self() const override;
522+
523+ /**
524+ \return Returns the error number that was passed to the constructor.
525+ */
526+ int error() const noexcept;
527+};
528+
529+namespace internal
530+{
531+class SyscallExceptionImpl;
532+}
533+
534+/**
535+\brief Exception to indicate system or library call errors that set <code>errno</code>.
536+*/
537+
538+class SyscallException : public Exception
539+{
540+public:
541+ /**
542+ \brief Constructs the exception.
543+ */
544+ /**
545+ \brief Constructs the exception from a reason string and and error number.
546+ \param reason Further details about the cause of the exception.
547+ \param err The UNIX <code>errno</code> value for the error.
548+ */
549+ SyscallException(std::string const& reason, int err);
550+ //! @cond
551+ SyscallException(SyscallException const&);
552+ SyscallException& operator=(SyscallException const&);
553+ virtual ~SyscallException() noexcept;
554+ //! @endcond
555+
556+ /**
557+ \brief Returns the fully-qualified name of the exception.
558+ */
559+ virtual char const* what() const noexcept override;
560+
561+ /**
562+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
563+ */
564+ virtual std::exception_ptr self() const override;
565+
566+ /**
567+ \return Returns the error number that was passed to the constructor.
568+ */
569+ int error() const noexcept;
570+};
571+
572+namespace internal
573+{
574+class ResourceExceptionImpl;
575+}
576+
577+/**
578+\brief Exception for miscellaneous errors, such as failure of a third-party library or hitting resource limitations.
579+*/
580+
581+class ResourceException : public Exception
582+{
583+public:
584+ /**
585+ \brief Constructs the exception.
586+ \param reason Further details about the cause of the exception.
587+ */
588+ ResourceException(std::string const& reason);
589+ //! @cond
590+ ResourceException(ResourceException const&);
591+ ResourceException& operator=(ResourceException const&);
592+ virtual ~ResourceException() noexcept;
593+ //! @endcond
594+
595+ /**
596+ \brief Returns the fully-qualified name of the exception.
597+ */
598+ virtual char const* what() const noexcept override;
599+
600+ /**
601+ \brief Returns a <code>std::exception_ptr</code> to <code>this</code>.
602+ */
603+ virtual std::exception_ptr self() const override;
604+};
605+
606+} // namespace unity
607+
608+#endif
609
610=== added directory 'include/unity/api'
611=== added file 'include/unity/api/CMakeLists.txt'
612--- include/unity/api/CMakeLists.txt 1970-01-01 00:00:00 +0000
613+++ include/unity/api/CMakeLists.txt 2013-04-05 10:31:25 +0000
614@@ -0,0 +1,27 @@
615+#
616+# Copyright (C) 2013 Canonical Ltd
617+#
618+# This program is free software: you can redistribute it and/or modify
619+# it under the terms of the GNU General Public License version 3 as
620+# published by the Free Software Foundation.
621+#
622+# This program is distributed in the hope that it will be useful,
623+# but WITHOUT ANY WARRANTY; without even the implied warranty of
624+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
625+# GNU General Public License for more details.
626+#
627+# You should have received a copy of the GNU General Public License
628+# along with this program. If not, see <http://www.gnu.org/licenses/>.
629+#
630+# Authored by: Michi Henning <michi.henning@canonical.com>
631+#
632+
633+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
634+
635+#
636+# Generated headers
637+#
638+configure_file(Version.h.cmake Version.h)
639+set(headers ${headers} ${CMAKE_CURRENT_BINARY_DIR}/Version.h)
640+
641+install(FILES ${headers} DESTINATION ${HDR_INSTALL_DIR}/unity/api)
642
643=== added file 'include/unity/api/Version.h.cmake'
644--- include/unity/api/Version.h.cmake 1970-01-01 00:00:00 +0000
645+++ include/unity/api/Version.h.cmake 2013-04-05 10:31:25 +0000
646@@ -0,0 +1,101 @@
647+//
648+// DO NOT EDIT Version.h (this file)! It is generated from Version.h.cmake.
649+//
650+
651+/*
652+ * Copyright (C) 2013 Canonical Ltd
653+ *
654+ * This program is free software: you can redistribute it and/or modify
655+ * it under the terms of the GNU General Public License version 3 as
656+ * published by the Free Software Foundation.
657+ *
658+ * This program is distributed in the hope that it will be useful,
659+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
660+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
661+ * GNU General Public License for more details.
662+ *
663+ * You should have received a copy of the GNU General Public License
664+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
665+ *
666+ * Authored by: Michi Henning <michi.henning@canonical.com>
667+ */
668+
669+#ifndef UNITY_API_VERSION_H
670+#define UNITY_API_VERSION_H
671+
672+#define UNITY_API_VERSION_MAJOR @UNITY_API_MAJOR@
673+#define UNITY_API_VERSION_MINOR @UNITY_API_MINOR@
674+#define UNITY_API_VERSION_MICRO @UNITY_API_MICRO@
675+
676+#define UNITY_API_VERSION_STRING "@UNITY_API_VERSION@"
677+
678+namespace unity
679+{
680+
681+namespace api
682+{
683+
684+/**
685+\brief Class to obtain version information for the Unity API at run time.
686+
687+Version information is represented as
688+<i>&lt;<code>major</code>&gt;</i>.<i>&lt;<code>minor</code>&gt;</i>.<i>&lt;<code>micro</code>&gt;</i>.
689+
690+Releases that differ in the major or minor version number are binary incompatible.
691+
692+Releases of the library that differ only in the micro version number are binary compatible with older releases,
693+so client code does not need to be recompiled to use the newer library version.
694+
695+A different minor version is compatible at the API level, that is, it may add new APIs, but does not change existing
696+ones. API clients must be recompiled for a new major version.
697+
698+A different major version indicates incompatible API changes.
699+*/
700+
701+// Version could be a namespace instead of a class, but that requires a lower-case name,
702+// which is inconsistent with the remainder of the API.
703+
704+class Version
705+{
706+public:
707+ /**
708+ \brief Returns the major version number of the Unity API library.
709+
710+ The major version number is also available as the macro <code>UNITY_API_VERSION_MAJOR</code>.
711+ */
712+ static int major_version();
713+
714+ /**
715+ \brief Returns the minor version number of the Unity API library.
716+
717+ The minor version number is also available as the macro <code>UNITY_API_VERSION_MINOR</code>.
718+ */
719+ static int minor_version();
720+
721+ /**
722+ \brief Returns the micro version number of the Unity API library.
723+
724+ The micro version number is also available as the macro <code>UNITY_API_VERSION_MICRO</code>.
725+ */
726+ static int micro_version();
727+
728+ /**
729+ \brief Returns the Unity API version as a string in the format
730+ <i>&lt;<code>major</code>&gt;</i>.<i>&lt;<code>minor</code>&gt;</i>.<i>&lt;<code>micro</code>&gt;</i>.
731+
732+ The version string is also available as the macro <code>UNITY_API_VERSION_STRING</code>.
733+ */
734+ static const char* str(); // Returns "major.minor.micro"
735+
736+ // TODO: Add methods to report compiler version and compiler flags
737+
738+private:
739+ Version() = delete;
740+ ~Version() = delete;
741+};
742+
743+} // namespace api
744+
745+} // namespace unity
746+
747+#endif
748
749=== added directory 'include/unity/internal'
750=== added file 'include/unity/internal/ExceptionImpl.h'
751--- include/unity/internal/ExceptionImpl.h 1970-01-01 00:00:00 +0000
752+++ include/unity/internal/ExceptionImpl.h 2013-04-05 10:31:25 +0000
753@@ -0,0 +1,60 @@
754+/*
755+ * Copyright (C) 2013 Canonical Ltd
756+ *
757+ * This program is free software: you can redistribute it and/or modify
758+ * it under the terms of the GNU General Public License version 3 as
759+ * published by the Free Software Foundation.
760+ *
761+ * This program is distributed in the hope that it will be useful,
762+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
763+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
764+ * GNU General Public License for more details.
765+ *
766+ * You should have received a copy of the GNU General Public License
767+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
768+ *
769+ * Authored by: Michi Henning <michi.henning@canonical.com>
770+ */
771+
772+#ifndef UNITY_INTERNAL_EXCEPTIONIMPL_H
773+#define UNITY_INTERNAL_EXCEPTIONIMPL_H
774+
775+#include <unity/util/NonCopyable.h>
776+
777+#include <string>
778+#include <exception>
779+
780+namespace unity
781+{
782+
783+class Exception;
784+
785+namespace internal
786+{
787+
788+class ExceptionImpl : private util::NonCopyable
789+{
790+public:
791+ explicit ExceptionImpl(std::string const& reason);
792+
793+ virtual char const* what() const noexcept = 0;
794+ virtual std::string reason() const;
795+ virtual std::string to_string(std::nested_exception const& nested, int indent_level, std::string const& indent) const;
796+
797+ std::exception_ptr remember(unity::Exception const* env, std::exception_ptr earlier_exception);
798+ std::exception_ptr remember(unity::Exception const* env, Exception const& earlier_exception);
799+ std::exception_ptr get_earlier() const noexcept;
800+
801+protected:
802+ virtual ~ExceptionImpl() noexcept;
803+
804+private:
805+ std::string const reason_;
806+ std::exception_ptr previous_;
807+};
808+
809+} // namespace internal
810+
811+} // namespace unity
812+
813+#endif
814
815=== added file 'include/unity/internal/UnityExceptionsImpl.h'
816--- include/unity/internal/UnityExceptionsImpl.h 1970-01-01 00:00:00 +0000
817+++ include/unity/internal/UnityExceptionsImpl.h 2013-04-05 10:31:25 +0000
818@@ -0,0 +1,95 @@
819+/*
820+ * Copyright (C) 2012 Canonical Ltd
821+ *
822+ * This program is free software: you can redistribute it and/or modify
823+ * it under the terms of the GNU General Public License version 3 as
824+ * published by the Free Software Foundation.
825+ *
826+ * This program is distributed in the hope that it will be useful,
827+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
828+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
829+ * GNU General Public License for more details.
830+ *
831+ * You should have received a copy of the GNU General Public License
832+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
833+ *
834+ * Authored by: Michi Henning <michi.henning@canonical.com>
835+ */
836+
837+#ifndef UNITY_INTERNAL_UNITYEXCEPTIONSIMPL_H
838+#define UNITY_INTERNAL_UNITYEXCEPTIONSIMPL_H
839+
840+#include <unity/internal/ExceptionImpl.h>
841+
842+#include <string>
843+#include <exception>
844+
845+namespace unity
846+{
847+
848+class Exception;
849+
850+namespace internal
851+{
852+
853+class InvalidArgumentExceptionImpl : public ExceptionImpl
854+{
855+public:
856+ InvalidArgumentExceptionImpl(std::string const& reason);
857+
858+ virtual char const* what() const noexcept override;
859+};
860+
861+class LogicExceptionImpl : public ExceptionImpl
862+{
863+public:
864+ LogicExceptionImpl(std::string const& reason);
865+
866+ virtual char const* what() const noexcept override;
867+};
868+
869+class ShutdownExceptionImpl : public ExceptionImpl
870+{
871+public:
872+ ShutdownExceptionImpl(std::string const& reason);
873+
874+ virtual char const* what() const noexcept override;
875+};
876+
877+class FileExceptionImpl : public ExceptionImpl
878+{
879+public:
880+ FileExceptionImpl(std::string const& reason, int err);
881+
882+ virtual char const* what() const noexcept override;
883+ int error() const noexcept;
884+
885+private:
886+ int errno_;
887+};
888+
889+class SyscallExceptionImpl : public ExceptionImpl
890+{
891+public:
892+ SyscallExceptionImpl(std::string const& reason, int err);
893+
894+ virtual char const* what() const noexcept override;
895+ int error() const noexcept;
896+
897+private:
898+ int const errno_;
899+};
900+
901+class ResourceExceptionImpl : public ExceptionImpl
902+{
903+public:
904+ ResourceExceptionImpl(std::string const& reason);
905+
906+ virtual char const* what() const noexcept override;
907+};
908+
909+} // namespace internal
910+
911+} // namespace unity
912+
913+#endif
914
915=== added directory 'include/unity/scopes'
916=== added file 'include/unity/scopes/CMakeLists.txt'
917--- include/unity/scopes/CMakeLists.txt 1970-01-01 00:00:00 +0000
918+++ include/unity/scopes/CMakeLists.txt 2013-04-05 10:31:25 +0000
919@@ -0,0 +1,21 @@
920+#
921+# Copyright (C) 2013 Canonical Ltd
922+#
923+# This program is free software: you can redistribute it and/or modify
924+# it under the terms of the GNU General Public License version 3 as
925+# published by the Free Software Foundation.
926+#
927+# This program is distributed in the hope that it will be useful,
928+# but WITHOUT ANY WARRANTY; without even the implied warranty of
929+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
930+# GNU General Public License for more details.
931+#
932+# You should have received a copy of the GNU General Public License
933+# along with this program. If not, see <http://www.gnu.org/licenses/>.
934+#
935+# Authored by: Michi Henning <michi.henning@canonical.com>
936+#
937+
938+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
939+
940+install(FILES ${headers} DESTINATION include/unity/scopes)
941
942=== added directory 'include/unity/util'
943=== added file 'include/unity/util/CMakeLists.txt'
944--- include/unity/util/CMakeLists.txt 1970-01-01 00:00:00 +0000
945+++ include/unity/util/CMakeLists.txt 2013-04-05 10:31:25 +0000
946@@ -0,0 +1,21 @@
947+#
948+# Copyright (C) 2013 Canonical Ltd
949+#
950+# This program is free software: you can redistribute it and/or modify
951+# it under the terms of the GNU General Public License version 3 as
952+# published by the Free Software Foundation.
953+#
954+# This program is distributed in the hope that it will be useful,
955+# but WITHOUT ANY WARRANTY; without even the implied warranty of
956+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
957+# GNU General Public License for more details.
958+#
959+# You should have received a copy of the GNU General Public License
960+# along with this program. If not, see <http://www.gnu.org/licenses/>.
961+#
962+# Authored by: Michi Henning <michi.henning@canonical.com>
963+#
964+
965+file(GLOB headers "${CMAKE_CURRENT_SOURCE_DIR}/*.h")
966+
967+install(FILES ${headers} DESTINATION ${HDR_INSTALL_DIR}/unity/util)
968
969=== added file 'include/unity/util/Daemon.h'
970--- include/unity/util/Daemon.h 1970-01-01 00:00:00 +0000
971+++ include/unity/util/Daemon.h 2013-04-05 10:31:25 +0000
972@@ -0,0 +1,129 @@
973+/*
974+ * Copyright (C) 2013 Canonical Ltd
975+ *
976+ * This program is free software: you can redistribute it and/or modify
977+ * it under the terms of the GNU General Public License version 3 as
978+ * published by the Free Software Foundation.
979+ *
980+ * This program is distributed in the hope that it will be useful,
981+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
982+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
983+ * GNU General Public License for more details.
984+ *
985+ * You should have received a copy of the GNU General Public License
986+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
987+ *
988+ * Authored by: Michi Henning <michi.henning@canonical.com>
989+ */
990+
991+#ifndef UNITY_UTIL_DAEMON_H
992+#define UNITY_UTIL_DAEMON_H
993+
994+#include <unity/util/DefinesPtrs.h>
995+#include <unity/util/NonCopyable.h>
996+
997+#include <sys/types.h>
998+
999+namespace unity
1000+{
1001+
1002+namespace util
1003+{
1004+
1005+namespace internal
1006+{
1007+class DaemonImpl;
1008+}
1009+
1010+/**
1011+\class Daemon
1012+\brief Helper class to turn a process into a daemon.
1013+
1014+To turn a process into a daemon, instantiate this class and call daemonize_me().
1015+
1016+The new process becomes a session leader without a control terminal. The standard
1017+file descriptors (<code>stdin</code>, <code>stdout</code>, and stderr) are closed
1018+and re-opened to <code>/dev/null</code>.
1019+
1020+By default, any file descriptors (other than the standard three) that are open in the process
1021+remain open to the same destinations in the daemon. If you want to have other descriptors closed, call
1022+close_fds() before calling daemonize_me(). This will close all file descriptors > 2.
1023+
1024+By default, the signal disposition of the daemon is unchanged. To reset all signals to their
1025+default disposition, call reset_signals() before calling daemonize_me().
1026+
1027+By default, the umask of the daemon is unchanged. To set a different umask, call set_umask()
1028+before calling daemonize_me().
1029+
1030+By default, the working directory of the daemon is unchanged. To run the daemon with a different
1031+working directory, call set_working_dir() before calling daemonize_me(). Note that the working
1032+directory should be set to a path that is in the root file system. If the working directory
1033+is in any other file system, that file system cannot be unmounted while the daemon is running.
1034+
1035+Note: This class is not async signal-safe. Do not call daemonize_me() from a a signal handler.
1036+*/
1037+
1038+class Daemon final : public util::DefinesPtrs<Daemon>, private NonCopyable
1039+{
1040+public:
1041+ /**
1042+ \brief Create a Daemon instance.
1043+ \return A <code>unique_ptr</code> to the instance.
1044+ */
1045+ static UPtr create();
1046+
1047+ /**
1048+ \brief Causes daemonize_me() to close all open file descriptors other than the standard file
1049+ descriptors (which are connected <code>/dev/null</code>).
1050+ */
1051+ void close_fds() noexcept;
1052+
1053+ /**
1054+ \brief Causes daemonize_me() to reset all signals to their default behavior.
1055+ */
1056+ void reset_signals() noexcept;
1057+
1058+ /**
1059+ \brief Causes daemonize_me() to set the umask.
1060+ \param mask The umask for the daemon process.
1061+ */
1062+ void set_umask(mode_t mask) noexcept;
1063+
1064+ /**
1065+ \brief Causes daemonize_me() to set the working directory.
1066+ \param working_directory The working directory for the daemon process.
1067+ \throws SyscallException The process could not change the working directory to the specified directory.
1068+ \note Daemon processes should set their working to "/" or to a directory that is part of the root file system.
1069+ Otherwise, the file system containing the daemon's working directory cannot be unmounted without first
1070+ killing the daemon process.
1071+ */
1072+ void set_working_directory(std::string const& working_directory);
1073+
1074+ /**
1075+ \brief Turns the calling process into a daemon.
1076+
1077+ By default, daemonize_me() leaves open file descriptors, signal disposition, umask, and working
1078+ directory unchanged. Call the corresponding member function before calling daemonize_me() to
1079+ change this behavior as appropriate.
1080+
1081+ \note Calling daemonize_me() more than once is safe; any changes to file descriptors, signal disposition,
1082+ umask, or working directory as requested by calling the other member functions will be correctly set
1083+ for the calling process. However, daemonize_me() is not a cheap call because it calls <code>fork()</code>;
1084+ the normal use pattern is to create a Daemon instance, select the desired settings, call daemonize_me(),
1085+ and let the instance go out of scope.
1086+ */
1087+ void daemonize_me();
1088+
1089+ ~Daemon() noexcept;
1090+
1091+private:
1092+ Daemon(); // Class is final, instantiation only via create()
1093+
1094+ std::unique_ptr<internal::DaemonImpl> p_;
1095+};
1096+
1097+} // namespace util
1098+
1099+} // namespace unity
1100+
1101+#endif
1102
1103=== added file 'include/unity/util/DefinesPtrs.h'
1104--- include/unity/util/DefinesPtrs.h 1970-01-01 00:00:00 +0000
1105+++ include/unity/util/DefinesPtrs.h 2013-04-05 10:31:25 +0000
1106@@ -0,0 +1,89 @@
1107+/*
1108+ * Copyright (C) 2013 Canonical Ltd
1109+ *
1110+ * This program is free software: you can redistribute it and/or modify
1111+ * it under the terms of the GNU General Public License version 3 as
1112+ * published by the Free Software Foundation.
1113+ *
1114+ * This program is distributed in the hope that it will be useful,
1115+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1116+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1117+ * GNU General Public License for more details.
1118+ *
1119+ * You should have received a copy of the GNU General Public License
1120+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1121+ *
1122+ * Authored by: Michi Henning <michi.henning@canonical.com>
1123+ */
1124+
1125+#ifndef UNITY_UTIL_DEFINESPTRS_H
1126+#define UNITY_UTIL_DEFINESPTRS_H
1127+
1128+#include <memory>
1129+
1130+namespace unity
1131+{
1132+
1133+namespace util
1134+{
1135+
1136+/**
1137+\brief Helper template to inject smart pointer definitions into a class.
1138+
1139+This template injects type definitions for smart pointer types into a class. It is useful to
1140+establish a common naming convention for smart pointers across a project.
1141+
1142+You can use the template as follows. Note that the template parameter is the name of the class
1143+being defined ("curiously recurring template pattern").
1144+
1145+~~~
1146+* class MyClass : public util::DefinesPtrs<MyClass>
1147+* {
1148+* public:
1149+* // MyClass now provides public typedefs for Ptr, CPtr, UPtr, and UCPtr.
1150+* // ...
1151+* };
1152+~~~
1153+
1154+Callers of <code>MyClass</code> can now, for example, write
1155+
1156+~~~
1157+* MyClass::UPtr p(new MyClass);
1158+~~~
1159+
1160+*/
1161+
1162+template <typename T>
1163+class DefinesPtrs
1164+{
1165+public:
1166+ /**
1167+ A <code>std::shared_ptr</code> to a non-constant instance.
1168+ */
1169+ typedef std::shared_ptr<T> Ptr;
1170+
1171+ /**
1172+ A <code>std::shared_ptr</code> to a constant instance.
1173+ */
1174+ typedef std::shared_ptr<T const> CPtr;
1175+
1176+ /**
1177+ A <code>std::unique_ptr</code> to a non-constant instance.
1178+ */
1179+ typedef std::unique_ptr<T> UPtr;
1180+
1181+ /**
1182+ A <code>std::unique_ptr</code> to a constant instance.
1183+ */
1184+ typedef std::unique_ptr<T const> UCPtr;
1185+
1186+protected: // Not meant to be instantiated stand-alone
1187+ DefinesPtrs() = default;
1188+ virtual ~DefinesPtrs() = default;
1189+};
1190+
1191+} // namespace util
1192+
1193+} // namespace unity
1194+
1195+#endif
1196
1197=== added file 'include/unity/util/FileIO.h'
1198--- include/unity/util/FileIO.h 1970-01-01 00:00:00 +0000
1199+++ include/unity/util/FileIO.h 2013-04-05 10:31:25 +0000
1200@@ -0,0 +1,38 @@
1201+/*
1202+ * Copyright (C) 2013 Canonical Ltd
1203+ *
1204+ * This program is free software: you can redistribute it and/or modify
1205+ * it under the terms of the GNU General Public License version 3 as
1206+ * published by the Free Software Foundation.
1207+ *
1208+ * This program is distributed in the hope that it will be useful,
1209+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1210+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1211+ * GNU General Public License for more details.
1212+ *
1213+ * You should have received a copy of the GNU General Public License
1214+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1215+ *
1216+ * Authored by: Michi Henning <michi.henning@canonical.com>
1217+ */
1218+
1219+#ifndef UNITY_UTIL_FILEIO_H
1220+#define UNITY_UTIL_FILEIO_H
1221+
1222+#include <string>
1223+#include <vector>
1224+
1225+namespace unity
1226+{
1227+
1228+namespace util
1229+{
1230+
1231+std::string read_text_file(std::string const& filename);
1232+std::vector<uint8_t> read_binary_file(std::string const& filename);
1233+
1234+} // namespace util
1235+
1236+} // namespace unity
1237+
1238+#endif
1239
1240=== added file 'include/unity/util/NonCopyable.h'
1241--- include/unity/util/NonCopyable.h 1970-01-01 00:00:00 +0000
1242+++ include/unity/util/NonCopyable.h 2013-04-05 10:31:25 +0000
1243@@ -0,0 +1,87 @@
1244+/*
1245+ * Copyright (C) 2013 Canonical Ltd
1246+ *
1247+ * This program is free software: you can redistribute it and/or modify
1248+ * it under the terms of the GNU General Public License version 3 as
1249+ * published by the Free Software Foundation.
1250+ *
1251+ * This program is distributed in the hope that it will be useful,
1252+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1253+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1254+ * GNU General Public License for more details.
1255+ *
1256+ * You should have received a copy of the GNU General Public License
1257+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1258+ *
1259+ * Authored by: Michi Henning <michi.henning@canonical.com>
1260+ */
1261+
1262+//
1263+// Simple class to disable copy and assignment. (Provided here to avoid having to use
1264+// the equivalent boost version.)
1265+//
1266+// Use like this:
1267+//
1268+// class MyClass : private util::NonCopyable
1269+// {
1270+// // ...
1271+// };
1272+//
1273+
1274+#ifndef UNITY_UTIL_NONCOPYABLE_H
1275+#define UNITY_UTIL_NONCOPYABLE_H
1276+
1277+namespace unity
1278+{
1279+
1280+namespace util
1281+{
1282+
1283+namespace NonCopyable_ // Prevent unintended ADL
1284+{
1285+
1286+/**
1287+\brief Helper class to prevent a class from being copied.
1288+
1289+This class disables the copy constructor and assignment operator of a class to prevent it from being copied.
1290+This makes the fact that a class is not copyable immediately visible on reading the class definition,
1291+rather than having to read through the entire class to look for a copy constructor and assignment operator
1292+in the private section, or having to look for <code> = delete;</code> on the corresponding definitions.
1293+
1294+To use the class, use private inheritance:
1295+~~~
1296+* class MyClass : private unity::util::NonCopyable
1297+* {
1298+* public:
1299+* // MyClass cannot be copied now
1300+* // ...
1301+* };
1302+~~~
1303+
1304+\note Do not use public or protected inheritance for this class. Private inheritance prevents accidental polymorphism, such as
1305+~~~
1306+* void some_method(NonCopyable& param); // Bad, permits unrelated classes to be passed
1307+~~~
1308+
1309+*/
1310+
1311+class NonCopyable
1312+{
1313+protected:
1314+ NonCopyable() = default;
1315+ ~NonCopyable() = default;
1316+
1317+private:
1318+ NonCopyable(NonCopyable const&) = delete;
1319+ NonCopyable& operator=(NonCopyable const&) = delete;
1320+};
1321+
1322+} // namespace NonCopyable_
1323+
1324+typedef NonCopyable_::NonCopyable NonCopyable;
1325+
1326+} // namespace util
1327+
1328+} // namespace unity
1329+
1330+#endif
1331
1332=== added file 'include/unity/util/ResourcePtr.h'
1333--- include/unity/util/ResourcePtr.h 1970-01-01 00:00:00 +0000
1334+++ include/unity/util/ResourcePtr.h 2013-04-05 10:31:25 +0000
1335@@ -0,0 +1,788 @@
1336+/*
1337+ * Copyright (C) 2013 Canonical Ltd
1338+ *
1339+ * This program is free software: you can redistribute it and/or modify
1340+ * it under the terms of the GNU General Public License version 3 as
1341+ * published by the Free Software Foundation.
1342+ *
1343+ * This program is distributed in the hope that it will be useful,
1344+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1345+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1346+ * GNU General Public License for more details.
1347+ *
1348+ * You should have received a copy of the GNU General Public License
1349+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
1350+ *
1351+ * Authored by: Michi Henning <michi.henning@canonical.com>
1352+ */
1353+
1354+#ifndef UNITY_UTIL_RESOURCEPTR_H
1355+#define UNITY_UTIL_RESOURCEPTR_H
1356+
1357+#include <unity/util/NonCopyable.h>
1358+
1359+#include <boost/type_traits.hpp>
1360+
1361+#include <mutex>
1362+
1363+namespace unity
1364+{
1365+
1366+namespace util
1367+{
1368+
1369+namespace
1370+{
1371+
1372+// Simple helper class so we can adopt a lock without inconvenient syntax.
1373+
1374+template<typename T>
1375+class LockAdopter
1376+{
1377+public:
1378+ LockAdopter(T& mutex) noexcept
1379+ : m_(mutex, std::adopt_lock)
1380+ {
1381+ assert(!mutex.try_lock()); // Mutex must be locked to be adoptable.
1382+ }
1383+
1384+private:
1385+ std::unique_lock<T> m_;
1386+};
1387+
1388+} // namespace
1389+
1390+/**
1391+\brief Class to guarantee deallocation of arbitrary resources.
1392+
1393+ResourcePtr is a generalized resource pointer that guarantees deallocation.
1394+It is intended for arbitrary pairs of allocate/deallocate functions, such
1395+as <code>XCreateDisplay</code>/<code>XDestroyDisplay</code>.
1396+
1397+The resource managed by this class must be default-constructible, copy-constructible, and assignable.
1398+
1399+ResourcePtr essentially does what <code>std::unique_ptr</code> does, but it works with opaque types
1400+and resource allocation functions that do not return a pointer type, such as <code>open()</code>.
1401+
1402+ResourcePtr is thread-safe.
1403+
1404+\note Do not use reset() to set the resource to the "no resource allocated" state.
1405+ Instead, call dealloc() to do this. ResourcePtr has no idea
1406+ what a "not allocated" resource value looks like and therefore cannot test
1407+ for it. If you use reset() to install a "no resource allocated" value for
1408+ for the resource, the deleter will eventually be called with this value
1409+ as its argument. Whether this is benign or not depends on the deleter. For
1410+ example, <code>XFree()</code> must not be called with a <code>nullptr</code> argument.
1411+
1412+\note Do not call get() or release() if no resource is currently allocated.
1413+ Doing so throws <code>std::logic_error</code>.
1414+
1415+Here is an example that shows how to use this for a <code>glXCreateContext</code>/<code>GLXDestroyContext</code> pair.
1416+The returned <code>GLXContext</code> is a pointer to an opaque type; <code>std::unique_ptr</code> cannot be used
1417+for this, even with a custom deleter, because the signatures of the allocator and deallocator
1418+do not match <code>unique_ptr</code>'s expectations.
1419+
1420+~~~
1421+ResourcePtr<GLXContext, std::function<void(GLXContext)>> context =
1422+ std::bind(&glXDestroyContext, display_, std::placeholders::_1);
1423+~~~
1424+
1425+display_ is declared as
1426+
1427+~~~
1428+ Display* display_;
1429+~~~
1430+
1431+in this case.
1432+
1433+The deleter for the resource can return any type (including int, such as returned by <code>XDestroyWindow()</code>),
1434+and it must accept a single argument of the resource type (<code>GLXContext</code> in this example).
1435+
1436+<code>glXDestroyContext()</code> expects the display pointer as the first argument so, for this example,
1437+<code>std::bind</code> converts the binary <code>glXDestroyContext()</code> function into a
1438+unary function suitable as the deleter.
1439+
1440+Rather than mucking around with <code>std::bind</code>, it is often easier to use a lambda. For example:
1441+
1442+~~~
1443+ResourcePtr<GLXContext, std::function<void(GLXContext)>> context =
1444+ [this](GLXContext c) { this->dealloc_GLXContext(c); };
1445+~~~
1446+
1447+This calls a member function <code>dealloc_GLXContext()</code> that, in turn calls <code>glXDestroyContext()</code>
1448+and supplies the display parameter.
1449+
1450+\note Even though you can use ResourcePtr to deallocate dynamic memory, doing so is discouraged.
1451+Use <code>std::unique_ptr</code> instead, which is better suited to the task.
1452+*/
1453+
1454+// TODO: Discuss throwing deleters and requirements (copy constructible, etc.) on deleter.
1455+
1456+template<typename R, typename D>
1457+class ResourcePtr final : private NonCopyable
1458+{
1459+public:
1460+ /**
1461+ \typedef element_type
1462+ The type of resource managed by this ResourcePtr.
1463+ */
1464+ typedef R element_type;
1465+
1466+ /**
1467+ \typedef deleter_type
1468+ A function object or lvalue reference to a function or function object. The ResourcePtr
1469+ calls this to deallocate the resource.
1470+ */
1471+ typedef D deleter_type;
1472+
1473+ explicit ResourcePtr(D d);
1474+ ResourcePtr(R r, D d);
1475+ ResourcePtr(ResourcePtr&& r);
1476+ ResourcePtr& operator=(ResourcePtr&& r);
1477+ ~ResourcePtr() noexcept;
1478+
1479+ void swap(ResourcePtr& other);
1480+
1481+ void reset(R r);
1482+ R release();
1483+ void dealloc();
1484+
1485+ R get() const;
1486+ bool has_resource() const noexcept;
1487+ explicit operator bool() const noexcept;
1488+ D& get_deleter() noexcept;
1489+ D const& get_deleter() const noexcept;
1490+
1491+ typename std::enable_if<boost::has_equal_to<R>::value, bool>::type
1492+ operator==(ResourcePtr const& rhs) const;
1493+
1494+ typename std::enable_if<boost::has_equal_to<R>::value, bool>::type
1495+ operator!=(ResourcePtr const& rhs) const;
1496+
1497+ typename std::enable_if<boost::has_less<R>::value, bool>::type
1498+ operator<(ResourcePtr const& rhs) const;
1499+
1500+ typename std::enable_if<boost::has_less<R>::value &&
1501+ boost::has_equal_to<R>::value, bool>::type
1502+ operator<=(ResourcePtr const& rhs) const;
1503+
1504+ typename std::enable_if<boost::has_less<R>::value &&
1505+ boost::has_equal_to<R>::value, bool>::type
1506+ operator>(ResourcePtr const& rhs) const;
1507+
1508+ typename std::enable_if<boost::has_less<R>::value, bool>::type
1509+ operator>=(ResourcePtr const& rhs) const;
1510+
1511+private:
1512+ R resource_; // The managed resource.
1513+ D delete_; // The deleter to call.
1514+ bool initialized_; // True while we have a resource assigned.
1515+ mutable std::mutex m_; // Protects this instance.
1516+
1517+ typedef std::lock_guard<decltype(m_)> AutoLock;
1518+ typedef LockAdopter<decltype(m_)> AdoptLock;
1519+};
1520+
1521+/**
1522+Constructs a ResourcePtr with the specified deleter. No resource is held, so a call to has_resource()
1523+after constructing a ResourcePtr this way returns <code>false</code>.
1524+*/
1525+
1526+template<typename R, typename D>
1527+ResourcePtr<R, D>::
1528+ResourcePtr(D d)
1529+ : delete_(d), initialized_(false)
1530+{
1531+}
1532+
1533+/**
1534+Constructs a ResourcePtr with the specified resource and deleter. has_resource() returns <code>true</code> after
1535+calling this constructor.
1536+
1537+\note It is legal to pass a resource that represents the "not allocated" state. For example, the
1538+ following code passes the value <code>-1</code> to <code>close()</code> if the call to <code>open()</code> fails:
1539+
1540+~~~
1541+ResourcePtr<int, decltype(&::close)> fd(::open("/somefile", O_RDONLY), ::close);
1542+~~~
1543+ When the ResourcePtr goes out of scope, this results in a call to <code>close(-1)</code>. In this case,
1544+ the call with an invalid file descriptor is harmless (but causes noise from diagnostic tools, such as
1545+ <code>valgrind</code>). However, depending on the specific deleter, passing an invalid value to the deleter may
1546+ have more serious consequences.
1547+
1548+ To avoid the problem, you can delay initialization of the ResourcePtr until you know that the
1549+ resource was successfully allocated, for example:
1550+~~~
1551+ int tmp_fd = ::open(filename.c_str(), O_RDONLY);
1552+ if (tmp_fd == -1)
1553+ {
1554+ throw FileException(filename.c_str());
1555+ }
1556+ util::ResourcePtr<int, decltype(&::close)> fd(tmp_fd, ::close(fd));
1557+~~~
1558+ Alternatively, you can use a deleter function that tests the resource value
1559+ for validity and avoids calling the deleter with an invalid value:
1560+~~~
1561+ util::ResourcePtr<int, std::function<void(int)>> fd(
1562+ ::open(filename.c_str(), O_RDONLY),
1563+ [](int fd) { if (fd != -1) ::close(fd); }
1564+ );
1565+~~~
1566+ Note that, with the second approach, a call to get() will succeed and return -1 rather than throwing an
1567+ exception, so the first approach is the recommended one.
1568+*/
1569+
1570+template<typename R, typename D>
1571+ResourcePtr<R, D>::
1572+ResourcePtr(R r, D d)
1573+ : resource_(r), delete_(d), initialized_(true)
1574+{
1575+}
1576+
1577+/**
1578+Constructs a ResourcePtr by transferring ownership from <code>r</code> to <code>this</code>.
1579+
1580+If the resource's move or copy constructor throws, the exception is propagated to the caller.
1581+The strong exception guarantee is preserved if it is provided by the resource.
1582+*/
1583+// TODO: Mark as nothrow if the resource has a nothrow move constructor or nothrow copy constructor
1584+
1585+template<typename R, typename D>
1586+ResourcePtr<R, D>::
1587+ResourcePtr(ResourcePtr<R, D>&& r)
1588+ : resource_(std::move(r.resource_)), delete_(r.delete_), initialized_(r.initialized_)
1589+{
1590+ r.initialized_ = false; // Stop r from deleting its resource, if it held any. No need to lock: r is a temporary.
1591+}
1592+
1593+/**
1594+Assigns the resource held by <code>r</code>, transferring ownership. After the transfer,
1595+<code>r.has_resource()</code> returns <code>false</code>, and <code>this.has_resource()</code> returns
1596+the value of <code>r.has_resource()</code> prior to the assignment.
1597+*/
1598+// TODO: document exception safety behavior
1599+
1600+template<typename R, typename D>
1601+ResourcePtr<R, D>&
1602+ResourcePtr<R, D>::
1603+operator=(ResourcePtr&& r)
1604+{
1605+ AutoLock lock(m_);
1606+
1607+ if (initialized_) // If we hold a resource, deallocate it first.
1608+ {
1609+ initialized_ = false; // If the deleter throws, we will not try it again for the same resource.
1610+ delete_(resource_); // Delete our own resource.
1611+ }
1612+
1613+ // r is a temporary, so we don't need to lock it.
1614+
1615+ resource_ = std::move(r.resource_);
1616+ initialized_ = r.initialized_;
1617+ r.initialized_ = false; // Stop r from deleting its resource, if it held any.
1618+ delete_ = r.delete_;
1619+
1620+ return *this;
1621+}
1622+
1623+/**
1624+Destroys the ResourcePtr. If a resource is held, it calls the deleter for the current resource (if any).
1625+*/
1626+
1627+template<typename R, typename D>
1628+ResourcePtr<R, D>::
1629+~ResourcePtr() noexcept
1630+{
1631+ try
1632+ {
1633+ dealloc();
1634+ }
1635+ catch (...)
1636+ {
1637+ }
1638+}
1639+
1640+/**
1641+Swaps the resource and deleter of <code>this</code> with the resource and deleter of <code>other</code>
1642+using argument dependent lookup (ADL).
1643+
1644+If the underlying swap throws an exception, that exception is propagated to the caller, and the resource
1645+held by the ResourcePtr is unchanged.
1646+*/
1647+// TODO Split this into throw and no-throw versions depending on the underlying swap?
1648+
1649+template<typename R, typename D>
1650+void
1651+ResourcePtr<R, D>::
1652+swap(ResourcePtr& other)
1653+{
1654+ if (this == &other) // This is necessary to avoid deadlock for self-swap
1655+ {
1656+ return;
1657+ }
1658+
1659+ std::lock(m_, other.m_);
1660+ AdoptLock left(m_);
1661+ AdoptLock right(other.m_);
1662+
1663+ using std::swap; // Enable ADL
1664+ swap(resource_, other.resource_);
1665+ swap(delete_, other.delete_);
1666+ swap(initialized_, other.initialized_);
1667+}
1668+
1669+// The non-member swap() must be in the same namespace as ResourcePtr, so it will work with ADL. And, once it is
1670+// defined here, there is no point in adding a specialization to namespace std any longer, because ADL
1671+// will find it here anyway.
1672+
1673+/**
1674+Swaps the resource and deleter of <code>lhs</code> with the resource and deleter of <code>rhs</code>
1675+by calling <code>lhs.swap(rhs)</code>.
1676+
1677+If the underlying swap throws an exception, that exception is propagated to the caller, and the resource
1678+held by the ResourcePtr is unchanged.
1679+*/
1680+// TODO Split this into throw and no-throw versions depending on the underlying swap?
1681+
1682+template<typename R, typename D>
1683+void
1684+swap(unity::util::ResourcePtr<R, D>& lhs, unity::util::ResourcePtr<R, D>& rhs)
1685+{
1686+ lhs.swap(rhs);
1687+}
1688+
1689+/**
1690+Assigns a new resource to <code>this</code>, first deallocating the current resource (if any).
1691+
1692+If the deleter for the current resource throws an exception, the exception is propagated to the caller. In this
1693+case, the transfer of <code>r</code> to <code>this</code> is still carried out so, after the call to reset(),
1694+<code>this</code> manages <code>r</code>, whether the deleter throws or not. (If the deleter <i>does</i> throw,
1695+no attempt is made to call the deleter again for the same resource.)
1696+*/
1697+
1698+template<typename R, typename D>
1699+void
1700+ResourcePtr<R, D>::
1701+reset(R r)
1702+{
1703+ AutoLock lock(m_);
1704+
1705+ bool has_old = initialized_;
1706+ R old_resource;
1707+
1708+ if (has_old)
1709+ {
1710+ old_resource = resource_;
1711+ }
1712+ resource_ = r;
1713+ initialized_ = true; // If the deleter throws, we still satisfy the postcondition: resource_ == r.
1714+ if (has_old)
1715+ {
1716+ delete_(old_resource);
1717+ }
1718+}
1719+
1720+/**
1721+Releases ownership of the current resource without calling the deleter.
1722+\return The current resource.
1723+\throw std::logic_error if has_resource() is false.
1724+*/
1725+
1726+template<typename R, typename D>
1727+inline
1728+R
1729+ResourcePtr<R, D>::
1730+release()
1731+{
1732+ AutoLock lock(m_);
1733+
1734+ if (!initialized_)
1735+ {
1736+ throw std::logic_error("release() called on ResourcePtr without resource");
1737+ }
1738+ initialized_ = false;
1739+ return resource_;
1740+}
1741+
1742+/**
1743+Calls the deleter for the current resource.
1744+
1745+If the deleter throws, the resource is considered in the "not allocated" state,
1746+that is, no attempt is made to call the deleter again for this resource.
1747+*/
1748+
1749+template<typename R, typename D>
1750+void
1751+ResourcePtr<R, D>::
1752+dealloc()
1753+{
1754+ AutoLock lock(m_);
1755+
1756+ if (!initialized_)
1757+ {
1758+ return;
1759+ }
1760+ initialized_ = false; // If the deleter throws, we will not try it again for the same resource.
1761+ delete_(resource_);
1762+}
1763+
1764+/**
1765+Returns the current resource. If no resource is currently held, get() throws <code>std::logic_error</code>.
1766+\return The current resource (if any).
1767+
1768+If the resource's copy constructor throws an exception, that exception is propagated to the caller.
1769+
1770+\throw std::logic_error if has_resource() is false.
1771+*/
1772+
1773+template<typename R, typename D>
1774+inline
1775+R
1776+ResourcePtr<R, D>::
1777+get() const
1778+{
1779+ AutoLock lock(m_);
1780+
1781+ if (!initialized_)
1782+ {
1783+ throw std::logic_error("get() called on ResourcePtr without resource");
1784+ }
1785+ return resource_;
1786+}
1787+
1788+/**
1789+\return <code>true</code> if <code>this</code> currently manages a resource; <code>false</code>, otherwise.
1790+*/
1791+
1792+template<typename R, typename D>
1793+inline
1794+bool
1795+ResourcePtr<R, D>::
1796+has_resource() const noexcept
1797+{
1798+ AutoLock lock(m_);
1799+ return initialized_;
1800+}
1801+
1802+/**
1803+Synonym for has_resource().
1804+*/
1805+
1806+template<typename R, typename D>
1807+inline
1808+ResourcePtr<R, D>::
1809+operator bool() const noexcept
1810+{
1811+ return has_resource();
1812+}
1813+
1814+/**
1815+\return The deleter for the resource.
1816+*/
1817+
1818+template<typename R, typename D>
1819+inline
1820+D&
1821+ResourcePtr<R, D>::
1822+get_deleter() noexcept
1823+{
1824+ AutoLock lock(m_);
1825+ return delete_;
1826+}
1827+
1828+/**
1829+\return The deleter for the resource.
1830+*/
1831+
1832+template<typename R, typename D>
1833+inline
1834+D const&
1835+ResourcePtr<R, D>::
1836+get_deleter() const noexcept
1837+{
1838+ AutoLock lock(m_);
1839+ return delete_;
1840+}
1841+
1842+/**
1843+\brief Compares two instances for equality by calling the corresponding operator on the resource.
1844+
1845+Two instances that do not hold a resource are equal. An instance that does not hold a resource is not equal
1846+to any instance that holds a resource.
1847+
1848+If the underlying operator throws an exception, that exception is propagated to the caller.
1849+
1850+\note This operator is available only if the underlying resource provides <code>operator==</code>.
1851+*/
1852+
1853+template<typename R, typename D>
1854+typename std::enable_if<boost::has_equal_to<R>::value, bool>::type
1855+ResourcePtr<R, D>::
1856+operator==(ResourcePtr<R, D> const& rhs) const
1857+{
1858+ if (this == &rhs) // This is necessary to avoid deadlock for self-comparison
1859+ {
1860+ return true;
1861+ }
1862+
1863+ std::lock(m_, rhs.m_);
1864+ AdoptLock left(m_);
1865+ AdoptLock right(rhs.m_);
1866+
1867+ if (!initialized_)
1868+ {
1869+ return !rhs.initialized_; // Equal if both are not initialized
1870+ }
1871+ else if (!rhs.initialized_)
1872+ {
1873+ return false; // Not equal if lhs initialized, but rhs not initialized
1874+ }
1875+ else
1876+ {
1877+ return resource_ == rhs.resource_;
1878+ }
1879+}
1880+
1881+/**
1882+\brief Compares two instances for inequality by calling the corresponding operator on the resource.
1883+
1884+If the underlying operator throws an exception, that exception is propagated to the caller.
1885+
1886+\note This operator is available only if the underlying resource provides <code>operator!=</code>.
1887+*/
1888+
1889+template<typename R, typename D>
1890+inline
1891+typename std::enable_if<boost::has_equal_to<R>::value, bool>::type
1892+ResourcePtr<R, D>::
1893+operator!=(ResourcePtr<R, D> const& rhs) const
1894+{
1895+ return !(*this == rhs);
1896+}
1897+
1898+/**
1899+\brief Returns <code>true</code> if <code>this</code> is less than <code>rhs</code> by calling the
1900+corresponding operator on the resource.
1901+
1902+An instance that does not hold a resource is less than any instance that holds a resource.
1903+
1904+If the underlying operator throws an exception, that exception is propagated to the caller.
1905+
1906+\note This operator is available only if the underlying resource provides <code>operator\<</code>.
1907+*/
1908+
1909+template<typename R, typename D>
1910+typename std::enable_if<boost::has_less<R>::value, bool>::type
1911+ResourcePtr<R, D>::
1912+operator<(ResourcePtr<R, D> const& rhs) const
1913+{
1914+ if (this == &rhs) // This is necessary to avoid deadlock for self-comparison
1915+ {
1916+ return false;
1917+ }
1918+
1919+ std::lock(m_, rhs.m_);
1920+ AdoptLock left(m_);
1921+ AdoptLock right(rhs.m_);
1922+
1923+ if (!initialized_)
1924+ {
1925+ return rhs.initialized_; // Not initialized is less than initialized
1926+ }
1927+ else if (!rhs.initialized_) // Initialized is not less than not initialized
1928+ {
1929+ return false;
1930+ }
1931+ else
1932+ {
1933+ return resource_ < rhs.resource_;
1934+ }
1935+}
1936+
1937+/**
1938+\brief Returns <code>true</code> if <code>this</code> is less than or equal to <code>rhs</code> by calling the
1939+corresponding operator on the resource.
1940+
1941+An instance that does not hold a resource is less than any instance that holds a resource.
1942+Two instances that do not hold a resource are equal.
1943+
1944+If the underlying operator throws an exception, that exception is propagated to the caller.
1945+
1946+\note This operator is available only if the underlying resource provides <code>operator\<=</code>.
1947+*/
1948+
1949+template<typename R, typename D>
1950+typename std::enable_if<boost::has_less<R>::value && boost::has_equal_to<R>::value, bool>::type
1951+ResourcePtr<R, D>::
1952+operator<=(ResourcePtr<R, D> const& rhs) const
1953+{
1954+ if (this == &rhs) // This is necessary to avoid deadlock for self-comparison
1955+ {
1956+ return true;
1957+ }
1958+
1959+ // We can't just write:
1960+ //
1961+ // return *this < rhs || *this == rhs;
1962+ //
1963+ // because that creates a race condition: the locks would be released and
1964+ // re-aquired in between the two comparisons.
1965+
1966+ std::lock(m_, rhs.m_);
1967+ AdoptLock left(m_);
1968+ AdoptLock right(rhs.m_);
1969+
1970+ return resource_ < rhs.resource_ || resource_ == rhs.resource_;
1971+}
1972+
1973+/**
1974+\brief Returns <code>true</code> if <code>this</code> is greater than <code>rhs</code> by calling the
1975+corresponding operator on the resource.
1976+
1977+An instance that holds a resource is greater than any instance that does not hold a resource.
1978+
1979+If the underlying operator throws an exception, that exception is propagated to the caller.
1980+
1981+\note This operator is available only if the underlying resource provides <code>operator\></code>.
1982+*/
1983+
1984+template<typename R, typename D>
1985+inline
1986+typename std::enable_if<boost::has_less<R>::value && boost::has_equal_to<R>::value, bool>::type
1987+ResourcePtr<R, D>::
1988+operator>(ResourcePtr<R, D> const& rhs) const
1989+{
1990+ return !(*this <= rhs);
1991+}
1992+
1993+/**
1994+\brief Returns <code>true</code> if <code>this</code> is greater than or equal to <code>rhs</code> by calling the
1995+corresponding operator on the resource.
1996+
1997+An instance that holds a resource is greater than any instance that does not hold a resource.
1998+Two instances that do not hold a resource are equal.
1999+
2000+If the underlying operator throws an exception, that exception is propagated to the caller.
2001+
2002+\note This operator is available only if the underlying resource provides <code>operator\>=</code>.
2003+*/
2004+
2005+template<typename R, typename D>
2006+inline
2007+typename std::enable_if<boost::has_less<R>::value, bool>::type
2008+ResourcePtr<R, D>::
2009+operator>=(ResourcePtr<R, D> const& rhs) const
2010+{
2011+ return !(*this < rhs);
2012+}
2013+
2014+} // namespace util
2015+
2016+} // namespace unity
2017+
2018+// Specializations in namespace std, so we play nicely with STL and metaprogramming.
2019+
2020+namespace std
2021+{
2022+
2023+/**
2024+\brief Function object for equality comparison.
2025+*/
2026+
2027+template<typename R, typename D>
2028+struct equal_to<unity::util::ResourcePtr<R, D>>
2029+{
2030+ /**
2031+ Invokes <code>operator==</code> on <code>lhs</code>.
2032+ */
2033+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2034+ {
2035+ return lhs == rhs;
2036+ }
2037+};
2038+
2039+/**
2040+\brief Function object for inequality comparison.
2041+*/
2042+
2043+template<typename R, typename D>
2044+struct not_equal_to<unity::util::ResourcePtr<R, D>>
2045+{
2046+ /**
2047+ Invokes <code>operator!=</code> on <code>lhs</code>.
2048+ */
2049+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2050+ {
2051+ return lhs != rhs;
2052+ }
2053+};
2054+
2055+/**
2056+\brief Function object for less than comparison.
2057+*/
2058+
2059+template<typename R, typename D>
2060+struct less<unity::util::ResourcePtr<R, D>>
2061+{
2062+ /**
2063+ Invokes <code>operator\<</code> on <code>lhs</code>.
2064+ */
2065+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2066+ {
2067+ return lhs < rhs;
2068+ }
2069+};
2070+
2071+/**
2072+\brief Function object for less than or equal comparison.
2073+*/
2074+
2075+template<typename R, typename D>
2076+struct less_equal<unity::util::ResourcePtr<R, D>>
2077+{
2078+ /**
2079+ Invokes <code>operator\<=</code> on <code>lhs</code>.
2080+ */
2081+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2082+ {
2083+ return lhs <= rhs;
2084+ }
2085+};
2086+
2087+/**
2088+\brief Function object for greater than comparison.
2089+*/
2090+
2091+template<typename R, typename D>
2092+struct greater<unity::util::ResourcePtr<R, D>>
2093+{
2094+ /**
2095+ Invokes <code>operator\></code> on <code>lhs</code>.
2096+ */
2097+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2098+ {
2099+ return lhs > rhs;
2100+ }
2101+};
2102+
2103+/**
2104+\brief Function object for less than or equal comparison.
2105+*/
2106+
2107+template<typename R, typename D>
2108+struct greater_equal<unity::util::ResourcePtr<R, D>>
2109+{
2110+ /**
2111+ Invokes <code>operator\>=</code> on <code>lhs</code>.
2112+ */
2113+ bool operator()(unity::util::ResourcePtr<R, D> const& lhs, unity::util::ResourcePtr<R, D> const& rhs) const
2114+ {
2115+ return lhs >= rhs;
2116+ }
2117+};
2118+
2119+// TODO: provide hash if std::hash<R> exists.
2120+
2121+} // namespace std
2122+
2123+#endif
2124
2125=== added directory 'include/unity/util/internal'
2126=== added file 'include/unity/util/internal/DaemonImpl.h'
2127--- include/unity/util/internal/DaemonImpl.h 1970-01-01 00:00:00 +0000
2128+++ include/unity/util/internal/DaemonImpl.h 2013-04-05 10:31:25 +0000
2129@@ -0,0 +1,67 @@
2130+/*
2131+ * Copyright (C) 2013 Canonical Ltd
2132+ *
2133+ * This program is free software: you can redistribute it and/or modify
2134+ * it under the terms of the GNU General Public License version 3 as
2135+ * published by the Free Software Foundation.
2136+ *
2137+ * This program is distributed in the hope that it will be useful,
2138+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2139+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2140+ * GNU General Public License for more details.
2141+ *
2142+ * You should have received a copy of the GNU General Public License
2143+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2144+ *
2145+ * Authored by: Michi Henning <michi.henning@canonical.com>
2146+ */
2147+
2148+#ifndef UNITY_UTIL_DAEMONIMPL_H
2149+#define UNITY_UTIL_DAEMONIMPL_H
2150+
2151+#include <unity/UnityExceptions.h>
2152+#include <unity/util/NonCopyable.h>
2153+
2154+#include <sys/types.h>
2155+
2156+#include <string>
2157+
2158+namespace unity
2159+{
2160+
2161+namespace util
2162+{
2163+
2164+namespace internal
2165+{
2166+
2167+class DaemonImpl final : private NonCopyable
2168+{
2169+public:
2170+ DaemonImpl();
2171+ ~DaemonImpl() = default;
2172+
2173+ void close_fds() noexcept;
2174+ void reset_signals() noexcept;
2175+ void set_umask(mode_t mask) noexcept;
2176+ void set_working_directory(std::string const& working_directory);
2177+
2178+ void daemonize_me();
2179+
2180+private:
2181+ bool close_fds_;
2182+ bool reset_signals_;
2183+ bool set_umask_;
2184+ mode_t umask_;
2185+ std::string working_directory_;
2186+
2187+ void close_open_files() noexcept;
2188+};
2189+
2190+} // namespace internal
2191+
2192+} // namespace util
2193+
2194+} // namespace unity
2195+
2196+#endif
2197
2198=== modified file 'plugins/HudClient/hudclient.cpp'
2199--- plugins/HudClient/hudclient.cpp 2013-02-14 16:39:59 +0000
2200+++ plugins/HudClient/hudclient.cpp 2013-04-05 10:31:25 +0000
2201@@ -20,41 +20,51 @@
2202
2203 #include <QDebug>
2204
2205-static void loadingCB(GObject* /*src*/, gpointer dst)
2206+namespace
2207+{
2208+
2209+extern "C"
2210+{
2211+
2212+void loadingCB(GObject* /*src*/, gpointer dst)
2213 {
2214 static_cast<HudClient*>(dst)->voiceQueryLoading();
2215 }
2216
2217-static void listeningCB(GObject* /*src*/, gpointer dst)
2218+void listeningCB(GObject* /*src*/, gpointer dst)
2219 {
2220 static_cast<HudClient*>(dst)->voiceQueryListening();
2221 }
2222
2223-static void heardSomethingCB(GObject* /*src*/, gpointer dst)
2224+void heardSomethingCB(GObject* /*src*/, gpointer dst)
2225 {
2226 static_cast<HudClient*>(dst)->voiceQueryHeardSomething();
2227 }
2228
2229-static void failedCB(GObject* /*src*/, const gchar * /*reason*/, gpointer dst)
2230+void failedCB(GObject* /*src*/, const gchar * /*reason*/, gpointer dst)
2231 {
2232 static_cast<HudClient*>(dst)->voiceQueryFailed();
2233 }
2234
2235-static void finishedCB(GObject* /*src*/, const gchar* query, gpointer dst)
2236+void finishedCB(GObject* /*src*/, const gchar* query, gpointer dst)
2237 {
2238 static_cast<HudClient*>(dst)->voiceQueryFinished(QString::fromUtf8(query));
2239 }
2240
2241-static void modelReadyCB(GObject* /*src*/, gpointer dst)
2242+void modelReadyCB(GObject* /*src*/, gpointer dst)
2243 {
2244 static_cast<HudClient*>(dst)->modelReady(true);
2245 }
2246
2247-static void modelReallyReadyCB(GObject* /*src*/, gint /*position*/, gint /*removed*/, gint /*added*/, gpointer dst)
2248+void modelReallyReadyCB(GObject* /*src*/, gint /*position*/, gint /*removed*/, gint /*added*/, gpointer dst)
2249 {
2250 static_cast<HudClient*>(dst)->modelReallyReady(true);
2251 }
2252
2253+} // extern "C"
2254+
2255+} // namespace
2256+
2257 HudClient::HudClient()
2258 {
2259 m_results = new DeeListModel();
2260
2261=== added directory 'src'
2262=== added file 'src/CMakeLists.txt'
2263--- src/CMakeLists.txt 1970-01-01 00:00:00 +0000
2264+++ src/CMakeLists.txt 2013-04-05 10:31:25 +0000
2265@@ -0,0 +1,23 @@
2266+#
2267+# Copyright (C) 2013 Canonical Ltd
2268+#
2269+# This program is free software: you can redistribute it and/or modify
2270+# it under the terms of the GNU General Public License version 3 as
2271+# published by the Free Software Foundation.
2272+#
2273+# This program is distributed in the hope that it will be useful,
2274+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2275+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2276+# GNU General Public License for more details.
2277+#
2278+# You should have received a copy of the GNU General Public License
2279+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2280+#
2281+# Authored by: Michi Henning <michi.henning@canonical.com>
2282+#
2283+
2284+add_subdirectory(unity)
2285+
2286+add_library(${UNITY_API_LIB} SHARED ${UNITY_API_LIB_SRC})
2287+
2288+install(TARGETS ${UNITY_API_LIB} LIBRARY DESTINATION lib)
2289
2290=== added directory 'src/unity'
2291=== added file 'src/unity/CMakeLists.txt'
2292--- src/unity/CMakeLists.txt 1970-01-01 00:00:00 +0000
2293+++ src/unity/CMakeLists.txt 2013-04-05 10:31:25 +0000
2294@@ -0,0 +1,28 @@
2295+#
2296+# Copyright (C) 2013 Canonical Ltd
2297+#
2298+# This program is free software: you can redistribute it and/or modify
2299+# it under the terms of the GNU General Public License version 3 as
2300+# published by the Free Software Foundation.
2301+#
2302+# This program is distributed in the hope that it will be useful,
2303+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2304+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2305+# GNU General Public License for more details.
2306+#
2307+# You should have received a copy of the GNU General Public License
2308+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2309+#
2310+# Authored by: Michi Henning <michi.henning@canonical.com>
2311+#
2312+
2313+add_subdirectory(api)
2314+add_subdirectory(internal)
2315+add_subdirectory(util)
2316+
2317+set(UNITY_SRC
2318+ ${CMAKE_CURRENT_SOURCE_DIR}/Exception.cpp
2319+ ${CMAKE_CURRENT_SOURCE_DIR}/UnityExceptions.cpp
2320+)
2321+
2322+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UNITY_SRC} PARENT_SCOPE)
2323
2324=== added file 'src/unity/Exception.cpp'
2325--- src/unity/Exception.cpp 1970-01-01 00:00:00 +0000
2326+++ src/unity/Exception.cpp 2013-04-05 10:31:25 +0000
2327@@ -0,0 +1,145 @@
2328+/*
2329+ * Copyright (C) 2012 Canonical Ltd
2330+ *
2331+ * This program is free software: you can redistribute it and/or modify
2332+ * it under the terms of the GNU General Public License version 3 as
2333+ * published by the Free Software Foundation.
2334+ *
2335+ * This program is distributed in the hope that it will be useful,
2336+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2337+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2338+ * GNU General Public License for more details.
2339+ *
2340+ * You should have received a copy of the GNU General Public License
2341+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2342+ *
2343+ * Authored by: Michi Henning <michi.henning@canonical.com>
2344+ */
2345+
2346+#include <unity/Exception.h>
2347+#include <unity/internal/ExceptionImpl.h>
2348+
2349+using namespace std;
2350+
2351+namespace unity
2352+{
2353+
2354+//! @cond
2355+
2356+Exception::
2357+Exception(shared_ptr<internal::ExceptionImpl> const& derived)
2358+ : p_(derived)
2359+{
2360+}
2361+
2362+Exception::
2363+Exception(Exception const&) = default;
2364+
2365+Exception&
2366+Exception::
2367+operator=(Exception const&) = default;
2368+
2369+Exception::
2370+~Exception() noexcept = default;
2371+
2372+//! @endcond
2373+
2374+/**
2375+\brief Returns the reason set by the derived class's constructor (empty string if none).
2376+
2377+Derived classes should include any other state information, such as the value of data members or
2378+other relevant detail in the <code>reason</code> string they pass to the protected constructor.
2379+*/
2380+
2381+string
2382+Exception::
2383+reason() const
2384+{
2385+ return p_->reason();
2386+}
2387+
2388+/**
2389+Returns a string describing the exception, including any exceptions that were nested or chained.
2390+
2391+Nested exceptions are indented according to their nesting level. If the exception contains chained
2392+exceptions, these are shown in oldest-to-newest order.
2393+
2394+\param indent This controls the amount of indenting per level. The default indent is four spaces.
2395+\return The string describing the exception.
2396+
2397+\note The default implementation of this member function calls <code>to_string(0, indent)</code>.
2398+*/
2399+
2400+string
2401+Exception::
2402+to_string(std::string const& indent) const
2403+{
2404+ return p_->to_string(*this, 0, indent);
2405+}
2406+
2407+/**
2408+Returns a string describing the exception, including any exceptions that were nested or chained.
2409+
2410+Nested exceptions are indented according to their nesting level. If the exception contains chained
2411+exceptions, these are shown in oldest-to-newest order.
2412+
2413+\param indent_level This controls the outermost indent level. The value <code>0</code> indicates
2414+ the outermost level (no indent).
2415+\param indent This controls the amount of indenting per level. The pass string is prependended
2416+ <i><code>indent_level</code></i> times to each line.
2417+\return The string describing the exception.
2418+
2419+\note This member function has a default implementation, so derived classes do not need to override it
2420+ unless they want to change the formatting of the returned string.
2421+*/
2422+
2423+string
2424+Exception::
2425+to_string(int indent_level, std::string const& indent) const
2426+{
2427+ return p_->to_string(*this, indent_level, indent);
2428+}
2429+
2430+/**
2431+Adds an exception to the exception history chain.
2432+
2433+\param earlier_exception The parameter must be a <code>nullptr</code> or a <code>std::exception_ptr</code>
2434+to an exception that was remembered earlier. This allows a sequence of exceptions to be remembered without
2435+having to throw them and is useful for example, in shutdown scenarios where any one of a sequence of steps
2436+can fail, but we want to continue and try all the following steps and only throw after all of them have been
2437+tried. In this case, each step that fails can add itself to the sequence of remembered exceptions, and finally
2438+throw something like <code>ShutdownException</code>.
2439+\return A <code>std::exception_ptr</code> to <code>this</code>.
2440+*/
2441+
2442+exception_ptr
2443+Exception::
2444+remember(exception_ptr earlier_exception)
2445+{
2446+ return p_->remember(this, earlier_exception);
2447+}
2448+
2449+/**
2450+Returns the previous exception.
2451+\return Returns the next-older remembered exception, or <code>nullptr</code>, if none.
2452+*/
2453+
2454+exception_ptr
2455+Exception::
2456+get_earlier() const noexcept
2457+{
2458+ return p_->get_earlier();
2459+}
2460+
2461+//! @cond
2462+
2463+internal::ExceptionImpl*
2464+Exception::
2465+pimpl() const noexcept
2466+{
2467+ return p_.get();
2468+}
2469+
2470+//! @endcond
2471+
2472+} // namespace unity
2473
2474=== added file 'src/unity/UnityExceptions.cpp'
2475--- src/unity/UnityExceptions.cpp 1970-01-01 00:00:00 +0000
2476+++ src/unity/UnityExceptions.cpp 2013-04-05 10:31:25 +0000
2477@@ -0,0 +1,246 @@
2478+/*
2479+ * Copyright (C) 2012 Canonical Ltd
2480+ *
2481+ * This program is free software: you can redistribute it and/or modify
2482+ * it under the terms of the GNU General Public License version 3 as
2483+ * published by the Free Software Foundation.
2484+ *
2485+ * This program is distributed in the hope that it will be useful,
2486+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2487+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2488+ * GNU General Public License for more details.
2489+ *
2490+ * You should have received a copy of the GNU General Public License
2491+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2492+ *
2493+ * Authored by: Michi Henning <michi.henning@canonical.com>
2494+ */
2495+
2496+#include <unity/UnityExceptions.h>
2497+#include <unity/internal/UnityExceptionsImpl.h>
2498+
2499+using namespace std;
2500+
2501+namespace unity
2502+{
2503+
2504+InvalidArgumentException::
2505+InvalidArgumentException(string const& reason)
2506+ : Exception(make_shared<internal::InvalidArgumentExceptionImpl>(reason))
2507+{
2508+}
2509+
2510+InvalidArgumentException::
2511+InvalidArgumentException(InvalidArgumentException const&) = default;
2512+
2513+//! @cond
2514+
2515+InvalidArgumentException&
2516+InvalidArgumentException::
2517+operator=(InvalidArgumentException const&) = default;
2518+
2519+
2520+InvalidArgumentException::
2521+~InvalidArgumentException() noexcept = default;
2522+
2523+//! @endcond
2524+
2525+char const*
2526+InvalidArgumentException::
2527+what() const noexcept
2528+{
2529+ return dynamic_cast<internal::InvalidArgumentExceptionImpl*>(pimpl())->what();
2530+}
2531+
2532+exception_ptr
2533+InvalidArgumentException::
2534+self() const
2535+{
2536+ return make_exception_ptr(*this);
2537+}
2538+
2539+LogicException::
2540+LogicException(string const& reason)
2541+ : Exception(make_shared<internal::LogicExceptionImpl>(reason))
2542+{
2543+}
2544+
2545+LogicException::
2546+LogicException(LogicException const&) = default;
2547+
2548+//! @cond
2549+
2550+LogicException&
2551+LogicException::
2552+operator=(LogicException const&) = default;
2553+
2554+LogicException::
2555+~LogicException() noexcept = default;
2556+
2557+//! @endcond
2558+
2559+char const*
2560+LogicException::
2561+what() const noexcept
2562+{
2563+ return dynamic_cast<internal::LogicExceptionImpl*>(pimpl())->what();
2564+}
2565+
2566+exception_ptr
2567+LogicException::
2568+self() const
2569+{
2570+ return make_exception_ptr(*this);
2571+}
2572+
2573+ShutdownException::
2574+ShutdownException(string const& reason)
2575+ : Exception(make_shared<internal::ShutdownExceptionImpl>(reason))
2576+{
2577+}
2578+
2579+ShutdownException::
2580+ShutdownException(ShutdownException const&) = default;
2581+
2582+//! @cond
2583+
2584+ShutdownException&
2585+ShutdownException::
2586+operator=(ShutdownException const&) = default;
2587+
2588+ShutdownException::
2589+~ShutdownException() noexcept = default;
2590+
2591+//! @endcond
2592+
2593+char const*
2594+ShutdownException::
2595+what() const noexcept
2596+{
2597+ return dynamic_cast<internal::ShutdownExceptionImpl*>(pimpl())->what();
2598+}
2599+
2600+exception_ptr
2601+ShutdownException::
2602+self() const
2603+{
2604+ return make_exception_ptr(*this);
2605+}
2606+
2607+FileException::
2608+FileException(string const& reason, int err)
2609+ : Exception(make_shared<internal::FileExceptionImpl>(reason, err))
2610+{
2611+}
2612+
2613+FileException::
2614+FileException(FileException const&) = default;
2615+
2616+//! @cond
2617+
2618+FileException&
2619+FileException::
2620+operator=(FileException const&) = default;
2621+
2622+FileException::
2623+~FileException() noexcept = default;
2624+
2625+//! @endcond
2626+
2627+char const*
2628+FileException::
2629+what() const noexcept
2630+{
2631+ return dynamic_cast<internal::FileExceptionImpl*>(pimpl())->what();
2632+}
2633+
2634+int
2635+FileException::
2636+error() const noexcept
2637+{
2638+ return dynamic_cast<internal::FileExceptionImpl*>(pimpl())->error();
2639+}
2640+
2641+exception_ptr
2642+FileException::
2643+self() const
2644+{
2645+ return make_exception_ptr(*this);
2646+}
2647+
2648+SyscallException::
2649+SyscallException(string const& reason, int err)
2650+ : Exception(make_shared<internal::SyscallExceptionImpl>(reason, err))
2651+{
2652+}
2653+
2654+SyscallException::
2655+SyscallException(SyscallException const&) = default;
2656+
2657+//! @cond
2658+
2659+SyscallException&
2660+SyscallException::
2661+operator=(SyscallException const&) = default;
2662+
2663+SyscallException::
2664+~SyscallException() noexcept = default;
2665+
2666+//! @endcond
2667+
2668+char const*
2669+SyscallException::
2670+what() const noexcept
2671+{
2672+ return dynamic_cast<internal::SyscallExceptionImpl*>(pimpl())->what();
2673+}
2674+
2675+int
2676+SyscallException::
2677+error() const noexcept
2678+{
2679+ return dynamic_cast<internal::SyscallExceptionImpl*>(pimpl())->error();
2680+}
2681+
2682+exception_ptr
2683+SyscallException::
2684+self() const
2685+{
2686+ return make_exception_ptr(*this);
2687+}
2688+
2689+ResourceException::
2690+ResourceException(string const& reason)
2691+ : Exception(make_shared<internal::ResourceExceptionImpl>(reason))
2692+{
2693+}
2694+
2695+ResourceException::
2696+ResourceException(ResourceException const&) = default;
2697+
2698+//! @cond
2699+
2700+ResourceException&
2701+ResourceException::
2702+operator=(ResourceException const&) = default;
2703+
2704+ResourceException::
2705+~ResourceException() noexcept = default;
2706+
2707+//! @endcond
2708+
2709+char const*
2710+ResourceException::
2711+what() const noexcept
2712+{
2713+ return dynamic_cast<internal::ResourceExceptionImpl*>(pimpl())->what();
2714+}
2715+
2716+exception_ptr
2717+ResourceException::
2718+self() const
2719+{
2720+ return make_exception_ptr(*this);
2721+}
2722+
2723+} // namespace unity
2724
2725=== added directory 'src/unity/api'
2726=== added file 'src/unity/api/CMakeLists.txt'
2727--- src/unity/api/CMakeLists.txt 1970-01-01 00:00:00 +0000
2728+++ src/unity/api/CMakeLists.txt 2013-04-05 10:31:25 +0000
2729@@ -0,0 +1,26 @@
2730+#
2731+# Copyright (C) 2013 Canonical Ltd
2732+#
2733+# This program is free software: you can redistribute it and/or modify
2734+# it under the terms of the GNU General Public License version 3 as
2735+# published by the Free Software Foundation.
2736+#
2737+# This program is distributed in the hope that it will be useful,
2738+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2739+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2740+# GNU General Public License for more details.
2741+#
2742+# You should have received a copy of the GNU General Public License
2743+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2744+#
2745+# Authored by: Michi Henning <michi.henning@canonical.com>
2746+#
2747+
2748+add_subdirectory(internal)
2749+add_subdirectory(scopes)
2750+
2751+set(API_SRC
2752+ ${CMAKE_CURRENT_SOURCE_DIR}/Version.cpp
2753+)
2754+
2755+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${API_SRC} PARENT_SCOPE)
2756
2757=== added file 'src/unity/api/Version.cpp'
2758--- src/unity/api/Version.cpp 1970-01-01 00:00:00 +0000
2759+++ src/unity/api/Version.cpp 2013-04-05 10:31:25 +0000
2760@@ -0,0 +1,59 @@
2761+/*
2762+ * Copyright (C) 2013 Canonical Ltd
2763+ *
2764+ * This program is free software: you can redistribute it and/or modify
2765+ * it under the terms of the GNU General Public License version 3 as
2766+ * published by the Free Software Foundation.
2767+ *
2768+ * This program is distributed in the hope that it will be useful,
2769+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2770+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2771+ * GNU General Public License for more details.
2772+ *
2773+ * You should have received a copy of the GNU General Public License
2774+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2775+ *
2776+ * Authored by: Michi Henning <michi.henning@canonical.com>
2777+ */
2778+
2779+#include <unity/api/Version.h>
2780+
2781+using namespace std;
2782+
2783+namespace unity
2784+{
2785+
2786+namespace api
2787+{
2788+
2789+int
2790+Version::
2791+major_version()
2792+{
2793+ return UNITY_API_VERSION_MAJOR;
2794+}
2795+
2796+int
2797+Version::
2798+minor_version()
2799+{
2800+ return UNITY_API_VERSION_MINOR;
2801+}
2802+
2803+int
2804+Version::
2805+micro_version()
2806+{
2807+ return UNITY_API_VERSION_MICRO;
2808+}
2809+
2810+char const*
2811+Version::
2812+str()
2813+{
2814+ return UNITY_API_VERSION_STRING;
2815+}
2816+
2817+} // namespace api
2818+
2819+} // namespace unity
2820
2821=== added directory 'src/unity/api/internal'
2822=== added file 'src/unity/api/internal/CMakeLists.txt'
2823--- src/unity/api/internal/CMakeLists.txt 1970-01-01 00:00:00 +0000
2824+++ src/unity/api/internal/CMakeLists.txt 2013-04-05 10:31:25 +0000
2825@@ -0,0 +1,22 @@
2826+#
2827+# Copyright (C) 2013 Canonical Ltd
2828+#
2829+# This program is free software: you can redistribute it and/or modify
2830+# it under the terms of the GNU General Public License version 3 as
2831+# published by the Free Software Foundation.
2832+#
2833+# This program is distributed in the hope that it will be useful,
2834+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2835+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2836+# GNU General Public License for more details.
2837+#
2838+# You should have received a copy of the GNU General Public License
2839+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2840+#
2841+# Authored by: Michi Henning <michi.henning@canonical.com>
2842+#
2843+
2844+set(API_INTERNAL_SRC
2845+)
2846+
2847+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${API_INTERNAL_SRC} PARENT_SCOPE)
2848
2849=== added directory 'src/unity/api/scopes'
2850=== added file 'src/unity/api/scopes/CMakeLists.txt'
2851--- src/unity/api/scopes/CMakeLists.txt 1970-01-01 00:00:00 +0000
2852+++ src/unity/api/scopes/CMakeLists.txt 2013-04-05 10:31:25 +0000
2853@@ -0,0 +1,24 @@
2854+#
2855+# Copyright (C) 2013 Canonical Ltd
2856+#
2857+# This program is free software: you can redistribute it and/or modify
2858+# it under the terms of the GNU General Public License version 3 as
2859+# published by the Free Software Foundation.
2860+#
2861+# This program is distributed in the hope that it will be useful,
2862+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2863+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2864+# GNU General Public License for more details.
2865+#
2866+# You should have received a copy of the GNU General Public License
2867+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2868+#
2869+# Authored by: Michi Henning <michi.henning@canonical.com>
2870+#
2871+
2872+add_subdirectory(internal)
2873+
2874+set(SCOPES_SRC
2875+)
2876+
2877+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${SCOPES_SRC} PARENT_SCOPE)
2878
2879=== added directory 'src/unity/api/scopes/internal'
2880=== added file 'src/unity/api/scopes/internal/CMakeLists.txt'
2881--- src/unity/api/scopes/internal/CMakeLists.txt 1970-01-01 00:00:00 +0000
2882+++ src/unity/api/scopes/internal/CMakeLists.txt 2013-04-05 10:31:25 +0000
2883@@ -0,0 +1,22 @@
2884+#
2885+# Copyright (C) 2013 Canonical Ltd
2886+#
2887+# This program is free software: you can redistribute it and/or modify
2888+# it under the terms of the GNU General Public License version 3 as
2889+# published by the Free Software Foundation.
2890+#
2891+# This program is distributed in the hope that it will be useful,
2892+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2893+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2894+# GNU General Public License for more details.
2895+#
2896+# You should have received a copy of the GNU General Public License
2897+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2898+#
2899+# Authored by: Michi Henning <michi.henning@canonical.com>
2900+#
2901+
2902+set(SCOPES_INTERNAL_SRC
2903+)
2904+
2905+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UNITY_SCOPES_INTERNAL_SRC} PARENT_SCOPE)
2906
2907=== added directory 'src/unity/internal'
2908=== added file 'src/unity/internal/CMakeLists.txt'
2909--- src/unity/internal/CMakeLists.txt 1970-01-01 00:00:00 +0000
2910+++ src/unity/internal/CMakeLists.txt 2013-04-05 10:31:25 +0000
2911@@ -0,0 +1,24 @@
2912+#
2913+# Copyright (C) 2013 Canonical Ltd
2914+#
2915+# This program is free software: you can redistribute it and/or modify
2916+# it under the terms of the GNU General Public License version 3 as
2917+# published by the Free Software Foundation.
2918+#
2919+# This program is distributed in the hope that it will be useful,
2920+# but WITHOUT ANY WARRANTY; without even the implied warranty of
2921+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2922+# GNU General Public License for more details.
2923+#
2924+# You should have received a copy of the GNU General Public License
2925+# along with this program. If not, see <http://www.gnu.org/licenses/>.
2926+#
2927+# Authored by: Michi Henning <michi.henning@canonical.com>
2928+#
2929+
2930+set(UNITY_INTERNAL_SRC
2931+ ${CMAKE_CURRENT_SOURCE_DIR}/ExceptionImpl.cpp
2932+ ${CMAKE_CURRENT_SOURCE_DIR}/UnityExceptionsImpl.cpp
2933+)
2934+
2935+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UNITY_INTERNAL_SRC} PARENT_SCOPE)
2936
2937=== added file 'src/unity/internal/ExceptionImpl.cpp'
2938--- src/unity/internal/ExceptionImpl.cpp 1970-01-01 00:00:00 +0000
2939+++ src/unity/internal/ExceptionImpl.cpp 2013-04-05 10:31:25 +0000
2940@@ -0,0 +1,244 @@
2941+/*
2942+ * Copyright (C) 2013 Canonical Ltd
2943+ *
2944+ * This program is free software: you can redistribute it and/or modify
2945+ * it under the terms of the GNU General Public License version 3 as
2946+ * published by the Free Software Foundation.
2947+ *
2948+ * This program is distributed in the hope that it will be useful,
2949+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2950+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2951+ * GNU General Public License for more details.
2952+ *
2953+ * You should have received a copy of the GNU General Public License
2954+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
2955+ *
2956+ * Authored by: Michi Henning <michi.henning@canonical.com>
2957+ */
2958+
2959+#include <unity/internal/ExceptionImpl.h>
2960+#include <unity/Exception.h>
2961+
2962+using namespace std;
2963+
2964+namespace unity
2965+{
2966+
2967+namespace internal
2968+{
2969+
2970+ExceptionImpl::
2971+ExceptionImpl(string const& reason)
2972+ : reason_(reason)
2973+{
2974+}
2975+
2976+ExceptionImpl::
2977+~ExceptionImpl() noexcept = default;
2978+
2979+string
2980+ExceptionImpl::
2981+reason() const
2982+{
2983+ return reason_;
2984+}
2985+
2986+namespace
2987+{
2988+
2989+//
2990+// Return the margin string for the indent level and indent.
2991+//
2992+
2993+string
2994+get_margin(int indent_level, string const& indent)
2995+{
2996+ string margin;
2997+ for (int i = 0; i < indent_level; ++i)
2998+ {
2999+ margin += indent;
3000+ }
3001+ return margin;
3002+}
3003+
3004+//
3005+// Follow the nested exceptions that were rethrown along the call stack, printing them into s.
3006+//
3007+
3008+void
3009+print_name_and_reason(string& s, nested_exception const& nested)
3010+{
3011+ // Add the what() string if this is a std::exception.
3012+
3013+ std::exception const* std_exception = dynamic_cast<std::exception const*>(&nested);
3014+ if (std_exception)
3015+ {
3016+ s += std_exception->what();
3017+ }
3018+
3019+ // Add the reason if this is a unity::Exception.
3020+
3021+ unity::Exception const* unity_exception = dynamic_cast<unity::Exception const*>(&nested);
3022+ if (unity_exception)
3023+ {
3024+ string reason = unity_exception->reason();
3025+ if (!reason.empty())
3026+ {
3027+ s += ": " + reason;
3028+ }
3029+ }
3030+
3031+ // Append info about unknown std::exception and std::nested_exception.
3032+
3033+ if (!unity_exception)
3034+ {
3035+ if (std_exception)
3036+ {
3037+ s += " (derived from std::exception and std::nested_exception)";
3038+ }
3039+ else
3040+ {
3041+ s += "std::nested_exception";
3042+ }
3043+ }
3044+}
3045+
3046+void
3047+follow_nested(string& s, nested_exception const& nested, int indent_level, std::string const& indent)
3048+{
3049+ if (nested.nested_ptr())
3050+ {
3051+ string margin = get_margin(indent_level, indent);
3052+
3053+ s += ":\n";
3054+ try
3055+ {
3056+ nested.rethrow_nested();
3057+ }
3058+ catch (std::nested_exception const& e)
3059+ {
3060+ unity::Exception const* ge = dynamic_cast<unity::Exception const*>(&e);
3061+ if (ge)
3062+ {
3063+ s += ge->to_string(indent_level + 1, indent);
3064+ }
3065+ else
3066+ {
3067+ s += margin + indent;
3068+ print_name_and_reason(s, e);
3069+ follow_nested(s, e, indent_level + 1, indent);
3070+ }
3071+ }
3072+ catch (std::exception const& e)
3073+ {
3074+ s += margin + indent;
3075+ s += e.what(); // Can show only what() for std::exception.
3076+ }
3077+ catch (...)
3078+ {
3079+ s += margin + indent;
3080+ s += "unknown exception"; // Best we can do for an exception whose type we don't know.
3081+ }
3082+ }
3083+}
3084+
3085+//
3086+// Follow the history chain and print each exception in the chain.
3087+//
3088+
3089+void
3090+follow_history(string& s, int& count, unity::Exception const& e, int indent_level, std::string const& indent)
3091+{
3092+ if (!e.get_earlier())
3093+ {
3094+ count = 1; // We have reached the oldest exception; set exception generation count and terminate recursion.
3095+ }
3096+ else
3097+ {
3098+ try
3099+ {
3100+ rethrow_exception(e.get_earlier());
3101+ }
3102+ catch (unity::Exception const& e)
3103+ {
3104+ // Recurse along the chain until we hit the end, then, as we pop back up the levels, we increment the
3105+ // count and print it as a generation number for the exception information.
3106+ // A bit like the "kicks" in "Inception", except that the deepest level is level 1...
3107+
3108+ follow_history(s, count, e, indent_level, indent);
3109+ }
3110+ ++count;
3111+ }
3112+
3113+ // Show info for this exception.
3114+
3115+ s += "\n" + get_margin(indent_level, indent) + "Exception #";
3116+ s += to_string(count) + ":\n";
3117+ s += get_margin(indent_level, indent) + indent;
3118+ print_name_and_reason(s, e);
3119+ follow_nested(s, e, indent_level + 1, indent);
3120+}
3121+
3122+} // namespace
3123+
3124+string
3125+ExceptionImpl::
3126+to_string(nested_exception const& nested, int indent_level, string const& indent) const
3127+{
3128+ string margin = get_margin(indent_level, indent);
3129+ string s = margin;
3130+ s += what();
3131+
3132+ string r = reason();
3133+ if (!r.empty())
3134+ {
3135+ s += ": " + r;
3136+ }
3137+
3138+ // Check whether there is an exception history and print each exception in the history.
3139+
3140+ unity::Exception const* unity_exception(dynamic_cast<unity::Exception const*>(&nested));
3141+ if (unity_exception && unity_exception->get_earlier())
3142+ {
3143+ s += "\n" + margin + indent + "Exception history:";
3144+ try
3145+ {
3146+ rethrow_exception(unity_exception->get_earlier());
3147+ }
3148+ catch (unity::Exception const& e)
3149+ {
3150+ int count;
3151+ follow_history(s, count, e, indent_level + 2, indent);
3152+ }
3153+ }
3154+
3155+ // Print this and any nested exceptions.
3156+
3157+ follow_nested(s, nested, indent_level, indent);
3158+
3159+ return s;
3160+}
3161+
3162+exception_ptr
3163+ExceptionImpl::
3164+remember(Exception const* env, exception_ptr earlier_exception)
3165+{
3166+ // Doesn't prevent loops, but protects against accidental self-assignment.
3167+
3168+ if (previous_ != earlier_exception)
3169+ {
3170+ previous_ = earlier_exception;
3171+ }
3172+ return env->self();
3173+}
3174+
3175+exception_ptr
3176+ExceptionImpl::
3177+get_earlier() const noexcept
3178+{
3179+ return previous_;
3180+}
3181+
3182+} // namespace internal
3183+
3184+} // namespace unity
3185
3186=== added file 'src/unity/internal/UnityExceptionsImpl.cpp'
3187--- src/unity/internal/UnityExceptionsImpl.cpp 1970-01-01 00:00:00 +0000
3188+++ src/unity/internal/UnityExceptionsImpl.cpp 2013-04-05 10:31:25 +0000
3189@@ -0,0 +1,126 @@
3190+/*
3191+ * Copyright (C) 2012 Canonical Ltd
3192+ *
3193+ * This program is free software: you can redistribute it and/or modify
3194+ * it under the terms of the GNU General Public License version 3 as
3195+ * published by the Free Software Foundation.
3196+ *
3197+ * This program is distributed in the hope that it will be useful,
3198+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3199+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3200+ * GNU General Public License for more details.
3201+ *
3202+ * You should have received a copy of the GNU General Public License
3203+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3204+ *
3205+ * Authored by: Michi Henning <michi.henning@canonical.com>
3206+ */
3207+
3208+#include <unity/internal/UnityExceptionsImpl.h>
3209+
3210+using namespace std;
3211+
3212+namespace unity
3213+{
3214+
3215+namespace internal
3216+{
3217+
3218+InvalidArgumentExceptionImpl::
3219+InvalidArgumentExceptionImpl(string const& reason)
3220+ : ExceptionImpl(reason)
3221+{
3222+}
3223+
3224+char const*
3225+InvalidArgumentExceptionImpl::
3226+what() const noexcept
3227+{
3228+ return "unity::InvalidArgumentException";
3229+}
3230+
3231+LogicExceptionImpl::
3232+LogicExceptionImpl(string const& reason)
3233+ : ExceptionImpl(reason)
3234+{
3235+}
3236+
3237+char const*
3238+LogicExceptionImpl::
3239+what() const noexcept
3240+{
3241+ return "unity::LogicException";
3242+}
3243+
3244+ShutdownExceptionImpl::
3245+ShutdownExceptionImpl(string const& reason)
3246+ : ExceptionImpl(reason)
3247+{
3248+}
3249+
3250+char const*
3251+ShutdownExceptionImpl::
3252+what() const noexcept
3253+{
3254+ return "unity::ShutdownException";
3255+}
3256+
3257+FileExceptionImpl::
3258+FileExceptionImpl(string const& reason, int err)
3259+ : ExceptionImpl(reason + (err == 0 ? "" : " (errno = " + std::to_string(err) + ")"))
3260+ , errno_(err)
3261+{
3262+}
3263+
3264+char const*
3265+FileExceptionImpl::
3266+what() const noexcept
3267+{
3268+ return "unity::FileException";
3269+}
3270+
3271+int
3272+FileExceptionImpl::
3273+error() const noexcept
3274+{
3275+ return errno_;
3276+}
3277+
3278+SyscallExceptionImpl::
3279+SyscallExceptionImpl(string const& reason, int err)
3280+ : ExceptionImpl(reason + (reason.empty() ? "" : " ") + "(errno = " + std::to_string(err) + ")")
3281+ , errno_(err)
3282+{
3283+}
3284+
3285+char const*
3286+SyscallExceptionImpl::
3287+what() const noexcept
3288+{
3289+ return "unity::SyscallException";
3290+}
3291+
3292+int
3293+SyscallExceptionImpl::
3294+error() const noexcept
3295+{
3296+ return errno_;
3297+}
3298+
3299+ResourceExceptionImpl::
3300+ResourceExceptionImpl(string const& reason)
3301+ : ExceptionImpl(reason)
3302+{
3303+}
3304+
3305+char const*
3306+ResourceExceptionImpl::
3307+what() const noexcept
3308+{
3309+ return "unity::ResourceException";
3310+}
3311+
3312+
3313+} // namespace internal
3314+
3315+} // namespace unity
3316
3317=== added directory 'src/unity/util'
3318=== added file 'src/unity/util/CMakeLists.txt'
3319--- src/unity/util/CMakeLists.txt 1970-01-01 00:00:00 +0000
3320+++ src/unity/util/CMakeLists.txt 2013-04-05 10:31:25 +0000
3321@@ -0,0 +1,26 @@
3322+#
3323+# Copyright (C) 2013 Canonical Ltd
3324+#
3325+# This program is free software: you can redistribute it and/or modify
3326+# it under the terms of the GNU General Public License version 3 as
3327+# published by the Free Software Foundation.
3328+#
3329+# This program is distributed in the hope that it will be useful,
3330+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3331+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3332+# GNU General Public License for more details.
3333+#
3334+# You should have received a copy of the GNU General Public License
3335+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3336+#
3337+# Authored by: Michi Henning <michi.henning@canonical.com>
3338+#
3339+
3340+add_subdirectory(internal)
3341+
3342+set(UTIL_SRC
3343+ ${CMAKE_CURRENT_SOURCE_DIR}/Daemon.cpp
3344+ ${CMAKE_CURRENT_SOURCE_DIR}/FileIO.cpp
3345+)
3346+
3347+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UTIL_SRC} PARENT_SCOPE)
3348
3349=== added file 'src/unity/util/Daemon.cpp'
3350--- src/unity/util/Daemon.cpp 1970-01-01 00:00:00 +0000
3351+++ src/unity/util/Daemon.cpp 2013-04-05 10:31:25 +0000
3352@@ -0,0 +1,89 @@
3353+/*
3354+ * Copyright (C) 2013 Canonical Ltd
3355+ *
3356+ * This program is free software: you can redistribute it and/or modify
3357+ * it under the terms of the GNU General Public License version 3 as
3358+ * published by the Free Software Foundation.
3359+ *
3360+ * This program is distributed in the hope that it will be useful,
3361+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3362+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3363+ * GNU General Public License for more details.
3364+ *
3365+ * You should have received a copy of the GNU General Public License
3366+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3367+ *
3368+ * Authored by: Michi Henning <michi.henning@canonical.com>
3369+ */
3370+
3371+#include <unity/util/Daemon.h>
3372+#include <unity/util/internal/DaemonImpl.h>
3373+
3374+using namespace std;
3375+
3376+namespace unity
3377+{
3378+
3379+namespace util
3380+{
3381+
3382+Daemon::UPtr
3383+Daemon::
3384+create()
3385+{
3386+ return UPtr(new Daemon());
3387+}
3388+
3389+void
3390+Daemon::
3391+close_fds() noexcept
3392+{
3393+ p_->close_fds();
3394+}
3395+
3396+void
3397+Daemon::
3398+reset_signals() noexcept
3399+{
3400+ p_->reset_signals();
3401+}
3402+
3403+void
3404+Daemon::
3405+set_umask(mode_t mask) noexcept
3406+{
3407+ p_->set_umask(mask);
3408+}
3409+
3410+void
3411+Daemon::
3412+set_working_directory(string const& working_directory)
3413+{
3414+ p_->set_working_directory(working_directory);
3415+}
3416+
3417+// Turn this process into a proper daemon in its own session and without a control terminal.
3418+// Whether to close open file descriptors, reset signals to their defaults, change the umask,
3419+// or change the working directory is determined by the setters above.
3420+
3421+void
3422+Daemon::
3423+daemonize_me()
3424+{
3425+ p_->daemonize_me();
3426+}
3427+
3428+Daemon::
3429+Daemon()
3430+ : p_(new internal::DaemonImpl())
3431+{
3432+}
3433+
3434+Daemon::
3435+~Daemon() noexcept
3436+{
3437+}
3438+
3439+} // namespace util
3440+
3441+} // namespace unity
3442
3443=== added file 'src/unity/util/FileIO.cpp'
3444--- src/unity/util/FileIO.cpp 1970-01-01 00:00:00 +0000
3445+++ src/unity/util/FileIO.cpp 2013-04-05 10:31:25 +0000
3446@@ -0,0 +1,106 @@
3447+/*
3448+ * Copyright (C) 2013 Canonical Ltd
3449+ *
3450+ * This program is free software: you can redistribute it and/or modify
3451+ * it under the terms of the GNU General Public License version 3 as
3452+ * published by the Free Software Foundation.
3453+ *
3454+ * This program is distributed in the hope that it will be useful,
3455+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3456+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3457+ * GNU General Public License for more details.
3458+ *
3459+ * You should have received a copy of the GNU General Public License
3460+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3461+ *
3462+ * Authored by: Michi Henning <michi.henning@canonical.com>
3463+ */
3464+
3465+#include <unity/util/FileIO.h>
3466+#include <unity/util/ResourcePtr.h>
3467+#include <unity/UnityExceptions.h>
3468+
3469+#include <fcntl.h>
3470+#include <string.h>
3471+#include <sys/stat.h>
3472+
3473+using namespace std;
3474+
3475+namespace unity
3476+{
3477+
3478+namespace util
3479+{
3480+
3481+namespace
3482+{
3483+
3484+//
3485+// It would be nice to use fstream for I/O, but the error reporting is so useless that it's better to step
3486+// down to system calls. At least then, when something goes wrong, we know what it was.
3487+//
3488+
3489+template<typename T>
3490+vector<T>
3491+read_file(string const& filename)
3492+{
3493+ util::ResourcePtr<int, std::function<void(int)>> fd(::open(filename.c_str(), O_RDONLY),
3494+ [](int fd) { if (fd != -1) ::close(fd); });
3495+ if (fd.get() == -1)
3496+ {
3497+ throw FileException("cannot open \"" + filename + "\": " + strerror(errno), errno);
3498+ }
3499+
3500+ struct stat st;
3501+ if (fstat(fd.get(), &st) == -1)
3502+ {
3503+ throw FileException("cannot fstat \"" + filename + "\": " + strerror(errno), errno); // LCOV_EXCL_LINE
3504+ }
3505+
3506+ if (!S_ISREG(st.st_mode))
3507+ {
3508+ throw FileException("\"" + filename + "\" is not a regular file", 0);
3509+ }
3510+
3511+ vector<T> buf(st.st_size);
3512+
3513+ if (st.st_size == 0)
3514+ {
3515+ return buf;
3516+ }
3517+
3518+ if (read(fd.get(), &buf[0], st.st_size) != st.st_size)
3519+ {
3520+ // LCOV_EXCL_START
3521+ ostringstream msg;
3522+ msg << "cannot read " << st.st_size << " byte";
3523+ if (st.st_size != 1)
3524+ {
3525+ msg << "s";
3526+ }
3527+ msg << " from \"" << filename << "\": " << strerror(errno);
3528+ throw FileException(msg.str(), errno);
3529+ // LCOV_EXCL_STOP
3530+ }
3531+
3532+ return buf;
3533+}
3534+
3535+} // namespace
3536+
3537+string
3538+read_text_file(string const& filename)
3539+{
3540+ vector<char> buf(read_file<char>(filename));
3541+ return string(buf.begin(), buf.end());
3542+}
3543+
3544+vector<uint8_t>
3545+read_binary_file(string const& filename)
3546+{
3547+ return read_file<uint8_t>(filename);
3548+}
3549+
3550+} // namespace util
3551+
3552+} // namespace unity
3553
3554=== added directory 'src/unity/util/internal'
3555=== added file 'src/unity/util/internal/CMakeLists.txt'
3556--- src/unity/util/internal/CMakeLists.txt 1970-01-01 00:00:00 +0000
3557+++ src/unity/util/internal/CMakeLists.txt 2013-04-05 10:31:25 +0000
3558@@ -0,0 +1,23 @@
3559+#
3560+# Copyright (C) 2013 Canonical Ltd
3561+#
3562+# This program is free software: you can redistribute it and/or modify
3563+# it under the terms of the GNU General Public License version 3 as
3564+# published by the Free Software Foundation.
3565+#
3566+# This program is distributed in the hope that it will be useful,
3567+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3568+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3569+# GNU General Public License for more details.
3570+#
3571+# You should have received a copy of the GNU General Public License
3572+# along with this program. If not, see <http://www.gnu.org/licenses/>.
3573+#
3574+# Authored by: Michi Henning <michi.henning@canonical.com>
3575+#
3576+
3577+set(UTIL_INTERNAL_SRC
3578+ ${CMAKE_CURRENT_SOURCE_DIR}/DaemonImpl.cpp
3579+)
3580+
3581+set(UNITY_API_LIB_SRC ${UNITY_API_LIB_SRC} ${UTIL_INTERNAL_SRC} PARENT_SCOPE)
3582
3583=== added file 'src/unity/util/internal/DaemonImpl.cpp'
3584--- src/unity/util/internal/DaemonImpl.cpp 1970-01-01 00:00:00 +0000
3585+++ src/unity/util/internal/DaemonImpl.cpp 2013-04-05 10:31:25 +0000
3586@@ -0,0 +1,271 @@
3587+/*
3588+ * Copyright (C) 2013 Canonical Ltd
3589+ *
3590+ * This program is free software: you can redistribute it and/or modify
3591+ * it under the terms of the GNU General Public License version 3 as
3592+ * published by the Free Software Foundation.
3593+ *
3594+ * This program is distributed in the hope that it will be useful,
3595+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
3596+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3597+ * GNU General Public License for more details.
3598+ *
3599+ * You should have received a copy of the GNU General Public License
3600+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
3601+ *
3602+ * Authored by: Michi Henning <michi.henning@canonical.com>
3603+ */
3604+
3605+#include <unity/util/internal/DaemonImpl.h>
3606+#include <unity/util/ResourcePtr.h>
3607+
3608+#include <dirent.h>
3609+#include <fcntl.h>
3610+#include <signal.h>
3611+#include <stddef.h>
3612+#include <string.h>
3613+#include <sys/stat.h>
3614+#include <unistd.h>
3615+
3616+#include <cassert>
3617+#include <sstream>
3618+#include <vector>
3619+
3620+using namespace std;
3621+
3622+namespace unity
3623+{
3624+
3625+namespace util
3626+{
3627+
3628+namespace internal
3629+{
3630+
3631+DaemonImpl::
3632+DaemonImpl()
3633+ : close_fds_(false), reset_signals_(false), set_umask_(false)
3634+{
3635+}
3636+
3637+void
3638+DaemonImpl::
3639+close_fds() noexcept
3640+{
3641+ close_fds_ = true;
3642+}
3643+
3644+void
3645+DaemonImpl::
3646+reset_signals() noexcept
3647+{
3648+ reset_signals_ = true;
3649+}
3650+
3651+void
3652+DaemonImpl::
3653+set_umask(mode_t mask) noexcept
3654+{
3655+ set_umask_ = true;
3656+ umask_ = mask;
3657+}
3658+
3659+void
3660+DaemonImpl::
3661+set_working_directory(string const& working_directory)
3662+{
3663+ working_directory_ = working_directory;
3664+}
3665+
3666+// Turn this process into a proper daemon in its own session and without a control terminal.
3667+// Whether to close open file descriptors, reset signals to their defaults, change the umask,
3668+// or change the working directory is determined by the setters above.
3669+
3670+void
3671+DaemonImpl::
3672+daemonize_me()
3673+{
3674+ // Let's start by changing the working directory because that is the most likely thing to fail. If it does
3675+ // fail, we have not modified any other properties of the calling process.
3676+
3677+ if (!working_directory_.empty())
3678+ {
3679+ if (chdir(working_directory_.c_str()) == -1)
3680+ {
3681+ ostringstream msg;
3682+ msg << "chdir(\"" << working_directory_.c_str() << "\") failed";
3683+ throw SyscallException(msg.str(), errno);
3684+ }
3685+ }
3686+
3687+ // Fork and let the parent exit.
3688+
3689+ switch (fork())
3690+ {
3691+ case -1:
3692+ {
3693+ throw SyscallException("fork() failed", errno); // LCOV_EXCL_LINE
3694+ }
3695+ case 0:
3696+ {
3697+ break; // Child process
3698+ }
3699+ default:
3700+ {
3701+ exit(EXIT_SUCCESS); // Parent process, we are done.
3702+ }
3703+ }
3704+
3705+ // Make us a process group leader, thereby losing the control terminal.
3706+ // No error check needed here: the only possible error is EPERM which means we are a process
3707+ // group leader already. But that's impossible because we just forked and are the child.
3708+
3709+ setsid();
3710+
3711+ // Set the umask if the caller asked for that. No error checking here because umask() cannot fail.
3712+
3713+ if (set_umask_)
3714+ {
3715+ umask(umask_);
3716+ }
3717+
3718+ // We are about to fork a second time, to prevent the process from re-acquiring a control terminal if it
3719+ // later opens a terminal device. Because we are a session leader now, we need to ignore SIGHUP, otherwise,
3720+ // when the parent exits after the next fork, we'll receive SIGHUP and die. We remember the previous SIGHUP
3721+ // disposition so we can restore it to what it was if the caller doesn't want all signals to be
3722+ // reset to their default behavior.
3723+
3724+ struct sigaction old_action;
3725+ memset(&old_action, 0, sizeof(old_action)); // To stop valgrind complaints
3726+ struct sigaction action;
3727+ memset(&action, 0, sizeof(old_action)); // To stop valgrind complaints
3728+ action.sa_handler = SIG_IGN;
3729+ sigaction(SIGHUP, &action, &old_action);
3730+
3731+ switch (fork())
3732+ {
3733+ case -1:
3734+ {
3735+ // LCOV_EXCL_START
3736+ sigaction(SIGHUP, &old_action, nullptr); // Strong exception guarantee
3737+ throw SyscallException("fork() failed", errno); // Better than trying to muddle on despite the problem.
3738+ // LCOV_EXCL_STOP
3739+ }
3740+ case 0:
3741+ {
3742+ break; // Child process
3743+ }
3744+ default:
3745+ {
3746+ exit(EXIT_SUCCESS); // Parent process, we are done.
3747+ }
3748+ }
3749+
3750+ // From here on, we do as much of the daemonizing as we can, ignoring errors from system calls.
3751+ // That's because, now that the second fork has happened, we are committed. Any system call errors below
3752+ // are effectively impossible anyway because things like closing open files and changing signal disposition
3753+ // never fail unless the OS is seriously ill.
3754+
3755+ if (!reset_signals_ && old_action.sa_handler != action.sa_handler)
3756+ {
3757+ sigaction(SIGHUP, &old_action, nullptr); // Restore previous disposition for SIGHUP.
3758+ }
3759+
3760+ // If the caller asked for it, we reset all signals to the default behavior.
3761+
3762+ if (reset_signals_)
3763+ {
3764+ action.sa_handler = SIG_DFL;
3765+ for (int sig = 1; sig < NSIG; ++sig)
3766+ {
3767+ sigaction(sig, &action, nullptr);
3768+ }
3769+ }
3770+
3771+ // Close standard descriptors plus, if the caller asked for that, all others, and
3772+ // connect the standard file descriptors to /dev/null.
3773+
3774+ close_open_files();
3775+
3776+ int fd = open("/dev/null", O_RDWR);
3777+ assert(fd == 0);
3778+ fd = dup(fd);
3779+ assert(fd == 1);
3780+ fd = dup(fd);
3781+ assert(fd == 2);
3782+}
3783+
3784+// Close all open file descriptors
3785+
3786+void
3787+DaemonImpl::
3788+close_open_files() noexcept
3789+{
3790+ if (close_fds_)
3791+ {
3792+ // Close all open files. We use /proc to figure out what files are open.
3793+ // That's more efficient than calling close() potentially tens of thousands of times, once for each possible
3794+ // descriptor up to the process limit. We close the standard file descriptors as well because we need to
3795+ // re-open those later anyway.
3796+
3797+ char const* proc_self_fd = "/proc/self/fd";
3798+
3799+ ResourcePtr<DIR*, decltype(&closedir)> dir(opendir(proc_self_fd), closedir);
3800+ if (dir.get() == nullptr)
3801+ {
3802+ return; // This should never happen but, for diligence, we check anyway. // LCOV_EXCL_LINE
3803+ }
3804+
3805+ vector<int> descriptors; // We collect the file descriptors to close here
3806+
3807+ // We use the re-entrant version of readdir().
3808+
3809+ size_t len = offsetof(struct dirent, d_name) + pathconf(proc_self_fd, _PC_NAME_MAX) + 1;
3810+ unique_ptr<struct dirent, decltype(&free)> entry(reinterpret_cast<struct dirent*>(malloc(len)), free);
3811+
3812+ struct dirent* result_p;
3813+
3814+ readdir_r(dir.get(), entry.get(), &result_p); // Read first entry
3815+
3816+ while (result_p)
3817+ {
3818+ if (result_p->d_name[0] != '.') // Ignore . and ..
3819+ {
3820+ // Try to treat the file name as a number. If it doesn't look like a number, something is seriously
3821+ // wrong because /proc/self/fd is supposed to contain only open file descriptor numbers. Rather than
3822+ // giving up in that case, we keep going, closing as many file descriptors as we can.
3823+
3824+ size_t pos;
3825+ int fd = std::stoi(result_p->d_name, &pos);
3826+ if (result_p->d_name[pos] == '\0') // The file name did parse as a number
3827+ {
3828+ // We can't call close() here because that would modify the directory while we are iterating
3829+ // over it, which has undefined behavior.
3830+ descriptors.push_back(fd);
3831+ }
3832+ }
3833+ readdir_r(dir.get(), entry.get(), &result_p); // Read next entry
3834+ }
3835+
3836+ // Close all open descriptors.
3837+
3838+ for (auto fd : descriptors)
3839+ {
3840+ close(fd);
3841+ }
3842+ }
3843+ else
3844+ {
3845+ // Caller asked for file descriptors to be left alone, so we only close the standard three.
3846+
3847+ close(0);
3848+ close(1);
3849+ close(2);
3850+ }
3851+}
3852+
3853+} // namespace internal
3854+
3855+} // namespace util
3856+
3857+} // namespace unity

Subscribers

People subscribed via source and target branches