Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
J
jlib
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
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
captainwong
jlib
Commits
b73967c5
Commit
b73967c5
authored
Dec 09, 2015
by
captainwong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
testing muduo log
parent
9910e719
Hide whitespace changes
Inline
Side-by-side
Showing
17 changed files
with
1452 additions
and
1 deletion
+1452
-1
AsyncLogging.cc
test/test/include/muduo/base/AsyncLogging.cc
+131
-0
AsyncLogging.h
test/test/include/muduo/base/AsyncLogging.h
+78
-0
BlockingQueue.h
test/test/include/muduo/base/BlockingQueue.h
+80
-0
BoundedBlockingQueue.h
test/test/include/muduo/base/BoundedBlockingQueue.h
+90
-0
Condition.cc
test/test/include/muduo/base/Condition.cc
+20
-0
Condition.h
test/test/include/muduo/base/Condition.h
+56
-0
CountDownLatch.cc
test/test/include/muduo/base/CountDownLatch.cc
+41
-0
CountDownLatch.h
test/test/include/muduo/base/CountDownLatch.h
+36
-0
CurrentThread.h
test/test/include/muduo/base/CurrentThread.h
+52
-0
LogStream.cc
test/test/include/muduo/base/LogStream.cc
+212
-0
LogStream.h
test/test/include/muduo/base/LogStream.h
+199
-0
Mutex.h
test/test/include/muduo/base/Mutex.h
+163
-0
Thread.cc
test/test/include/muduo/base/Thread.cc
+223
-0
Thread.h
test/test/include/muduo/base/Thread.h
+55
-0
test.cpp
test/test/test.cpp
+1
-1
test.vcxproj
test/test/test.vcxproj
+3
-0
test.vcxproj.filters
test/test/test.vcxproj.filters
+12
-0
No files found.
test/test/include/muduo/base/AsyncLogging.cc
0 → 100644
View file @
b73967c5
#include "stdafx.h"
#include <muduo/base/AsyncLogging.h>
#include <muduo/base/LogFile.h>
#include <muduo/base/Timestamp.h>
#include <stdio.h>
using
namespace
muduo
;
AsyncLogging
::
AsyncLogging
(
const
string
&
basename
,
size_t
rollSize
,
int
flushInterval
)
:
flushInterval_
(
flushInterval
),
running_
(
false
),
basename_
(
basename
),
rollSize_
(
rollSize
),
thread_
(
boost
::
bind
(
&
AsyncLogging
::
threadFunc
,
this
),
"Logging"
),
latch_
(
1
),
mutex_
(),
cond_
(
mutex_
),
currentBuffer_
(
new
Buffer
),
nextBuffer_
(
new
Buffer
),
buffers_
()
{
currentBuffer_
->
bzero
();
nextBuffer_
->
bzero
();
buffers_
.
reserve
(
16
);
}
void
AsyncLogging
::
append
(
const
char
*
logline
,
int
len
)
{
muduo
::
MutexLockGuard
lock
(
mutex_
);
if
(
currentBuffer_
->
avail
()
>
len
)
{
currentBuffer_
->
append
(
logline
,
len
);
}
else
{
buffers_
.
push_back
(
currentBuffer_
.
release
());
if
(
nextBuffer_
)
{
currentBuffer_
=
boost
::
ptr_container
::
move
(
nextBuffer_
);
}
else
{
currentBuffer_
.
reset
(
new
Buffer
);
// Rarely happens
}
currentBuffer_
->
append
(
logline
,
len
);
cond_
.
notify
();
}
}
void
AsyncLogging
::
threadFunc
()
{
assert
(
running_
==
true
);
latch_
.
countDown
();
LogFile
output
(
basename_
,
rollSize_
,
false
);
BufferPtr
newBuffer1
(
new
Buffer
);
BufferPtr
newBuffer2
(
new
Buffer
);
newBuffer1
->
bzero
();
newBuffer2
->
bzero
();
BufferVector
buffersToWrite
;
buffersToWrite
.
reserve
(
16
);
while
(
running_
)
{
assert
(
newBuffer1
&&
newBuffer1
->
length
()
==
0
);
assert
(
newBuffer2
&&
newBuffer2
->
length
()
==
0
);
assert
(
buffersToWrite
.
empty
());
{
muduo
::
MutexLockGuard
lock
(
mutex_
);
if
(
buffers_
.
empty
())
// unusual usage!
{
cond_
.
waitForSeconds
(
flushInterval_
);
}
buffers_
.
push_back
(
currentBuffer_
.
release
());
currentBuffer_
=
boost
::
ptr_container
::
move
(
newBuffer1
);
buffersToWrite
.
swap
(
buffers_
);
if
(
!
nextBuffer_
)
{
nextBuffer_
=
boost
::
ptr_container
::
move
(
newBuffer2
);
}
}
assert
(
!
buffersToWrite
.
empty
());
if
(
buffersToWrite
.
size
()
>
25
)
{
char
buf
[
256
];
snprintf
(
buf
,
sizeof
buf
,
"Dropped log messages at %s, %zd larger buffers
\n
"
,
Timestamp
::
now
().
toFormattedString
().
c_str
(),
buffersToWrite
.
size
()
-
2
);
fputs
(
buf
,
stderr
);
output
.
append
(
buf
,
static_cast
<
int
>
(
strlen
(
buf
)));
buffersToWrite
.
erase
(
buffersToWrite
.
begin
()
+
2
,
buffersToWrite
.
end
());
}
for
(
size_t
i
=
0
;
i
<
buffersToWrite
.
size
();
++
i
)
{
// FIXME: use unbuffered stdio FILE ? or use ::writev ?
output
.
append
(
buffersToWrite
[
i
].
data
(),
buffersToWrite
[
i
].
length
());
}
if
(
buffersToWrite
.
size
()
>
2
)
{
// drop non-bzero-ed buffers, avoid trashing
buffersToWrite
.
resize
(
2
);
}
if
(
!
newBuffer1
)
{
assert
(
!
buffersToWrite
.
empty
());
newBuffer1
=
buffersToWrite
.
pop_back
();
newBuffer1
->
reset
();
}
if
(
!
newBuffer2
)
{
assert
(
!
buffersToWrite
.
empty
());
newBuffer2
=
buffersToWrite
.
pop_back
();
newBuffer2
->
reset
();
}
buffersToWrite
.
clear
();
output
.
flush
();
}
output
.
flush
();
}
test/test/include/muduo/base/AsyncLogging.h
0 → 100644
View file @
b73967c5
#ifndef MUDUO_BASE_ASYNCLOGGING_H
#define MUDUO_BASE_ASYNCLOGGING_H
#include <muduo/base/BlockingQueue.h>
#include <muduo/base/BoundedBlockingQueue.h>
#include <muduo/base/CountDownLatch.h>
#include <muduo/base/Mutex.h>
#include <muduo/base/Thread.h>
#include <muduo/base/LogStream.h>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
namespace
muduo
{
class
AsyncLogging
:
boost
::
noncopyable
{
public
:
AsyncLogging
(
const
string
&
basename
,
size_t
rollSize
,
int
flushInterval
=
3
);
~
AsyncLogging
()
{
if
(
running_
)
{
stop
();
}
}
void
append
(
const
char
*
logline
,
int
len
);
void
start
()
{
running_
=
true
;
thread_
.
start
();
latch_
.
wait
();
}
void
stop
()
{
running_
=
false
;
cond_
.
notify
();
thread_
.
join
();
}
private
:
// declare but not define, prevent compiler-synthesized functions
AsyncLogging
(
const
AsyncLogging
&
);
// ptr_container
void
operator
=
(
const
AsyncLogging
&
);
// ptr_container
void
threadFunc
();
typedef
muduo
::
detail
::
FixedBuffer
<
muduo
::
detail
::
kLargeBuffer
>
Buffer
;
typedef
boost
::
ptr_vector
<
Buffer
>
BufferVector
;
typedef
BufferVector
::
auto_type
BufferPtr
;
const
int
flushInterval_
;
bool
running_
;
string
basename_
;
size_t
rollSize_
;
muduo
::
Thread
thread_
;
muduo
::
CountDownLatch
latch_
;
muduo
::
MutexLock
mutex_
;
muduo
::
Condition
cond_
;
BufferPtr
currentBuffer_
;
BufferPtr
nextBuffer_
;
BufferVector
buffers_
;
};
}
#endif // MUDUO_BASE_ASYNCLOGGING_H
test/test/include/muduo/base/BlockingQueue.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_BLOCKINGQUEUE_H
#define MUDUO_BASE_BLOCKINGQUEUE_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
#include <deque>
#include <assert.h>
namespace
muduo
{
template
<
typename
T
>
class
BlockingQueue
:
boost
::
noncopyable
{
public
:
BlockingQueue
()
:
mutex_
(),
notEmpty_
(
mutex_
),
queue_
()
{
}
void
put
(
const
T
&
x
)
{
MutexLockGuard
lock
(
mutex_
);
queue_
.
push_back
(
x
);
notEmpty_
.
notify
();
// wait morphing saves us
// http://www.domaigne.com/blog/computing/condvars-signal-with-mutex-locked-or-not/
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
void
put
(
T
&&
x
)
{
MutexLockGuard
lock
(
mutex_
);
queue_
.
push_back
(
std
::
move
(
x
));
notEmpty_
.
notify
();
}
// FIXME: emplace()
#endif
T
take
()
{
MutexLockGuard
lock
(
mutex_
);
// always use a while-loop, due to spurious wakeup
while
(
queue_
.
empty
())
{
notEmpty_
.
wait
();
}
assert
(
!
queue_
.
empty
());
#ifdef __GXX_EXPERIMENTAL_CXX0X__
T
front
(
std
::
move
(
queue_
.
front
()));
#else
T
front
(
queue_
.
front
());
#endif
queue_
.
pop_front
();
return
front
;
}
size_t
size
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
queue_
.
size
();
}
private
:
mutable
MutexLock
mutex_
;
Condition
notEmpty_
;
std
::
deque
<
T
>
queue_
;
};
}
#endif // MUDUO_BASE_BLOCKINGQUEUE_H
test/test/include/muduo/base/BoundedBlockingQueue.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H
#define MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <boost/circular_buffer.hpp>
#include <boost/noncopyable.hpp>
#include <assert.h>
namespace
muduo
{
template
<
typename
T
>
class
BoundedBlockingQueue
:
boost
::
noncopyable
{
public
:
explicit
BoundedBlockingQueue
(
int
maxSize
)
:
mutex_
(),
notEmpty_
(
mutex_
),
notFull_
(
mutex_
),
queue_
(
maxSize
)
{
}
void
put
(
const
T
&
x
)
{
MutexLockGuard
lock
(
mutex_
);
while
(
queue_
.
full
())
{
notFull_
.
wait
();
}
assert
(
!
queue_
.
full
());
queue_
.
push_back
(
x
);
notEmpty_
.
notify
();
}
T
take
()
{
MutexLockGuard
lock
(
mutex_
);
while
(
queue_
.
empty
())
{
notEmpty_
.
wait
();
}
assert
(
!
queue_
.
empty
());
T
front
(
queue_
.
front
());
queue_
.
pop_front
();
notFull_
.
notify
();
return
front
;
}
bool
empty
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
queue_
.
empty
();
}
bool
full
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
queue_
.
full
();
}
size_t
size
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
queue_
.
size
();
}
size_t
capacity
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
queue_
.
capacity
();
}
private
:
mutable
MutexLock
mutex_
;
Condition
notEmpty_
;
Condition
notFull_
;
boost
::
circular_buffer
<
T
>
queue_
;
};
}
#endif // MUDUO_BASE_BOUNDEDBLOCKINGQUEUE_H
test/test/include/muduo/base/Condition.cc
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include <muduo/base/Condition.h>
#include <errno.h>
// returns true if time out, false otherwise.
bool
muduo
::
Condition
::
waitForSeconds
(
int
seconds
)
{
struct
timespec
abstime
;
// FIXME: use CLOCK_MONOTONIC or CLOCK_MONOTONIC_RAW to prevent time rewind.
clock_gettime
(
CLOCK_REALTIME
,
&
abstime
);
abstime
.
tv_sec
+=
seconds
;
MutexLock
::
UnassignGuard
ug
(
mutex_
);
return
ETIMEDOUT
==
pthread_cond_timedwait
(
&
pcond_
,
mutex_
.
getPthreadMutex
(),
&
abstime
);
}
test/test/include/muduo/base/Condition.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_CONDITION_H
#define MUDUO_BASE_CONDITION_H
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
#include <pthread.h>
namespace
muduo
{
class
Condition
:
boost
::
noncopyable
{
public
:
explicit
Condition
(
MutexLock
&
mutex
)
:
mutex_
(
mutex
)
{
MCHECK
(
pthread_cond_init
(
&
pcond_
,
NULL
));
}
~
Condition
()
{
MCHECK
(
pthread_cond_destroy
(
&
pcond_
));
}
void
wait
()
{
MutexLock
::
UnassignGuard
ug
(
mutex_
);
MCHECK
(
pthread_cond_wait
(
&
pcond_
,
mutex_
.
getPthreadMutex
()));
}
// returns true if time out, false otherwise.
bool
waitForSeconds
(
int
seconds
);
void
notify
()
{
MCHECK
(
pthread_cond_signal
(
&
pcond_
));
}
void
notifyAll
()
{
MCHECK
(
pthread_cond_broadcast
(
&
pcond_
));
}
private
:
MutexLock
&
mutex_
;
pthread_cond_t
pcond_
;
};
}
#endif // MUDUO_BASE_CONDITION_H
test/test/include/muduo/base/CountDownLatch.cc
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include <muduo/base/CountDownLatch.h>
using
namespace
muduo
;
CountDownLatch
::
CountDownLatch
(
int
count
)
:
mutex_
(),
condition_
(
mutex_
),
count_
(
count
)
{
}
void
CountDownLatch
::
wait
()
{
MutexLockGuard
lock
(
mutex_
);
while
(
count_
>
0
)
{
condition_
.
wait
();
}
}
void
CountDownLatch
::
countDown
()
{
MutexLockGuard
lock
(
mutex_
);
--
count_
;
if
(
count_
==
0
)
{
condition_
.
notifyAll
();
}
}
int
CountDownLatch
::
getCount
()
const
{
MutexLockGuard
lock
(
mutex_
);
return
count_
;
}
test/test/include/muduo/base/CountDownLatch.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_COUNTDOWNLATCH_H
#define MUDUO_BASE_COUNTDOWNLATCH_H
#include <muduo/base/Condition.h>
#include <muduo/base/Mutex.h>
#include <boost/noncopyable.hpp>
namespace
muduo
{
class
CountDownLatch
:
boost
::
noncopyable
{
public
:
explicit
CountDownLatch
(
int
count
);
void
wait
();
void
countDown
();
int
getCount
()
const
;
private
:
mutable
MutexLock
mutex_
;
Condition
condition_
;
int
count_
;
};
}
#endif // MUDUO_BASE_COUNTDOWNLATCH_H
test/test/include/muduo/base/CurrentThread.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_CURRENTTHREAD_H
#define MUDUO_BASE_CURRENTTHREAD_H
#include <stdint.h>
namespace
muduo
{
namespace
CurrentThread
{
// internal
extern
__thread
int
t_cachedTid
;
extern
__thread
char
t_tidString
[
32
];
extern
__thread
int
t_tidStringLength
;
extern
__thread
const
char
*
t_threadName
;
void
cacheTid
();
inline
int
tid
()
{
if
(
__builtin_expect
(
t_cachedTid
==
0
,
0
))
{
cacheTid
();
}
return
t_cachedTid
;
}
inline
const
char
*
tidString
()
// for logging
{
return
t_tidString
;
}
inline
int
tidStringLength
()
// for logging
{
return
t_tidStringLength
;
}
inline
const
char
*
name
()
{
return
t_threadName
;
}
bool
isMainThread
();
void
sleepUsec
(
int64_t
usec
);
}
}
#endif
test/test/include/muduo/base/LogStream.cc
0 → 100644
View file @
b73967c5
#include <muduo/base/LogStream.h>
#include <algorithm>
#include <limits>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
#include <assert.h>
#include <string.h>
#include <stdint.h>
#include <stdio.h>
using
namespace
muduo
;
using
namespace
muduo
::
detail
;
#if defined(__clang__)
#pragma clang diagnostic ignored "-Wtautological-compare"
#else
#pragma GCC diagnostic ignored "-Wtype-limits"
#endif
namespace
muduo
{
namespace
detail
{
const
char
digits
[]
=
"9876543210123456789"
;
const
char
*
zero
=
digits
+
9
;
BOOST_STATIC_ASSERT
(
sizeof
(
digits
)
==
20
);
const
char
digitsHex
[]
=
"0123456789ABCDEF"
;
BOOST_STATIC_ASSERT
(
sizeof
digitsHex
==
17
);
// Efficient Integer to String Conversions, by Matthew Wilson.
template
<
typename
T
>
size_t
convert
(
char
buf
[],
T
value
)
{
T
i
=
value
;
char
*
p
=
buf
;
do
{
int
lsd
=
static_cast
<
int
>
(
i
%
10
);
i
/=
10
;
*
p
++
=
zero
[
lsd
];
}
while
(
i
!=
0
);
if
(
value
<
0
)
{
*
p
++
=
'-'
;
}
*
p
=
'\0'
;
std
::
reverse
(
buf
,
p
);
return
p
-
buf
;
}
size_t
convertHex
(
char
buf
[],
uintptr_t
value
)
{
uintptr_t
i
=
value
;
char
*
p
=
buf
;
do
{
int
lsd
=
static_cast
<
int
>
(
i
%
16
);
i
/=
16
;
*
p
++
=
digitsHex
[
lsd
];
}
while
(
i
!=
0
);
*
p
=
'\0'
;
std
::
reverse
(
buf
,
p
);
return
p
-
buf
;
}
template
class
FixedBuffer
<
kSmallBuffer
>
;
template
class
FixedBuffer
<
kLargeBuffer
>
;
}
}
template
<
int
SIZE
>
const
char
*
FixedBuffer
<
SIZE
>::
debugString
()
{
*
cur_
=
'\0'
;
return
data_
;
}
template
<
int
SIZE
>
void
FixedBuffer
<
SIZE
>::
cookieStart
()
{
}
template
<
int
SIZE
>
void
FixedBuffer
<
SIZE
>::
cookieEnd
()
{
}
void
LogStream
::
staticCheck
()
{
BOOST_STATIC_ASSERT
(
kMaxNumericSize
-
10
>
std
::
numeric_limits
<
double
>::
digits10
);
BOOST_STATIC_ASSERT
(
kMaxNumericSize
-
10
>
std
::
numeric_limits
<
long
double
>::
digits10
);
BOOST_STATIC_ASSERT
(
kMaxNumericSize
-
10
>
std
::
numeric_limits
<
long
>::
digits10
);
BOOST_STATIC_ASSERT
(
kMaxNumericSize
-
10
>
std
::
numeric_limits
<
long
long
>::
digits10
);
}
template
<
typename
T
>
void
LogStream
::
formatInteger
(
T
v
)
{
if
(
buffer_
.
avail
()
>=
kMaxNumericSize
)
{
size_t
len
=
convert
(
buffer_
.
current
(),
v
);
buffer_
.
add
(
len
);
}
}
LogStream
&
LogStream
::
operator
<<
(
short
v
)
{
*
this
<<
static_cast
<
int
>
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
unsigned
short
v
)
{
*
this
<<
static_cast
<
unsigned
int
>
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
int
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
unsigned
int
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
long
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
unsigned
long
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
long
long
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
unsigned
long
long
v
)
{
formatInteger
(
v
);
return
*
this
;
}
LogStream
&
LogStream
::
operator
<<
(
const
void
*
p
)
{
uintptr_t
v
=
reinterpret_cast
<
uintptr_t
>
(
p
);
if
(
buffer_
.
avail
()
>=
kMaxNumericSize
)
{
char
*
buf
=
buffer_
.
current
();
buf
[
0
]
=
'0'
;
buf
[
1
]
=
'x'
;
size_t
len
=
convertHex
(
buf
+
2
,
v
);
buffer_
.
add
(
len
+
2
);
}
return
*
this
;
}
// FIXME: replace this with Grisu3 by Florian Loitsch.
LogStream
&
LogStream
::
operator
<<
(
double
v
)
{
if
(
buffer_
.
avail
()
>=
kMaxNumericSize
)
{
int
len
=
snprintf
(
buffer_
.
current
(),
kMaxNumericSize
,
"%.12g"
,
v
);
buffer_
.
add
(
len
);
}
return
*
this
;
}
template
<
typename
T
>
Fmt
::
Fmt
(
const
char
*
fmt
,
T
val
)
{
BOOST_STATIC_ASSERT
(
boost
::
is_arithmetic
<
T
>::
value
==
true
);
length_
=
snprintf
(
buf_
,
sizeof
buf_
,
fmt
,
val
);
assert
(
static_cast
<
size_t
>
(
length_
)
<
sizeof
buf_
);
}
// Explicit instantiations
template
Fmt
::
Fmt
(
const
char
*
fmt
,
char
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
short
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
unsigned
short
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
int
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
unsigned
int
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
long
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
unsigned
long
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
long
long
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
unsigned
long
long
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
float
);
template
Fmt
::
Fmt
(
const
char
*
fmt
,
double
);
test/test/include/muduo/base/LogStream.h
0 → 100644
View file @
b73967c5
#ifndef MUDUO_BASE_LOGSTREAM_H
#define MUDUO_BASE_LOGSTREAM_H
#include <muduo/base/StringPiece.h>
#include <muduo/base/Types.h>
#include <assert.h>
#include <string.h> // memcpy
#ifndef MUDUO_STD_STRING
#include <string>
#endif
#include <boost/noncopyable.hpp>
namespace
muduo
{
namespace
detail
{
const
int
kSmallBuffer
=
4000
;
const
int
kLargeBuffer
=
4000
*
1000
;
template
<
int
SIZE
>
class
FixedBuffer
:
boost
::
noncopyable
{
public
:
FixedBuffer
()
:
cur_
(
data_
)
{
setCookie
(
cookieStart
);
}
~
FixedBuffer
()
{
setCookie
(
cookieEnd
);
}
void
append
(
const
char
*
/*restrict*/
buf
,
size_t
len
)
{
// FIXME: append partially
if
(
implicit_cast
<
size_t
>
(
avail
())
>
len
)
{
memcpy
(
cur_
,
buf
,
len
);
cur_
+=
len
;
}
}
const
char
*
data
()
const
{
return
data_
;
}
int
length
()
const
{
return
static_cast
<
int
>
(
cur_
-
data_
);
}
// write to data_ directly
char
*
current
()
{
return
cur_
;
}
int
avail
()
const
{
return
static_cast
<
int
>
(
end
()
-
cur_
);
}
void
add
(
size_t
len
)
{
cur_
+=
len
;
}
void
reset
()
{
cur_
=
data_
;
}
void
bzero
()
{
::
bzero
(
data_
,
sizeof
data_
);
}
// for used by GDB
const
char
*
debugString
();
void
setCookie
(
void
(
*
cookie
)())
{
cookie_
=
cookie
;
}
// for used by unit test
string
toString
()
const
{
return
string
(
data_
,
length
());
}
StringPiece
toStringPiece
()
const
{
return
StringPiece
(
data_
,
length
());
}
private
:
const
char
*
end
()
const
{
return
data_
+
sizeof
data_
;
}
// Must be outline function for cookies.
static
void
cookieStart
();
static
void
cookieEnd
();
void
(
*
cookie_
)();
char
data_
[
SIZE
];
char
*
cur_
;
};
}
class
LogStream
:
boost
::
noncopyable
{
typedef
LogStream
self
;
public
:
typedef
detail
::
FixedBuffer
<
detail
::
kSmallBuffer
>
Buffer
;
self
&
operator
<<
(
bool
v
)
{
buffer_
.
append
(
v
?
"1"
:
"0"
,
1
);
return
*
this
;
}
self
&
operator
<<
(
short
);
self
&
operator
<<
(
unsigned
short
);
self
&
operator
<<
(
int
);
self
&
operator
<<
(
unsigned
int
);
self
&
operator
<<
(
long
);
self
&
operator
<<
(
unsigned
long
);
self
&
operator
<<
(
long
long
);
self
&
operator
<<
(
unsigned
long
long
);
self
&
operator
<<
(
const
void
*
);
self
&
operator
<<
(
float
v
)
{
*
this
<<
static_cast
<
double
>
(
v
);
return
*
this
;
}
self
&
operator
<<
(
double
);
// self& operator<<(long double);
self
&
operator
<<
(
char
v
)
{
buffer_
.
append
(
&
v
,
1
);
return
*
this
;
}
// self& operator<<(signed char);
// self& operator<<(unsigned char);
self
&
operator
<<
(
const
char
*
str
)
{
if
(
str
)
{
buffer_
.
append
(
str
,
strlen
(
str
));
}
else
{
buffer_
.
append
(
"(null)"
,
6
);
}
return
*
this
;
}
self
&
operator
<<
(
const
unsigned
char
*
str
)
{
return
operator
<<
(
reinterpret_cast
<
const
char
*>
(
str
));
}
self
&
operator
<<
(
const
string
&
v
)
{
buffer_
.
append
(
v
.
c_str
(),
v
.
size
());
return
*
this
;
}
#ifndef MUDUO_STD_STRING
self
&
operator
<<
(
const
std
::
string
&
v
)
{
buffer_
.
append
(
v
.
c_str
(),
v
.
size
());
return
*
this
;
}
#endif
self
&
operator
<<
(
const
StringPiece
&
v
)
{
buffer_
.
append
(
v
.
data
(),
v
.
size
());
return
*
this
;
}
self
&
operator
<<
(
const
Buffer
&
v
)
{
*
this
<<
v
.
toStringPiece
();
return
*
this
;
}
void
append
(
const
char
*
data
,
int
len
)
{
buffer_
.
append
(
data
,
len
);
}
const
Buffer
&
buffer
()
const
{
return
buffer_
;
}
void
resetBuffer
()
{
buffer_
.
reset
();
}
private
:
void
staticCheck
();
template
<
typename
T
>
void
formatInteger
(
T
);
Buffer
buffer_
;
static
const
int
kMaxNumericSize
=
32
;
};
class
Fmt
// : boost::noncopyable
{
public
:
template
<
typename
T
>
Fmt
(
const
char
*
fmt
,
T
val
);
const
char
*
data
()
const
{
return
buf_
;
}
int
length
()
const
{
return
length_
;
}
private
:
char
buf_
[
32
];
int
length_
;
};
inline
LogStream
&
operator
<<
(
LogStream
&
s
,
const
Fmt
&
fmt
)
{
s
.
append
(
fmt
.
data
(),
fmt
.
length
());
return
s
;
}
}
#endif // MUDUO_BASE_LOGSTREAM_H
test/test/include/muduo/base/Mutex.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_MUTEX_H
#define MUDUO_BASE_MUTEX_H
#include <muduo/base/CurrentThread.h>
#include <boost/noncopyable.hpp>
#include <assert.h>
#include <pthread.h>
#ifdef CHECK_PTHREAD_RETURN_VALUE
#ifdef NDEBUG
__BEGIN_DECLS
extern
void
__assert_perror_fail
(
int
errnum
,
const
char
*
file
,
unsigned
int
line
,
const
char
*
function
)
__THROW
__attribute__
((
__noreturn__
));
__END_DECLS
#endif
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret); \
if (__builtin_expect(errnum != 0, 0)) \
__assert_perror_fail (errnum, __FILE__, __LINE__, __func__);})
#else // CHECK_PTHREAD_RETURN_VALUE
#define MCHECK(ret) ({ __typeof__ (ret) errnum = (ret); \
assert(errnum == 0); (void) errnum;})
#endif // CHECK_PTHREAD_RETURN_VALUE
namespace
muduo
{
// Use as data member of a class, eg.
//
// class Foo
// {
// public:
// int size() const;
//
// private:
// mutable MutexLock mutex_;
// std::vector<int> data_; // GUARDED BY mutex_
// };
class
MutexLock
:
boost
::
noncopyable
{
public
:
MutexLock
()
:
holder_
(
0
)
{
MCHECK
(
pthread_mutex_init
(
&
mutex_
,
NULL
));
}
~
MutexLock
()
{
assert
(
holder_
==
0
);
MCHECK
(
pthread_mutex_destroy
(
&
mutex_
));
}
// must be called when locked, i.e. for assertion
bool
isLockedByThisThread
()
const
{
return
holder_
==
CurrentThread
::
tid
();
}
void
assertLocked
()
const
{
assert
(
isLockedByThisThread
());
}
// internal usage
void
lock
()
{
MCHECK
(
pthread_mutex_lock
(
&
mutex_
));
assignHolder
();
}
void
unlock
()
{
unassignHolder
();
MCHECK
(
pthread_mutex_unlock
(
&
mutex_
));
}
pthread_mutex_t
*
getPthreadMutex
()
/* non-const */
{
return
&
mutex_
;
}
private
:
friend
class
Condition
;
class
UnassignGuard
:
boost
::
noncopyable
{
public
:
UnassignGuard
(
MutexLock
&
owner
)
:
owner_
(
owner
)
{
owner_
.
unassignHolder
();
}
~
UnassignGuard
()
{
owner_
.
assignHolder
();
}
private
:
MutexLock
&
owner_
;
};
void
unassignHolder
()
{
holder_
=
0
;
}
void
assignHolder
()
{
holder_
=
CurrentThread
::
tid
();
}
pthread_mutex_t
mutex_
;
pid_t
holder_
;
};
// Use as a stack variable, eg.
// int Foo::size() const
// {
// MutexLockGuard lock(mutex_);
// return data_.size();
// }
class
MutexLockGuard
:
boost
::
noncopyable
{
public
:
explicit
MutexLockGuard
(
MutexLock
&
mutex
)
:
mutex_
(
mutex
)
{
mutex_
.
lock
();
}
~
MutexLockGuard
()
{
mutex_
.
unlock
();
}
private
:
MutexLock
&
mutex_
;
};
}
// Prevent misuse like:
// MutexLockGuard(mutex_);
// A tempory object doesn't hold the lock for long!
#define MutexLockGuard(x) error "Missing guard object name"
#endif // MUDUO_BASE_MUTEX_H
test/test/include/muduo/base/Thread.cc
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#include <muduo/base/Thread.h>
#include <muduo/base/CurrentThread.h>
#include <muduo/base/Exception.h>
#include <muduo/base/Logging.h>
#include <boost/static_assert.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/weak_ptr.hpp>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/prctl.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <linux/unistd.h>
namespace
muduo
{
namespace
CurrentThread
{
__thread
int
t_cachedTid
=
0
;
__thread
char
t_tidString
[
32
];
__thread
int
t_tidStringLength
=
6
;
__thread
const
char
*
t_threadName
=
"unknown"
;
const
bool
sameType
=
boost
::
is_same
<
int
,
pid_t
>::
value
;
BOOST_STATIC_ASSERT
(
sameType
);
}
namespace
detail
{
pid_t
gettid
()
{
return
static_cast
<
pid_t
>
(
::
syscall
(
SYS_gettid
));
}
void
afterFork
()
{
muduo
::
CurrentThread
::
t_cachedTid
=
0
;
muduo
::
CurrentThread
::
t_threadName
=
"main"
;
CurrentThread
::
tid
();
// no need to call pthread_atfork(NULL, NULL, &afterFork);
}
class
ThreadNameInitializer
{
public
:
ThreadNameInitializer
()
{
muduo
::
CurrentThread
::
t_threadName
=
"main"
;
CurrentThread
::
tid
();
pthread_atfork
(
NULL
,
NULL
,
&
afterFork
);
}
};
ThreadNameInitializer
init
;
struct
ThreadData
{
typedef
muduo
::
Thread
::
ThreadFunc
ThreadFunc
;
ThreadFunc
func_
;
string
name_
;
boost
::
weak_ptr
<
pid_t
>
wkTid_
;
ThreadData
(
const
ThreadFunc
&
func
,
const
string
&
name
,
const
boost
::
shared_ptr
<
pid_t
>&
tid
)
:
func_
(
func
),
name_
(
name
),
wkTid_
(
tid
)
{
}
void
runInThread
()
{
pid_t
tid
=
muduo
::
CurrentThread
::
tid
();
boost
::
shared_ptr
<
pid_t
>
ptid
=
wkTid_
.
lock
();
if
(
ptid
)
{
*
ptid
=
tid
;
ptid
.
reset
();
}
muduo
::
CurrentThread
::
t_threadName
=
name_
.
empty
()
?
"muduoThread"
:
name_
.
c_str
();
::
prctl
(
PR_SET_NAME
,
muduo
::
CurrentThread
::
t_threadName
);
try
{
func_
();
muduo
::
CurrentThread
::
t_threadName
=
"finished"
;
}
catch
(
const
Exception
&
ex
)
{
muduo
::
CurrentThread
::
t_threadName
=
"crashed"
;
fprintf
(
stderr
,
"exception caught in Thread %s
\n
"
,
name_
.
c_str
());
fprintf
(
stderr
,
"reason: %s
\n
"
,
ex
.
what
());
fprintf
(
stderr
,
"stack trace: %s
\n
"
,
ex
.
stackTrace
());
abort
();
}
catch
(
const
std
::
exception
&
ex
)
{
muduo
::
CurrentThread
::
t_threadName
=
"crashed"
;
fprintf
(
stderr
,
"exception caught in Thread %s
\n
"
,
name_
.
c_str
());
fprintf
(
stderr
,
"reason: %s
\n
"
,
ex
.
what
());
abort
();
}
catch
(...)
{
muduo
::
CurrentThread
::
t_threadName
=
"crashed"
;
fprintf
(
stderr
,
"unknown exception caught in Thread %s
\n
"
,
name_
.
c_str
());
throw
;
// rethrow
}
}
};
void
*
startThread
(
void
*
obj
)
{
ThreadData
*
data
=
static_cast
<
ThreadData
*>
(
obj
);
data
->
runInThread
();
delete
data
;
return
NULL
;
}
}
}
using
namespace
muduo
;
void
CurrentThread
::
cacheTid
()
{
if
(
t_cachedTid
==
0
)
{
t_cachedTid
=
detail
::
gettid
();
t_tidStringLength
=
snprintf
(
t_tidString
,
sizeof
t_tidString
,
"%5d "
,
t_cachedTid
);
}
}
bool
CurrentThread
::
isMainThread
()
{
return
tid
()
==
::
getpid
();
}
void
CurrentThread
::
sleepUsec
(
int64_t
usec
)
{
struct
timespec
ts
=
{
0
,
0
};
ts
.
tv_sec
=
static_cast
<
time_t
>
(
usec
/
Timestamp
::
kMicroSecondsPerSecond
);
ts
.
tv_nsec
=
static_cast
<
long
>
(
usec
%
Timestamp
::
kMicroSecondsPerSecond
*
1000
);
::
nanosleep
(
&
ts
,
NULL
);
}
AtomicInt32
Thread
::
numCreated_
;
Thread
::
Thread
(
const
ThreadFunc
&
func
,
const
string
&
n
)
:
started_
(
false
),
joined_
(
false
),
pthreadId_
(
0
),
tid_
(
new
pid_t
(
0
)),
func_
(
func
),
name_
(
n
)
{
setDefaultName
();
}
#ifdef __GXX_EXPERIMENTAL_CXX0X__
Thread
::
Thread
(
ThreadFunc
&&
func
,
const
string
&
n
)
:
started_
(
false
),
joined_
(
false
),
pthreadId_
(
0
),
tid_
(
new
pid_t
(
0
)),
func_
(
std
::
move
(
func
)),
name_
(
n
)
{
setDefaultName
();
}
#endif
Thread
::~
Thread
()
{
if
(
started_
&&
!
joined_
)
{
pthread_detach
(
pthreadId_
);
}
}
void
Thread
::
setDefaultName
()
{
int
num
=
numCreated_
.
incrementAndGet
();
if
(
name_
.
empty
())
{
char
buf
[
32
];
snprintf
(
buf
,
sizeof
buf
,
"Thread%d"
,
num
);
name_
=
buf
;
}
}
void
Thread
::
start
()
{
assert
(
!
started_
);
started_
=
true
;
// FIXME: move(func_)
detail
::
ThreadData
*
data
=
new
detail
::
ThreadData
(
func_
,
name_
,
tid_
);
if
(
pthread_create
(
&
pthreadId_
,
NULL
,
&
detail
::
startThread
,
data
))
{
started_
=
false
;
delete
data
;
// or no delete?
LOG_SYSFATAL
<<
"Failed in pthread_create"
;
}
}
int
Thread
::
join
()
{
assert
(
started_
);
assert
(
!
joined_
);
joined_
=
true
;
return
pthread_join
(
pthreadId_
,
NULL
);
}
test/test/include/muduo/base/Thread.h
0 → 100644
View file @
b73967c5
// Use of this source code is governed by a BSD-style license
// that can be found in the License file.
//
// Author: Shuo Chen (chenshuo at chenshuo dot com)
#ifndef MUDUO_BASE_THREAD_H
#define MUDUO_BASE_THREAD_H
#include <muduo/base/Atomic.h>
#include <muduo/base/Types.h>
#include <boost/function.hpp>
#include <boost/noncopyable.hpp>
#include <boost/shared_ptr.hpp>
#include <pthread.h>
namespace
muduo
{
class
Thread
:
boost
::
noncopyable
{
public
:
typedef
boost
::
function
<
void
()
>
ThreadFunc
;
explicit
Thread
(
const
ThreadFunc
&
,
const
string
&
name
=
string
());
#ifdef __GXX_EXPERIMENTAL_CXX0X__
explicit
Thread
(
ThreadFunc
&&
,
const
string
&
name
=
string
());
#endif
~
Thread
();
void
start
();
int
join
();
// return pthread_join()
bool
started
()
const
{
return
started_
;
}
// pthread_t pthreadId() const { return pthreadId_; }
pid_t
tid
()
const
{
return
*
tid_
;
}
const
string
&
name
()
const
{
return
name_
;
}
static
int
numCreated
()
{
return
numCreated_
.
get
();
}
private
:
void
setDefaultName
();
bool
started_
;
bool
joined_
;
pthread_t
pthreadId_
;
boost
::
shared_ptr
<
pid_t
>
tid_
;
ThreadFunc
func_
;
string
name_
;
static
AtomicInt32
numCreated_
;
};
}
#endif
test/test/test.cpp
View file @
b73967c5
...
@@ -4,7 +4,7 @@
...
@@ -4,7 +4,7 @@
#include "stdafx.h"
#include "stdafx.h"
#include "../../safe_mem.h"
#include "../../safe_mem.h"
#include "../../utf8.h"
#include "../../utf8.h"
#include "../../Log.h"
int
main
()
int
main
()
{
{
...
...
test/test/test.vcxproj
View file @
b73967c5
...
@@ -88,6 +88,7 @@
...
@@ -88,6 +88,7 @@
<Optimization>
Disabled
</Optimization>
<Optimization>
Disabled
</Optimization>
<PreprocessorDefinitions>
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
<PreprocessorDefinitions>
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
<SDLCheck>
true
</SDLCheck>
<SDLCheck>
true
</SDLCheck>
<AdditionalIncludeDirectories>
$(ProjectDir)\include
</AdditionalIncludeDirectories>
</ClCompile>
</ClCompile>
<Link>
<Link>
<SubSystem>
Console
</SubSystem>
<SubSystem>
Console
</SubSystem>
...
@@ -145,10 +146,12 @@
...
@@ -145,10 +146,12 @@
<Text
Include=
"ReadMe.txt"
/>
<Text
Include=
"ReadMe.txt"
/>
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<ClInclude
Include=
"include\muduo\base\AsyncLogging.h"
/>
<ClInclude
Include=
"stdafx.h"
/>
<ClInclude
Include=
"stdafx.h"
/>
<ClInclude
Include=
"targetver.h"
/>
<ClInclude
Include=
"targetver.h"
/>
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<ClCompile
Include=
"include\muduo\base\AsyncLogging.cc"
/>
<ClCompile
Include=
"stdafx.cpp"
>
<ClCompile
Include=
"stdafx.cpp"
>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
Create
</PrecompiledHeader>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
Create
</PrecompiledHeader>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
Create
</PrecompiledHeader>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
Create
</PrecompiledHeader>
...
...
test/test/test.vcxproj.filters
View file @
b73967c5
...
@@ -13,6 +13,12 @@
...
@@ -13,6 +13,12 @@
<UniqueIdentifier>
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
</UniqueIdentifier>
<UniqueIdentifier>
{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}
</UniqueIdentifier>
<Extensions>
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
</Extensions>
<Extensions>
rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms
</Extensions>
</Filter>
</Filter>
<Filter
Include=
"muduo_log"
>
<UniqueIdentifier>
{272523ca-b560-4b07-8d73-c83acdf2426a}
</UniqueIdentifier>
</Filter>
<Filter
Include=
"muduo_log\base"
>
<UniqueIdentifier>
{eac7dde0-5fd4-4e88-be7d-7e92d6650537}
</UniqueIdentifier>
</Filter>
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<Text
Include=
"ReadMe.txt"
/>
<Text
Include=
"ReadMe.txt"
/>
...
@@ -24,6 +30,9 @@
...
@@ -24,6 +30,9 @@
<ClInclude
Include=
"targetver.h"
>
<ClInclude
Include=
"targetver.h"
>
<Filter>
Header Files
</Filter>
<Filter>
Header Files
</Filter>
</ClInclude>
</ClInclude>
<ClInclude
Include=
"include\muduo\base\AsyncLogging.h"
>
<Filter>
muduo_log\base
</Filter>
</ClInclude>
</ItemGroup>
</ItemGroup>
<ItemGroup>
<ItemGroup>
<ClCompile
Include=
"stdafx.cpp"
>
<ClCompile
Include=
"stdafx.cpp"
>
...
@@ -32,5 +41,8 @@
...
@@ -32,5 +41,8 @@
<ClCompile
Include=
"test.cpp"
>
<ClCompile
Include=
"test.cpp"
>
<Filter>
Source Files
</Filter>
<Filter>
Source Files
</Filter>
</ClCompile>
</ClCompile>
<ClCompile
Include=
"include\muduo\base\AsyncLogging.cc"
>
<Filter>
muduo_log\base
</Filter>
</ClCompile>
</ItemGroup>
</ItemGroup>
</Project>
</Project>
\ No newline at end of file
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