Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
Actor Framework
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Operations
Operations
Metrics
Environments
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
cpp-libs
Actor Framework
Commits
168a2a2b
Unverified
Commit
168a2a2b
authored
Nov 21, 2018
by
Joseph Noir
Committed by
GitHub
Nov 21, 2018
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #797
Limit maximum memory consumption of the logger
parents
f52cf24f
af5eb9d3
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
612 additions
and
342 deletions
+612
-342
CMakeLists.txt
CMakeLists.txt
+5
-19
Jenkinsfile
Jenkinsfile
+1
-1
cmake/build_config.hpp.in
cmake/build_config.hpp.in
+3
-1
configure
configure
+1
-22
libcaf_core/caf/atom.hpp
libcaf_core/caf/atom.hpp
+4
-0
libcaf_core/caf/detail/log_level.hpp
libcaf_core/caf/detail/log_level.hpp
+37
-0
libcaf_core/caf/detail/ringbuffer.hpp
libcaf_core/caf/detail/ringbuffer.hpp
+117
-0
libcaf_core/caf/logger.hpp
libcaf_core/caf/logger.hpp
+201
-154
libcaf_core/src/atom.cpp
libcaf_core/src/atom.cpp
+38
-15
libcaf_core/src/logger.cpp
libcaf_core/src/logger.cpp
+104
-129
libcaf_core/test/logger.cpp
libcaf_core/test/logger.cpp
+1
-1
libcaf_core/test/ringbuffer.cpp
libcaf_core/test/ringbuffer.cpp
+100
-0
No files found.
CMakeLists.txt
View file @
168a2a2b
...
@@ -367,8 +367,11 @@ endif()
...
@@ -367,8 +367,11 @@ endif()
# setup logging #
# setup logging #
################################################################################
################################################################################
# make sure log level is defined and all-uppercase
if
(
NOT CAF_LOG_LEVEL
)
if
(
NOT CAF_LOG_LEVEL
)
set
(
CAF_LOG_LEVEL
"-1"
)
set
(
CAF_LOG_LEVEL
"QUIET"
)
else
()
string
(
TOUPPER
"
${
CAF_LOG_LEVEL
}
"
CAF_LOG_LEVEL
)
endif
()
endif
()
################################################################################
################################################################################
...
@@ -662,23 +665,6 @@ add_custom_target(gui_dummy SOURCES configure ${script_files})
...
@@ -662,23 +665,6 @@ add_custom_target(gui_dummy SOURCES configure ${script_files})
# print summary #
# print summary #
################################################################################
################################################################################
# set human-readable representation for log level
set
(
LOG_LEVEL_STR
"none"
)
if
(
CAF_LOG_LEVEL
)
if
(
${
CAF_LOG_LEVEL
}
EQUAL 0
)
set
(
LOG_LEVEL_STR
"ERROR"
)
elseif
(
${
CAF_LOG_LEVEL
}
EQUAL 1
)
set
(
LOG_LEVEL_STR
"WARNING"
)
elseif
(
${
CAF_LOG_LEVEL
}
EQUAL 2
)
set
(
LOG_LEVEL_STR
"INFO"
)
elseif
(
${
CAF_LOG_LEVEL
}
EQUAL 3
)
set
(
LOG_LEVEL_STR
"DEBUG"
)
elseif
(
${
CAF_LOG_LEVEL
}
EQUAL 4
)
set
(
LOG_LEVEL_STR
"TRACE"
)
else
()
set
(
LOG_LEVEL_STR
"invalid"
)
endif
()
endif
()
# little helper macro to invert a boolean
# little helper macro to invert a boolean
macro
(
invertYesNo in out
)
macro
(
invertYesNo in out
)
if
(
${
in
}
)
if
(
${
in
}
)
...
@@ -715,7 +701,7 @@ if(NOT CAF_NO_SUMMARY)
...
@@ -715,7 +701,7 @@ if(NOT CAF_NO_SUMMARY)
"
\n
Build static only:
${
CAF_BUILD_STATIC_ONLY
}
"
"
\n
Build static only:
${
CAF_BUILD_STATIC_ONLY
}
"
"
\n
Build static runtime:
${
CAF_BUILD_STATIC_RUNTIME
}
"
"
\n
Build static runtime:
${
CAF_BUILD_STATIC_RUNTIME
}
"
"
\n
Runtime checks:
${
CAF_ENABLE_RUNTIME_CHECKS
}
"
"
\n
Runtime checks:
${
CAF_ENABLE_RUNTIME_CHECKS
}
"
"
\n
Log level:
${
LOG_LEVEL_STR
}
"
"
\n
Log level:
${
CAF_LOG_LEVEL
}
"
"
\n
With mem. mgmt.:
${
CAF_BUILD_MEM_MANAGEMENT
}
"
"
\n
With mem. mgmt.:
${
CAF_BUILD_MEM_MANAGEMENT
}
"
"
\n
With exceptions:
${
CAF_BUILD_WITH_EXCEPTIONS
}
"
"
\n
With exceptions:
${
CAF_BUILD_WITH_EXCEPTIONS
}
"
"
\n
"
"
\n
"
...
...
Jenkinsfile
View file @
168a2a2b
...
@@ -17,7 +17,7 @@ releaseBuildFlags = defaultBuildFlags + [
...
@@ -17,7 +17,7 @@ releaseBuildFlags = defaultBuildFlags + [
debugBuildFlags
=
defaultBuildFlags
+
[
debugBuildFlags
=
defaultBuildFlags
+
[
'CAF_ENABLE_RUNTIME_CHECKS:BOOL=yes'
,
'CAF_ENABLE_RUNTIME_CHECKS:BOOL=yes'
,
'CAF_ENABLE_ADDRESS_SANITIZER:BOOL=yes'
,
'CAF_ENABLE_ADDRESS_SANITIZER:BOOL=yes'
,
'CAF_LOG_LEVEL:STRING=
4
'
,
'CAF_LOG_LEVEL:STRING=
TRACE
'
,
]
]
// Our build matrix. The keys are the operating system labels and the values
// Our build matrix. The keys are the operating system labels and the values
...
...
cmake/build_config.hpp.in
View file @
168a2a2b
...
@@ -19,9 +19,11 @@
...
@@ -19,9 +19,11 @@
#pragma once
#pragma once
#include "caf/detail/log_level.hpp"
// this header is auto-generated by CMake
// this header is auto-generated by CMake
#define CAF_LOG_LEVEL @CAF_LOG_LEVEL@
#define CAF_LOG_LEVEL
CAF_LOG_LEVEL_
@CAF_LOG_LEVEL@
#cmakedefine CAF_NO_MEM_MANAGEMENT
#cmakedefine CAF_NO_MEM_MANAGEMENT
...
...
configure
View file @
168a2a2b
...
@@ -284,28 +284,7 @@ while [ $# -ne 0 ]; do
...
@@ -284,28 +284,7 @@ while [ $# -ne 0 ]; do
append_cache_entry CAF_IOS_DEPLOYMENT_TARGET STRING
"
$optarg
"
append_cache_entry CAF_IOS_DEPLOYMENT_TARGET STRING
"
$optarg
"
;;
;;
--with-log-level
=
*
)
--with-log-level
=
*
)
level
=
`
echo
"
$optarg
"
|
tr
'[:lower:]'
'[:upper:]'
`
append_cache_entry CAF_LOG_LEVEL STRING
"
$optarg
"
case
$level
in
ERROR
)
append_cache_entry CAF_LOG_LEVEL STRING 0
;;
WARNING
)
append_cache_entry CAF_LOG_LEVEL STRING 1
;;
INFO
)
append_cache_entry CAF_LOG_LEVEL STRING 2
;;
DEBUG
)
append_cache_entry CAF_LOG_LEVEL STRING 3
;;
TRACE
)
append_cache_entry CAF_LOG_LEVEL STRING 4
;;
*
)
echo
"Invalid log level '
$level
'. Try '
$0
--help' to see valid values."
exit
1
;;
esac
;;
;;
--with-clang
=
*
)
--with-clang
=
*
)
clang
=
"
$optarg
"
clang
=
"
$optarg
"
...
...
libcaf_core/caf/atom.hpp
View file @
168a2a2b
...
@@ -23,6 +23,7 @@
...
@@ -23,6 +23,7 @@
#include <type_traits>
#include <type_traits>
#include "caf/detail/atom_val.hpp"
#include "caf/detail/atom_val.hpp"
#include "caf/fwd.hpp"
namespace
caf
{
namespace
caf
{
...
@@ -36,6 +37,9 @@ enum class atom_value : uint64_t {
...
@@ -36,6 +37,9 @@ enum class atom_value : uint64_t {
/// @relates atom_value
/// @relates atom_value
std
::
string
to_string
(
const
atom_value
&
what
);
std
::
string
to_string
(
const
atom_value
&
what
);
/// @relates atom_value
atom_value
to_lowercase
(
atom_value
x
);
atom_value
atom_from_string
(
const
std
::
string
&
x
);
atom_value
atom_from_string
(
const
std
::
string
&
x
);
/// Creates an atom from given string literal.
/// Creates an atom from given string literal.
...
...
libcaf_core/caf/detail/log_level.hpp
0 → 100644
View file @
168a2a2b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
/// Integer value for the QUIET log level.
#define CAF_LOG_LEVEL_QUIET 0
/// Integer value for the ERROR log level.
#define CAF_LOG_LEVEL_ERROR 3
/// Integer value for the WARNING log level.
#define CAF_LOG_LEVEL_WARNING 6
/// Integer value for the INFO log level.
#define CAF_LOG_LEVEL_INFO 9
/// Integer value for the DEBUG log level.
#define CAF_LOG_LEVEL_DEBUG 12
/// Integer value for the TRACE log level.
#define CAF_LOG_LEVEL_TRACE 15
libcaf_core/caf/detail/ringbuffer.hpp
0 → 100644
View file @
168a2a2b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#pragma once
#include <array>
#include <atomic>
#include <condition_variable>
#include <mutex>
namespace
caf
{
namespace
detail
{
// A ringbuffer designed for a single consumer and any number of producers that
// can hold a maximum of `Size - 1` elements.
template
<
class
T
,
size_t
Size
>
class
ringbuffer
{
public:
using
guard_type
=
std
::
unique_lock
<
std
::
mutex
>
;
ringbuffer
()
:
wr_pos_
(
0
),
rd_pos_
(
0
)
{
// nop
}
void
wait_nonempty
()
{
// Double-checked locking to reduce contention on mtx_.
if
(
!
empty
())
return
;
guard_type
guard
{
mtx_
};
while
(
empty
())
cv_empty_
.
wait
(
guard
);
}
T
&
front
()
{
// Safe to access without lock, because we assume a single consumer.
return
buf_
[
rd_pos_
];
}
void
pop_front
()
{
guard_type
guard
{
mtx_
};
auto
rp
=
rd_pos_
.
load
();
rd_pos_
=
next
(
rp
);
// Wakeup a waiting producers if the queue became non-full.
if
(
rp
==
next
(
wr_pos_
))
cv_full_
.
notify_all
();
}
void
push_back
(
T
&&
x
)
{
guard_type
guard
{
mtx_
};
while
(
full
())
cv_full_
.
wait
(
guard
);
auto
wp
=
wr_pos_
.
load
();
buf_
[
wp
]
=
std
::
move
(
x
);
wr_pos_
=
next
(
wp
);
if
(
rd_pos_
==
wp
)
cv_empty_
.
notify_all
();
}
bool
empty
()
const
noexcept
{
return
rd_pos_
==
wr_pos_
;
}
bool
full
()
const
noexcept
{
return
rd_pos_
==
next
(
wr_pos_
);
}
size_t
size
()
const
noexcept
{
auto
rp
=
rd_pos_
.
load
();
auto
wp
=
wr_pos_
.
load
();
if
(
rp
==
wp
)
return
0
;
if
(
rp
<
wp
)
return
wp
-
rp
;
return
Size
-
rp
+
wp
;
}
private:
static
size_t
next
(
size_t
pos
)
{
return
(
pos
+
1
)
%
Size
;
}
// Guards queue_.
mutable
std
::
mutex
mtx_
;
// Signals the empty condition.
std
::
condition_variable
cv_empty_
;
// Signals the full condition.
std
::
condition_variable
cv_full_
;
// Stores the current write position in the ringbuffer.
std
::
atomic
<
size_t
>
wr_pos_
;
// Stores the current read position in the ringbuffer.
std
::
atomic
<
size_t
>
rd_pos_
;
// Stores events in a circular ringbuffer.
std
::
array
<
T
,
Size
>
buf_
;
};
}
// namespace detail
}
// namespace caf
libcaf_core/caf/logger.hpp
View file @
168a2a2b
This diff is collapsed.
Click to expand it.
libcaf_core/src/atom.cpp
View file @
168a2a2b
...
@@ -18,34 +18,57 @@
...
@@ -18,34 +18,57 @@
#include "caf/atom.hpp"
#include "caf/atom.hpp"
#include <array>
#include <cstring>
#include <cstring>
#include "caf/string_view.hpp"
namespace
caf
{
namespace
caf
{
atom_value
atom_from_string
(
const
std
::
string
&
x
)
{
namespace
{
if
(
x
.
size
()
>
10
)
return
atom
(
""
);
/// A buffer for decoding atom values.
char
buf
[
11
];
using
atom_value_buf
=
std
::
array
<
char
,
11
>
;
memcpy
(
buf
,
x
.
c_str
(),
x
.
size
());
buf
[
x
.
size
()]
=
'\0'
;
return
atom
(
buf
);
}
std
::
string
to_string
(
const
atom_value
&
what
)
{
size_t
decode
(
atom_value_buf
&
buf
,
atom_value
what
)
{
size_t
pos
=
0
;
auto
x
=
static_cast
<
uint64_t
>
(
what
);
auto
x
=
static_cast
<
uint64_t
>
(
what
);
std
::
string
result
;
// Don't read characters before we found the leading 0xF.
result
.
reserve
(
11
);
// don't read characters before we found the leading 0xF
// first four bits set?
bool
read_chars
=
((
x
&
0xF000000000000000
)
>>
60
)
==
0xF
;
bool
read_chars
=
((
x
&
0xF000000000000000
)
>>
60
)
==
0xF
;
uint64_t
mask
=
0x0FC0000000000000
;
uint64_t
mask
=
0x0FC0000000000000
;
for
(
int
bitshift
=
54
;
bitshift
>=
0
;
bitshift
-=
6
,
mask
>>=
6
)
{
for
(
int
bitshift
=
54
;
bitshift
>=
0
;
bitshift
-=
6
,
mask
>>=
6
)
{
if
(
read_chars
)
if
(
read_chars
)
result
+
=
detail
::
decoding_table
[(
x
&
mask
)
>>
bitshift
];
buf
[
pos
++
]
=
detail
::
decoding_table
[(
x
&
mask
)
>>
bitshift
];
else
if
(((
x
&
mask
)
>>
bitshift
)
==
0xF
)
else
if
(((
x
&
mask
)
>>
bitshift
)
==
0xF
)
read_chars
=
true
;
read_chars
=
true
;
}
}
return
result
;
buf
[
pos
]
=
'\0'
;
return
pos
;
}
}
// namespace <anonymous>
atom_value
to_lowercase
(
atom_value
x
)
{
atom_value_buf
buf
;
decode
(
buf
,
x
);
for
(
auto
ch
=
buf
.
data
();
*
ch
!=
'\0'
;
++
ch
)
*
ch
=
static_cast
<
char
>
(
tolower
(
*
ch
));
return
static_cast
<
atom_value
>
(
detail
::
atom_val
(
buf
.
data
()));
}
atom_value
atom_from_string
(
const
std
::
string
&
x
)
{
if
(
x
.
size
()
>
10
)
return
atom
(
""
);
atom_value_buf
buf
;
memcpy
(
buf
.
data
(),
x
.
c_str
(),
x
.
size
());
buf
[
x
.
size
()]
=
'\0'
;
return
static_cast
<
atom_value
>
(
detail
::
atom_val
(
buf
.
data
()));
}
std
::
string
to_string
(
const
atom_value
&
x
)
{
atom_value_buf
str
;
auto
len
=
decode
(
str
,
x
);
return
std
::
string
(
str
.
begin
(),
str
.
begin
()
+
len
);
}
}
}
// namespace caf
}
// namespace caf
libcaf_core/src/logger.cpp
View file @
168a2a2b
This diff is collapsed.
Click to expand it.
libcaf_core/test/logger.cpp
View file @
168a2a2b
...
@@ -179,11 +179,11 @@ CAF_TEST(rendering) {
...
@@ -179,11 +179,11 @@ CAF_TEST(rendering) {
// Rendering of events.
// Rendering of events.
logger
::
event
e
{
logger
::
event
e
{
CAF_LOG_LEVEL_WARNING
,
CAF_LOG_LEVEL_WARNING
,
42
,
"unit.test"
,
"unit.test"
,
"void ns::foo::bar()"
,
"void ns::foo::bar()"
,
"bar"
,
"bar"
,
"foo.cpp"
,
"foo.cpp"
,
42
,
"hello world"
,
"hello world"
,
std
::
this_thread
::
get_id
(),
std
::
this_thread
::
get_id
(),
0
,
0
,
...
...
libcaf_core/test/ringbuffer.cpp
0 → 100644
View file @
168a2a2b
/******************************************************************************
* ____ _ _____ *
* / ___| / \ | ___| C++ *
* | | / _ \ | |_ Actor *
* | |___ / ___ \| _| Framework *
* \____/_/ \_|_| *
* *
* Copyright 2011-2018 Dominik Charousset *
* *
* Distributed under the terms and conditions of the BSD 3-Clause License or *
* (at your option) under the terms and conditions of the Boost Software *
* License 1.0. See accompanying files LICENSE and LICENSE_ALTERNATIVE. *
* *
* If you did not receive a copy of the license files, see *
* http://opensource.org/licenses/BSD-3-Clause and *
* http://www.boost.org/LICENSE_1_0.txt. *
******************************************************************************/
#define CAF_SUITE ringbuffer
#include "caf/detail/ringbuffer.hpp"
#include "caf/test/dsl.hpp"
#include <algorithm>
using
namespace
caf
;
namespace
{
static
constexpr
size_t
buf_size
=
64
;
using
int_ringbuffer
=
detail
::
ringbuffer
<
int
,
buf_size
>
;
std
::
vector
<
int
>
consumer
(
int_ringbuffer
&
buf
,
size_t
num
)
{
std
::
vector
<
int
>
result
;
for
(
size_t
i
=
0
;
i
<
num
;
++
i
)
{
buf
.
wait_nonempty
();
result
.
emplace_back
(
buf
.
front
());
buf
.
pop_front
();
}
return
result
;
}
void
producer
(
int_ringbuffer
&
buf
,
int
first
,
int
last
)
{
for
(
auto
i
=
first
;
i
!=
last
;
++
i
)
buf
.
push_back
(
std
::
move
(
i
));
}
struct
fixture
{
int_ringbuffer
buf
;
};
}
// namespace <anonymous>
CAF_TEST_FIXTURE_SCOPE
(
ringbuffer_tests
,
fixture
)
CAF_TEST
(
construction
)
{
CAF_CHECK_EQUAL
(
buf
.
empty
(),
true
);
CAF_CHECK_EQUAL
(
buf
.
full
(),
false
);
CAF_CHECK_EQUAL
(
buf
.
size
(),
0u
);
}
CAF_TEST
(
push_back
)
{
CAF_MESSAGE
(
"add one element"
);
buf
.
push_back
(
42
);
CAF_CHECK_EQUAL
(
buf
.
empty
(),
false
);
CAF_CHECK_EQUAL
(
buf
.
full
(),
false
);
CAF_CHECK_EQUAL
(
buf
.
size
(),
1u
);
CAF_CHECK_EQUAL
(
buf
.
front
(),
42
);
CAF_MESSAGE
(
"remove element"
);
buf
.
pop_front
();
CAF_CHECK_EQUAL
(
buf
.
empty
(),
true
);
CAF_CHECK_EQUAL
(
buf
.
full
(),
false
);
CAF_CHECK_EQUAL
(
buf
.
size
(),
0u
);
CAF_MESSAGE
(
"fill buffer"
);
for
(
int
i
=
0
;
i
<
static_cast
<
int
>
(
buf_size
-
1
);
++
i
)
buf
.
push_back
(
std
::
move
(
i
));
CAF_CHECK_EQUAL
(
buf
.
empty
(),
false
);
CAF_CHECK_EQUAL
(
buf
.
full
(),
true
);
CAF_CHECK_EQUAL
(
buf
.
size
(),
buf_size
-
1
);
CAF_CHECK_EQUAL
(
buf
.
front
(),
0
);
}
CAF_TEST
(
concurrent
access
)
{
std
::
vector
<
std
::
thread
>
producers
;
producers
.
emplace_back
(
producer
,
std
::
ref
(
buf
),
0
,
100
);
producers
.
emplace_back
(
producer
,
std
::
ref
(
buf
),
100
,
200
);
producers
.
emplace_back
(
producer
,
std
::
ref
(
buf
),
200
,
300
);
auto
vec
=
consumer
(
buf
,
300
);
std
::
sort
(
vec
.
begin
(),
vec
.
end
());
CAF_CHECK
(
std
::
is_sorted
(
vec
.
begin
(),
vec
.
end
()));
CAF_CHECK_EQUAL
(
vec
.
size
(),
300u
);
CAF_CHECK_EQUAL
(
vec
.
front
(),
0
);
CAF_CHECK_EQUAL
(
vec
.
back
(),
299
);
for
(
auto
&
t
:
producers
)
t
.
join
();
}
CAF_TEST_FIXTURE_SCOPE_END
()
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