Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
BaiXuePrincess
Paddle
提交
71f9b9a3
P
Paddle
项目概览
BaiXuePrincess
/
Paddle
与 Fork 源项目一致
Fork自
PaddlePaddle / Paddle
通知
1
Star
1
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
P
Paddle
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
71f9b9a3
编写于
1月 08, 2019
作者:
M
minqiyang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Accelerate little models
test=release/1.2
上级
847cbdce
变更
7
隐藏空白更改
内联
并排
Showing
7 changed file
with
121 addition
and
114 deletion
+121
-114
paddle/fluid/framework/CMakeLists.txt
paddle/fluid/framework/CMakeLists.txt
+1
-1
paddle/fluid/framework/details/execution_strategy.h
paddle/fluid/framework/details/execution_strategy.h
+1
-1
paddle/fluid/framework/details/scope_buffered_ssa_graph_executor.cc
...id/framework/details/scope_buffered_ssa_graph_executor.cc
+12
-21
paddle/fluid/framework/details/scope_buffered_ssa_graph_executor.h
...uid/framework/details/scope_buffered_ssa_graph_executor.h
+24
-0
paddle/fluid/framework/rw_lock.h
paddle/fluid/framework/rw_lock.h
+35
-68
paddle/fluid/framework/scope.cc
paddle/fluid/framework/scope.cc
+31
-20
paddle/fluid/framework/scope.h
paddle/fluid/framework/scope.h
+17
-3
未找到文件。
paddle/fluid/framework/CMakeLists.txt
浏览文件 @
71f9b9a3
...
@@ -80,7 +80,7 @@ cc_test(variable_test SRCS variable_test.cc)
...
@@ -80,7 +80,7 @@ cc_test(variable_test SRCS variable_test.cc)
cc_library
(
threadpool SRCS threadpool.cc DEPS enforce
)
cc_library
(
threadpool SRCS threadpool.cc DEPS enforce
)
cc_test
(
threadpool_test SRCS threadpool_test.cc DEPS threadpool
)
cc_test
(
threadpool_test SRCS threadpool_test.cc DEPS threadpool
)
cc_library
(
scope SRCS scope.cc DEPS glog threadpool
)
cc_library
(
scope SRCS scope.cc DEPS glog threadpool
xxhash
)
cc_test
(
scope_test SRCS scope_test.cc DEPS scope
)
cc_test
(
scope_test SRCS scope_test.cc DEPS scope
)
cc_library
(
data_device_transform SRCS data_device_transform.cc DEPS tensor
)
cc_library
(
data_device_transform SRCS data_device_transform.cc DEPS tensor
)
...
...
paddle/fluid/framework/details/execution_strategy.h
浏览文件 @
71f9b9a3
...
@@ -25,7 +25,7 @@ struct ExecutionStrategy {
...
@@ -25,7 +25,7 @@ struct ExecutionStrategy {
size_t
num_threads_
{
0
};
size_t
num_threads_
{
0
};
bool
use_cuda_
{
true
};
bool
use_cuda_
{
true
};
bool
allow_op_delay_
{
false
};
bool
allow_op_delay_
{
false
};
size_t
num_iteration_per_drop_scope_
{
1
00
};
size_t
num_iteration_per_drop_scope_
{
1
};
ExecutorType
type_
{
kDefault
};
ExecutorType
type_
{
kDefault
};
bool
dry_run_
{
false
};
bool
dry_run_
{
false
};
};
};
...
...
paddle/fluid/framework/details/scope_buffered_ssa_graph_executor.cc
浏览文件 @
71f9b9a3
...
@@ -67,35 +67,26 @@ FeedFetchList ScopeBufferedSSAGraphExecutor::Run(
...
@@ -67,35 +67,26 @@ FeedFetchList ScopeBufferedSSAGraphExecutor::Run(
}
}
platform
::
RecordEvent
e
(
"ScopeBufferedSSAGraphExecutorAfterRun"
,
nullptr
);
platform
::
RecordEvent
e
(
"ScopeBufferedSSAGraphExecutorAfterRun"
,
nullptr
);
drop_scope_counter_
+=
1
;
++
drop_scope_counter_
;
#ifdef PADDLE_WITH_CUDA
bool
stream_end
=
false
;
const
std
::
string
gc_name
=
"garbage_collector"
;
if
(
!
fetch_tensors
.
empty
())
{
DeviceGarbageCollectorMap
*
gc
=
WaitComputationalStreams
();
Graph
().
Has
(
gc_name
)
?
&
(
Graph
().
Get
<
DeviceGarbageCollectorMap
>
(
gc_name
))
stream_end
=
true
;
:
nullptr
;
}
#endif
if
(
!
fetch_tensors
.
empty
()
||
if
(
drop_scope_counter_
==
strategy_
.
num_iteration_per_drop_scope_
)
{
drop_scope_counter_
==
strategy_
.
num_iteration_per_drop_scope_
)
{
if
(
!
stream_end
)
{
drop_scope_counter_
=
0
;
WaitComputationalStreams
();
// Wait All computational streams
for
(
auto
p
:
places_
)
{
platform
::
DeviceContextPool
::
Instance
().
Get
(
p
)
->
Wait
();
#ifdef PADDLE_WITH_CUDA
if
(
gc
!=
nullptr
&&
platform
::
is_gpu_place
(
p
))
{
auto
gpu_place
=
boost
::
get
<
platform
::
CUDAPlace
>
(
p
);
auto
&
gc_at_place
=
gc
->
at
(
gpu_place
.
device
);
gc_at_place
->
Wait
();
gc_at_place
->
Reset
();
}
#endif
}
}
for
(
auto
&
scope
:
local_scopes_
)
{
for
(
auto
&
scope
:
local_scopes_
)
{
auto
&
local_scope
=
auto
&
local_scope
=
*
scope
->
Var
(
details
::
kLocalExecScopeName
)
->
GetMutable
<
Scope
*>
();
*
scope
->
Var
(
details
::
kLocalExecScopeName
)
->
GetMutable
<
Scope
*>
();
scope
->
DeleteScope
(
local_scope
);
scope
->
DeleteScope
(
local_scope
);
}
}
drop_scope_counter_
=
0
;
}
}
if
(
eptr
)
{
if
(
eptr
)
{
std
::
rethrow_exception
(
eptr
);
std
::
rethrow_exception
(
eptr
);
...
...
paddle/fluid/framework/details/scope_buffered_ssa_graph_executor.h
浏览文件 @
71f9b9a3
...
@@ -47,6 +47,30 @@ class ScopeBufferedSSAGraphExecutor : public SSAGraphExecutor {
...
@@ -47,6 +47,30 @@ class ScopeBufferedSSAGraphExecutor : public SSAGraphExecutor {
FeedFetchList
Run
(
const
std
::
vector
<
std
::
string
>&
fetch_tensors
)
override
;
FeedFetchList
Run
(
const
std
::
vector
<
std
::
string
>&
fetch_tensors
)
override
;
private:
inline
void
WaitComputationalStreams
()
{
#ifdef PADDLE_WITH_CUDA
const
std
::
string
gc_name
=
"garbage_collector"
;
DeviceGarbageCollectorMap
*
gc
=
Graph
().
Has
(
gc_name
)
?
&
(
Graph
().
Get
<
DeviceGarbageCollectorMap
>
(
gc_name
))
:
nullptr
;
#endif
// Wait All computational streams
for
(
auto
p
:
places_
)
{
platform
::
DeviceContextPool
::
Instance
().
Get
(
p
)
->
Wait
();
#ifdef PADDLE_WITH_CUDA
if
(
gc
!=
nullptr
&&
platform
::
is_gpu_place
(
p
))
{
auto
gpu_place
=
boost
::
get
<
platform
::
CUDAPlace
>
(
p
);
auto
&
gc_at_place
=
gc
->
at
(
gpu_place
.
device
);
gc_at_place
->
Wait
();
gc_at_place
->
Reset
();
}
#endif
}
}
private:
private:
size_t
drop_scope_counter_
{
0
};
size_t
drop_scope_counter_
{
0
};
...
...
paddle/fluid/framework/rw_lock.h
浏览文件 @
71f9b9a3
...
@@ -16,7 +16,9 @@ limitations under the License. */
...
@@ -16,7 +16,9 @@ limitations under the License. */
#if !defined(_WIN32)
#if !defined(_WIN32)
#include <pthread.h>
#include <pthread.h>
#endif // !_WIN32
#else
#include <mutex> // NOLINT
#endif // !_WIN32
#include "paddle/fluid/platform/enforce.h"
#include "paddle/fluid/platform/enforce.h"
...
@@ -29,17 +31,17 @@ struct RWLock {
...
@@ -29,17 +31,17 @@ struct RWLock {
~
RWLock
()
{
pthread_rwlock_destroy
(
&
lock_
);
}
~
RWLock
()
{
pthread_rwlock_destroy
(
&
lock_
);
}
void
RDLock
()
{
inline
void
RDLock
()
{
PADDLE_ENFORCE_EQ
(
pthread_rwlock_rdlock
(
&
lock_
),
0
,
PADDLE_ENFORCE_EQ
(
pthread_rwlock_rdlock
(
&
lock_
),
0
,
"acquire read lock failed"
);
"acquire read lock failed"
);
}
}
void
WRLock
()
{
inline
void
WRLock
()
{
PADDLE_ENFORCE_EQ
(
pthread_rwlock_wrlock
(
&
lock_
),
0
,
PADDLE_ENFORCE_EQ
(
pthread_rwlock_wrlock
(
&
lock_
),
0
,
"acquire write lock failed"
);
"acquire write lock failed"
);
}
}
void
UNLock
()
{
inline
void
UNLock
()
{
PADDLE_ENFORCE_EQ
(
pthread_rwlock_unlock
(
&
lock_
),
0
,
"unlock failed"
);
PADDLE_ENFORCE_EQ
(
pthread_rwlock_unlock
(
&
lock_
),
0
,
"unlock failed"
);
}
}
...
@@ -51,81 +53,46 @@ struct RWLock {
...
@@ -51,81 +53,46 @@ struct RWLock {
// https://stackoverflow.com/questions/7125250/making-pthread-rwlock-wrlock-recursive
// https://stackoverflow.com/questions/7125250/making-pthread-rwlock-wrlock-recursive
// In windows, rw_lock seems like a hack. Use empty object and do nothing.
// In windows, rw_lock seems like a hack. Use empty object and do nothing.
struct
RWLock
{
struct
RWLock
{
void
RDLock
()
{}
// FIXME(minqiyang): use mutex here to do fake lock
void
WRLock
()
{}
inline
void
RDLock
()
{
mutex_
.
lock
();
}
void
UNLock
()
{}
inline
void
WRLock
()
{
mutex_
.
lock
();
}
inline
void
UNLock
()
{
mutex_
.
unlock
();
}
private:
std
::
mutex
mutex_
;
};
};
#endif
#endif
class
RWLockGuard
{
class
AutoWRLock
{
public:
public:
enum
Status
{
kUnLock
,
kWRLock
,
kRDLock
};
explicit
AutoWRLock
(
RWLock
*
rw_lock
)
:
lock_
(
rw_lock
)
{
Lock
();
}
RWLockGuard
(
RWLock
*
rw_lock
,
Status
init_status
)
:
lock_
(
rw_lock
),
status_
(
Status
::
kUnLock
)
{
switch
(
init_status
)
{
case
Status
::
kRDLock
:
{
RDLock
();
break
;
}
case
Status
::
kWRLock
:
{
WRLock
();
break
;
}
case
Status
::
kUnLock
:
{
break
;
}
}
}
void
WRLock
()
{
~
AutoWRLock
()
{
UnLock
();
}
switch
(
status_
)
{
case
Status
::
kUnLock
:
{
lock_
->
WRLock
();
status_
=
Status
::
kWRLock
;
break
;
}
case
Status
::
kWRLock
:
{
break
;
}
case
Status
::
kRDLock
:
{
PADDLE_THROW
(
"Please unlock read lock first before invoking write lock."
);
break
;
}
}
}
void
RDLock
()
{
private:
switch
(
status_
)
{
inline
void
Lock
()
{
lock_
->
WRLock
();
}
case
Status
::
kUnLock
:
{
lock_
->
RDLock
();
status_
=
Status
::
kRDLock
;
break
;
}
case
Status
::
kRDLock
:
{
break
;
}
case
Status
::
kWRLock
:
{
PADDLE_THROW
(
"Please unlock write lock first before invoking read lock."
);
break
;
}
}
}
void
UnLock
()
{
inline
void
UnLock
()
{
lock_
->
UNLock
();
}
if
(
status_
!=
Status
::
kUnLock
)
{
lock_
->
UNLock
();
private:
status_
=
Status
::
kUnLock
;
RWLock
*
lock_
;
}
};
}
class
AutoRDLock
{
public:
explicit
AutoRDLock
(
RWLock
*
rw_lock
)
:
lock_
(
rw_lock
)
{
Lock
();
}
~
AutoRDLock
()
{
UnLock
();
}
private:
inline
void
Lock
()
{
lock_
->
RDLock
();
}
~
RWLockGuard
()
{
Un
Lock
();
}
inline
void
UnLock
()
{
lock_
->
UN
Lock
();
}
private:
private:
RWLock
*
lock_
;
RWLock
*
lock_
;
Status
status_
;
};
};
}
// namespace framework
}
// namespace framework
...
...
paddle/fluid/framework/scope.cc
浏览文件 @
71f9b9a3
...
@@ -43,9 +43,15 @@ DEFINE_double(
...
@@ -43,9 +43,15 @@ DEFINE_double(
// the mutex will cause serious performance issue.
// the mutex will cause serious performance issue.
// So the mutex is disabled when `ON_INFER`.
// So the mutex is disabled when `ON_INFER`.
#ifdef PADDLE_ON_INFERENCE
#ifdef PADDLE_ON_INFERENCE
#define SCOPE_LOCK_GUARD
#define SCOPE_KIDS_READER_LOCK
#define SCOPE_KIDS_WRITER_LOCK
#define SCOPE_VARS_READER_LOCK
#define SCOPE_VARS_WRITER_LOCK
#else
#else
#define SCOPE_LOCK_GUARD std::lock_guard<std::mutex> lock(mutex_);
#define SCOPE_KIDS_READER_LOCK AutoRDLock auto_lock(&kids_lock_);
#define SCOPE_KIDS_WRITER_LOCK AutoWRLock auto_lock(&kids_lock_);
#define SCOPE_VARS_READER_LOCK AutoRDLock auto_lock(&vars_lock_);
#define SCOPE_VARS_WRITER_LOCK AutoWRLock auto_lock(&vars_lock_);
#endif
#endif
namespace
paddle
{
namespace
paddle
{
...
@@ -61,64 +67,69 @@ int64_t GetEagerDeletionThreshold() {
...
@@ -61,64 +67,69 @@ int64_t GetEagerDeletionThreshold() {
Scope
::~
Scope
()
{
DropKids
();
}
Scope
::~
Scope
()
{
DropKids
();
}
Scope
&
Scope
::
NewScope
()
const
{
Scope
&
Scope
::
NewScope
()
const
{
SCOPE_LOCK_GUARD
Scope
*
child
=
new
Scope
(
this
);
kids_
.
push_back
(
new
Scope
(
this
));
{
return
*
kids_
.
back
();
SCOPE_KIDS_WRITER_LOCK
kids_
.
push_back
(
child
);
}
return
*
child
;
}
}
Variable
*
Scope
::
Var
(
const
std
::
string
&
name
)
{
Variable
*
Scope
::
Var
(
const
std
::
string
&
name
)
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_WRITER_LOCK
return
VarInternal
(
name
);
return
VarInternal
(
name
);
}
}
Variable
*
Scope
::
Var
(
std
::
string
*
name
)
{
Variable
*
Scope
::
Var
(
std
::
string
*
name
)
{
SCOPE_LOCK_GUARD
auto
new_name
=
string
::
Sprintf
(
"%p.%d"
,
this
,
vars_
.
size
());
auto
new_name
=
string
::
Sprintf
(
"%p.%d"
,
this
,
vars_
.
size
());
if
(
name
!=
nullptr
)
{
if
(
name
!=
nullptr
)
{
*
name
=
new_name
;
*
name
=
new_name
;
}
}
SCOPE_VARS_WRITER_LOCK
return
VarInternal
(
new_name
);
return
VarInternal
(
new_name
);
}
}
Variable
*
Scope
::
FindVar
(
const
std
::
string
&
name
)
const
{
Variable
*
Scope
::
FindVar
(
const
std
::
string
&
name
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_READER_LOCK
return
FindVarInternal
(
name
);
return
FindVarInternal
(
name
);
}
}
Variable
*
Scope
::
FindLocalVar
(
const
std
::
string
&
name
)
const
{
Variable
*
Scope
::
FindLocalVar
(
const
std
::
string
&
name
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_READER_LOCK
return
FindVarLocally
(
name
);
return
FindVarLocally
(
name
);
}
}
const
Scope
*
Scope
::
FindScope
(
const
Variable
*
var
)
const
{
const
Scope
*
Scope
::
FindScope
(
const
Variable
*
var
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_READER_LOCK
return
FindScopeInternal
(
var
);
return
FindScopeInternal
(
var
);
}
}
void
Scope
::
DropKids
()
{
void
Scope
::
DropKids
()
{
SCOPE_
LOCK_GUARD
SCOPE_
KIDS_WRITER_LOCK
for
(
Scope
*
s
:
kids_
)
delete
s
;
for
(
Scope
*
s
:
kids_
)
delete
s
;
kids_
.
clear
();
kids_
.
clear
();
}
}
bool
Scope
::
HasKid
(
const
Scope
*
scope
)
const
{
bool
Scope
::
HasKid
(
const
Scope
*
scope
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
KIDS_READER_LOCK
auto
it
=
std
::
find
(
this
->
kids_
.
begin
(),
this
->
kids_
.
end
(),
scope
);
auto
it
=
std
::
find
(
this
->
kids_
.
begin
(),
this
->
kids_
.
end
(),
scope
);
return
it
!=
this
->
kids_
.
end
();
return
it
!=
this
->
kids_
.
end
();
}
}
std
::
vector
<
std
::
string
>
Scope
::
LocalVarNames
()
const
{
std
::
vector
<
std
::
string
>
Scope
::
LocalVarNames
()
const
{
SCOPE_LOCK_GUARD
std
::
vector
<
std
::
string
>
known_vars
;
std
::
vector
<
std
::
string
>
known_vars
;
known_vars
.
reserve
(
this
->
vars_
.
size
());
{
for
(
auto
&
p
:
vars_
)
{
SCOPE_VARS_READER_LOCK
known_vars
.
emplace_back
(
p
.
first
);
known_vars
.
reserve
(
this
->
vars_
.
size
());
for
(
auto
&
p
:
vars_
)
{
known_vars
.
emplace_back
(
p
.
first
);
}
}
}
return
known_vars
;
return
known_vars
;
}
}
void
Scope
::
DeleteScope
(
Scope
*
scope
)
const
{
void
Scope
::
DeleteScope
(
Scope
*
scope
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
KIDS_WRITER_LOCK
auto
it
=
std
::
find
(
this
->
kids_
.
begin
(),
this
->
kids_
.
end
(),
scope
);
auto
it
=
std
::
find
(
this
->
kids_
.
begin
(),
this
->
kids_
.
end
(),
scope
);
PADDLE_ENFORCE
(
it
!=
this
->
kids_
.
end
(),
"%p Cannot find %p as kid scope"
,
PADDLE_ENFORCE
(
it
!=
this
->
kids_
.
end
(),
"%p Cannot find %p as kid scope"
,
this
,
scope
);
this
,
scope
);
...
@@ -132,8 +143,8 @@ void Scope::DeleteScope(Scope* scope) const {
...
@@ -132,8 +143,8 @@ void Scope::DeleteScope(Scope* scope) const {
}
}
void
Scope
::
EraseVars
(
const
std
::
vector
<
std
::
string
>&
var_names
)
{
void
Scope
::
EraseVars
(
const
std
::
vector
<
std
::
string
>&
var_names
)
{
SCOPE_LOCK_GUARD
std
::
set
<
std
::
string
>
var_set
(
var_names
.
begin
(),
var_names
.
end
());
std
::
set
<
std
::
string
>
var_set
(
var_names
.
begin
(),
var_names
.
end
());
SCOPE_VARS_WRITER_LOCK
for
(
auto
it
=
vars_
.
begin
();
it
!=
vars_
.
end
();)
{
for
(
auto
it
=
vars_
.
begin
();
it
!=
vars_
.
end
();)
{
if
(
var_set
.
find
(
it
->
first
)
!=
var_set
.
end
())
{
if
(
var_set
.
find
(
it
->
first
)
!=
var_set
.
end
())
{
it
=
vars_
.
erase
(
it
);
it
=
vars_
.
erase
(
it
);
...
@@ -145,12 +156,12 @@ void Scope::EraseVars(const std::vector<std::string>& var_names) {
...
@@ -145,12 +156,12 @@ void Scope::EraseVars(const std::vector<std::string>& var_names) {
void
Scope
::
Rename
(
const
std
::
string
&
origin_name
,
void
Scope
::
Rename
(
const
std
::
string
&
origin_name
,
const
std
::
string
&
new_name
)
const
{
const
std
::
string
&
new_name
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_WRITER_LOCK
RenameInternal
(
origin_name
,
new_name
);
RenameInternal
(
origin_name
,
new_name
);
}
}
std
::
string
Scope
::
Rename
(
const
std
::
string
&
origin_name
)
const
{
std
::
string
Scope
::
Rename
(
const
std
::
string
&
origin_name
)
const
{
SCOPE_
LOCK_GUARD
SCOPE_
VARS_WRITER_LOCK
auto
new_name
=
string
::
Sprintf
(
"%p.%d"
,
this
,
vars_
.
size
());
auto
new_name
=
string
::
Sprintf
(
"%p.%d"
,
this
,
vars_
.
size
());
RenameInternal
(
origin_name
,
new_name
);
RenameInternal
(
origin_name
,
new_name
);
return
new_name
;
return
new_name
;
...
...
paddle/fluid/framework/scope.h
浏览文件 @
71f9b9a3
...
@@ -14,12 +14,18 @@ limitations under the License. */
...
@@ -14,12 +14,18 @@ limitations under the License. */
#pragma once
#pragma once
extern
"C"
{
#include <xxhash.h>
}
#include <list>
#include <list>
#include <m
utex> // NOLINT
#include <m
emory>
#include <string>
#include <string>
#include <unordered_map>
#include <unordered_map>
#include <utility>
#include <vector>
#include <vector>
#include "paddle/fluid/framework/rw_lock.h"
#include "paddle/fluid/framework/variable.h"
#include "paddle/fluid/framework/variable.h"
#include "paddle/fluid/platform/macros.h"
#include "paddle/fluid/platform/macros.h"
...
@@ -94,7 +100,14 @@ class Scope {
...
@@ -94,7 +100,14 @@ class Scope {
std
::
string
Rename
(
const
std
::
string
&
origin_name
)
const
;
std
::
string
Rename
(
const
std
::
string
&
origin_name
)
const
;
protected:
protected:
mutable
std
::
unordered_map
<
std
::
string
,
std
::
unique_ptr
<
Variable
>>
vars_
;
struct
KeyHasher
{
std
::
size_t
operator
()(
const
std
::
string
&
key
)
const
{
return
XXH32
(
key
.
c_str
(),
key
.
size
(),
1
);
}
};
mutable
std
::
unordered_map
<
std
::
string
,
std
::
unique_ptr
<
Variable
>
,
KeyHasher
>
vars_
;
private:
private:
// Call Scope::NewScope for a sub-scope.
// Call Scope::NewScope for a sub-scope.
...
@@ -123,7 +136,8 @@ class Scope {
...
@@ -123,7 +136,8 @@ class Scope {
DISABLE_COPY_AND_ASSIGN
(
Scope
);
DISABLE_COPY_AND_ASSIGN
(
Scope
);
private:
private:
mutable
std
::
mutex
mutex_
;
mutable
RWLock
kids_lock_
;
mutable
RWLock
vars_lock_
;
};
};
// Generate some debug string about the inherience structure of scope, quite
// Generate some debug string about the inherience structure of scope, quite
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录