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
9 years ago
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
();
}
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
);
}
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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_
;
}
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
);
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
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
);
}
This diff is collapsed.
Click to expand it.
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
This diff is collapsed.
Click to expand it.
test/test/test.cpp
View file @
b73967c5
...
...
@@ -4,7 +4,7 @@
#include "stdafx.h"
#include "../../safe_mem.h"
#include "../../utf8.h"
#include "../../Log.h"
int
main
()
{
...
...
This diff is collapsed.
Click to expand it.
test/test/test.vcxproj
View file @
b73967c5
...
...
@@ -88,6 +88,7 @@
<Optimization>
Disabled
</Optimization>
<PreprocessorDefinitions>
WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)
</PreprocessorDefinitions>
<SDLCheck>
true
</SDLCheck>
<AdditionalIncludeDirectories>
$(ProjectDir)\include
</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>
Console
</SubSystem>
...
...
@@ -145,10 +146,12 @@
<Text
Include=
"ReadMe.txt"
/>
</ItemGroup>
<ItemGroup>
<ClInclude
Include=
"include\muduo\base\AsyncLogging.h"
/>
<ClInclude
Include=
"stdafx.h"
/>
<ClInclude
Include=
"targetver.h"
/>
</ItemGroup>
<ItemGroup>
<ClCompile
Include=
"include\muduo\base\AsyncLogging.cc"
/>
<ClCompile
Include=
"stdafx.cpp"
>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|Win32'"
>
Create
</PrecompiledHeader>
<PrecompiledHeader
Condition=
"'$(Configuration)|$(Platform)'=='Debug|x64'"
>
Create
</PrecompiledHeader>
...
...
This diff is collapsed.
Click to expand it.
test/test/test.vcxproj.filters
View file @
b73967c5
...
...
@@ -13,6 +13,12 @@
<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>
</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>
<Text
Include=
"ReadMe.txt"
/>
...
...
@@ -24,6 +30,9 @@
<ClInclude
Include=
"targetver.h"
>
<Filter>
Header Files
</Filter>
</ClInclude>
<ClInclude
Include=
"include\muduo\base\AsyncLogging.h"
>
<Filter>
muduo_log\base
</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile
Include=
"stdafx.cpp"
>
...
...
@@ -32,5 +41,8 @@
<ClCompile
Include=
"test.cpp"
>
<Filter>
Source Files
</Filter>
</ClCompile>
<ClCompile
Include=
"include\muduo\base\AsyncLogging.cc"
>
<Filter>
muduo_log\base
</Filter>
</ClCompile>
</ItemGroup>
</Project>
\ No newline at end of file
This diff is collapsed.
Click to expand it.
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