Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
C
capnproto
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
capnproto
Commits
cd02679f
Commit
cd02679f
authored
Jun 04, 2013
by
Kenton Varda
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Don't include <exception> in exception.h, but still throw object implementing std::exception.
parent
7a830031
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
126 additions
and
49 deletions
+126
-49
common.h
c++/src/kj/common.h
+32
-2
debug-test.c++
c++/src/kj/debug-test.c++
+33
-8
exception.c++
c++/src/kj/exception.c++
+51
-34
exception.h
c++/src/kj/exception.h
+10
-5
No files found.
c++/src/kj/common.h
View file @
cd02679f
...
...
@@ -426,13 +426,34 @@ public:
Maybe
(
decltype
(
nullptr
))
noexcept
:
ptr
(
nullptr
)
{}
~
Maybe
()
noexcept
{}
inline
Maybe
&
operator
=
(
Maybe
&&
other
)
{
ptr
=
kj
::
mv
(
other
.
ptr
);
return
*
this
;
}
inline
Maybe
&
operator
=
(
const
Maybe
&
other
)
{
ptr
=
other
.
ptr
;
return
*
this
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
ptr
==
nullptr
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
ptr
!=
nullptr
;
}
~
Maybe
()
noexcept
{}
template
<
typename
Func
>
auto
map
(
Func
&&
f
)
->
Maybe
<
decltype
(
f
(
instance
<
T
&>
()))
>
{
if
(
ptr
==
nullptr
)
{
return
nullptr
;
}
else
{
return
f
(
*
ptr
);
}
}
template
<
typename
Func
>
auto
map
(
Func
&&
f
)
const
->
Maybe
<
decltype
(
f
(
instance
<
const
T
&>
()))
>
{
if
(
ptr
==
nullptr
)
{
return
nullptr
;
}
else
{
return
f
(
*
ptr
);
}
}
// TODO(someday): Once it's safe to require GCC 4.8, use ref qualifiers to provide a version of
// map() that uses move semantics if *this is an rvalue.
private
:
internal
::
NullableValue
<
T
>
ptr
;
...
...
@@ -458,12 +479,21 @@ public:
Maybe
(
const
Maybe
<
U
&>&
other
)
:
ptr
(
other
.
ptr
)
{}
Maybe
(
decltype
(
nullptr
))
noexcept
:
ptr
(
nullptr
)
{}
~
Maybe
()
noexcept
{}
inline
Maybe
&
operator
=
(
const
Maybe
&
other
)
{
ptr
=
other
.
ptr
;
return
*
this
;
}
inline
bool
operator
==
(
decltype
(
nullptr
))
const
{
return
ptr
==
nullptr
;
}
inline
bool
operator
!=
(
decltype
(
nullptr
))
const
{
return
ptr
!=
nullptr
;
}
~
Maybe
()
noexcept
{}
template
<
typename
Func
>
auto
map
(
Func
&&
f
)
->
Maybe
<
decltype
(
f
(
instance
<
T
&>
()))
>
{
if
(
ptr
==
nullptr
)
{
return
nullptr
;
}
else
{
return
f
(
*
ptr
);
}
}
private
:
T
*
ptr
;
...
...
c++/src/kj/debug-test.c++
View file @
cd02679f
...
...
@@ -29,6 +29,7 @@
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <exception>
namespace
kj
{
namespace
internal
{
...
...
@@ -44,26 +45,26 @@ public:
void
onRecoverableException
(
Exception
&&
exception
)
override
{
text
+=
"recoverable exception: "
;
auto
what
=
str
(
exception
);
// Discard the last line of "what" because it is a stack trace.
const
char
*
what
=
exception
.
what
();
const
char
*
end
=
strrchr
(
what
,
'\n'
);
const
char
*
end
=
strrchr
(
what
.
cStr
(),
'\n'
);
if
(
end
==
nullptr
)
{
text
+=
exception
.
what
();
text
+=
what
.
cStr
();
}
else
{
text
.
append
(
what
,
end
);
text
.
append
(
what
.
cStr
()
,
end
);
}
text
+=
'\n'
;
}
void
onFatalException
(
Exception
&&
exception
)
override
{
text
+=
"fatal exception: "
;
auto
what
=
str
(
exception
);
// Discard the last line of "what" because it is a stack trace.
const
char
*
what
=
exception
.
what
();
const
char
*
end
=
strrchr
(
what
,
'\n'
);
const
char
*
end
=
strrchr
(
what
.
cStr
(),
'\n'
);
if
(
end
==
nullptr
)
{
text
+=
exception
.
what
();
text
+=
what
.
cStr
();
}
else
{
text
.
append
(
what
,
end
);
text
.
append
(
what
.
cStr
()
,
end
);
}
text
+=
'\n'
;
throw
MockException
();
...
...
@@ -155,6 +156,30 @@ TEST(Logging, Log) {
mockCallback
.
text
.
clear
();
}
TEST
(
Logging
,
Catch
)
{
int
line
;
// Catch as kj::Exception.
try
{
line
=
__LINE__
;
KJ_FAIL_ASSERT
(
"foo"
);
ADD_FAILURE
()
<<
"Expected exception."
;
}
catch
(
const
Exception
&
e
)
{
String
what
=
str
(
e
);
std
::
string
text
(
what
.
cStr
(),
strchr
(
what
.
cStr
(),
'\n'
)
-
what
.
cStr
());
EXPECT_EQ
(
fileLine
(
__FILE__
,
line
)
+
": bug in code: foo"
,
text
);
}
// Catch as std::exception.
try
{
line
=
__LINE__
;
KJ_FAIL_ASSERT
(
"foo"
);
ADD_FAILURE
()
<<
"Expected exception."
;
}
catch
(
const
std
::
exception
&
e
)
{
const
char
*
what
=
e
.
what
();
std
::
string
text
(
what
,
strchr
(
what
,
'\n'
)
-
what
);
EXPECT_EQ
(
fileLine
(
__FILE__
,
line
)
+
": bug in code: foo"
,
text
);
}
}
TEST
(
Logging
,
Syscall
)
{
MockExceptionCallback
mockCallback
;
MockExceptionCallback
::
ScopedRegistration
reg
(
mockCallback
);
...
...
c++/src/kj/exception.c++
View file @
cd02679f
...
...
@@ -27,6 +27,7 @@
#include <unistd.h>
#include <execinfo.h>
#include <stdlib.h>
#include <exception>
namespace
kj
{
...
...
@@ -53,6 +54,42 @@ ArrayPtr<const char> KJ_STRINGIFY(Exception::Durability durability) {
return
arrayPtr
(
s
,
strlen
(
s
));
}
String
KJ_STRINGIFY
(
const
Exception
&
e
)
{
uint
contextDepth
=
0
;
Maybe
<
const
Exception
::
Context
&>
contextPtr
=
e
.
getContext
();
for
(;;)
{
KJ_IF_MAYBE
(
c
,
contextPtr
)
{
++
contextDepth
;
contextPtr
=
c
->
next
.
map
(
[](
const
Own
<
Exception
::
Context
>&
c
)
->
const
Exception
::
Context
&
{
return
*
c
;
});
}
else
{
break
;
}
}
Array
<
String
>
contextText
=
heapArray
<
String
>
(
contextDepth
);
contextDepth
=
0
;
contextPtr
=
e
.
getContext
();
for
(;;)
{
KJ_IF_MAYBE
(
c
,
contextPtr
)
{
contextText
[
contextDepth
++
]
=
str
(
c
->
file
,
":"
,
c
->
line
,
": context: "
,
c
->
description
,
"
\n
"
);
contextPtr
=
c
->
next
.
map
(
[](
const
Own
<
Exception
::
Context
>&
c
)
->
const
Exception
::
Context
&
{
return
*
c
;
});
}
else
{
break
;
}
}
return
str
(
strArray
(
contextText
,
""
),
e
.
getFile
(),
":"
,
e
.
getLine
(),
": "
,
e
.
getNature
(),
e
.
getDurability
()
==
Exception
::
Durability
::
TEMPORARY
?
" (temporary)"
:
""
,
e
.
getDescription
()
==
nullptr
?
""
:
": "
,
e
.
getDescription
(),
"
\n
stack: "
,
strArray
(
e
.
getStackTrace
(),
" "
));
}
Exception
::
Exception
(
Nature
nature
,
Durability
durability
,
const
char
*
file
,
int
line
,
String
description
)
noexcept
:
file
(
file
),
line
(
line
),
nature
(
nature
),
durability
(
durability
),
...
...
@@ -83,41 +120,21 @@ void Exception::wrapContext(const char* file, int line, String&& description) {
context
=
heap
<
Context
>
(
file
,
line
,
mv
(
description
),
mv
(
context
));
}
const
char
*
Exception
::
what
()
const
noexcept
{
uint
contextDepth
=
0
;
const
Maybe
<
Own
<
Context
>>*
contextPtr
=
&
context
;
for
(;;)
{
KJ_IF_MAYBE
(
c
,
*
contextPtr
)
{
++
contextDepth
;
contextPtr
=
&
(
*
c
)
->
next
;
}
else
{
break
;
}
class
ExceptionImpl
:
public
Exception
,
public
std
::
exception
{
public
:
inline
ExceptionImpl
(
Exception
&&
other
)
:
Exception
(
mv
(
other
))
{}
ExceptionImpl
(
const
ExceptionImpl
&
other
)
:
Exception
(
other
)
{
// No need to copy whatBuffer since it's just to hold the return value of what().
}
Array
<
String
>
contextText
=
heapArray
<
String
>
(
contextDepth
);
contextDepth
=
0
;
contextPtr
=
&
context
;
for
(;;)
{
KJ_IF_MAYBE
(
c
,
*
contextPtr
)
{
const
Context
&
node
=
**
c
;
contextText
[
contextDepth
++
]
=
str
(
node
.
file
,
":"
,
node
.
line
,
": context: "
,
node
.
description
,
"
\n
"
);
contextPtr
=
&
node
.
next
;
}
else
{
break
;
}
}
const
char
*
what
()
const
noexcept
override
;
// Must be careful to NUL-terminate this.
whatBuffer
=
str
(
strArray
(
contextText
,
""
),
file
,
":"
,
line
,
": "
,
nature
,
durability
==
Durability
::
TEMPORARY
?
" (temporary)"
:
""
,
this
->
description
==
nullptr
?
""
:
": "
,
this
->
description
,
"
\n
stack: "
,
strArray
(
arrayPtr
(
trace
,
traceCount
),
" "
));
private
:
mutable
String
whatBuffer
;
};
const
char
*
ExceptionImpl
::
what
()
const
noexcept
{
whatBuffer
=
str
(
*
this
);
return
whatBuffer
.
begin
();
}
...
...
@@ -146,9 +163,9 @@ void ExceptionCallback::onRecoverableException(Exception&& exception) {
logMessage
(
str
(
exception
.
what
(),
'\n'
));
#else
if
(
std
::
uncaught_exception
())
{
logMessage
(
str
(
"unwind: "
,
exception
.
what
(),
'\n'
));
logMessage
(
str
(
"unwind: "
,
ExceptionImpl
(
mv
(
exception
))
.
what
(),
'\n'
));
}
else
{
throw
kj
::
mv
(
exception
);
throw
ExceptionImpl
(
mv
(
exception
)
);
}
#endif
}
...
...
@@ -157,7 +174,7 @@ void ExceptionCallback::onFatalException(Exception&& exception) {
#if KJ_NO_EXCEPTIONS
logMessage
(
str
(
exception
.
what
(),
'\n'
));
#else
throw
kj
::
mv
(
exception
);
throw
ExceptionImpl
(
mv
(
exception
)
);
#endif
}
...
...
c++/src/kj/exception.h
View file @
cd02679f
...
...
@@ -24,15 +24,19 @@
#ifndef KJ_EXCEPTION_H_
#define KJ_EXCEPTION_H_
#include <exception>
#include "memory.h"
#include "array.h"
#include "string.h"
namespace
kj
{
class
Exception
:
public
std
::
exception
{
class
ExceptionImpl
;
class
Exception
{
// Exception thrown in case of fatal errors.
//
// Actually, a subclass of this which also implements std::exception will be thrown, but we hide
// that fact from the interface to avoid #including <exception>.
#ifdef __CDT_PARSER__
// For some reason Eclipse gets confused by the definition of Nature if it's the first thing
...
...
@@ -74,6 +78,7 @@ public:
Nature
getNature
()
const
{
return
nature
;
}
Durability
getDurability
()
const
{
return
durability
;
}
ArrayPtr
<
const
char
>
getDescription
()
const
{
return
description
;
}
ArrayPtr
<
void
*
const
>
getStackTrace
()
const
{
return
arrayPtr
(
trace
,
traceCount
);
}
struct
Context
{
// Describes a bit about what was going on when the exception was thrown.
...
...
@@ -101,8 +106,6 @@ public:
// is expected that contexts will be added in reverse order as the exception passes up the
// callback stack.
const
char
*
what
()
const
noexcept
override
;
private
:
const
char
*
file
;
int
line
;
...
...
@@ -112,11 +115,13 @@ private:
Maybe
<
Own
<
Context
>>
context
;
void
*
trace
[
16
];
uint
traceCount
;
mutable
String
whatBuffer
;
friend
class
ExceptionImpl
;
};
ArrayPtr
<
const
char
>
KJ_STRINGIFY
(
Exception
::
Nature
nature
);
ArrayPtr
<
const
char
>
KJ_STRINGIFY
(
Exception
::
Durability
durability
);
String
KJ_STRINGIFY
(
const
Exception
&
e
);
class
ExceptionCallback
{
// If you don't like C++ exceptions, you may implement and register an ExceptionCallback in order
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment