Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
U
uniset2
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
1
Issues
1
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
UniSet project repositories
uniset2
Commits
705d6b82
Commit
705d6b82
authored
Jan 27, 2014
by
Pavel Vainerman
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Перешёл где можно от mutex к atomic.
parent
c377d11b
Show whitespace changes
Inline
Side-by-side
Showing
23 changed files
with
60 additions
and
68 deletions
+60
-68
ctl-cpp-common.xsl
Utilities/codegen/ctl-cpp-common.xsl
+7
-7
Makefile.am
Utilities/codegen/tests/Makefile.am
+4
-4
IOControl.cc
extensions/IOControl/IOControl.cc
+3
-3
IOControl.h
extensions/IOControl/IOControl.h
+1
-1
MBExchange.cc
extensions/ModbusMaster/MBExchange.cc
+5
-7
MBExchange.h
extensions/ModbusMaster/MBExchange.h
+1
-2
MBSlave.cc
extensions/ModbusSlave/MBSlave.cc
+5
-5
MBSlave.h
extensions/ModbusSlave/MBSlave.h
+1
-1
UNetExchange.cc
extensions/UNetUDP/UNetExchange.cc
+4
-4
UNetExchange.h
extensions/UNetUDP/UNetExchange.h
+1
-1
UNetReceiver.cc
extensions/UNetUDP/UNetReceiver.cc
+3
-6
UNetReceiver.h
extensions/UNetUDP/UNetReceiver.h
+1
-1
UNetSender.cc
extensions/UNetUDP/UNetSender.cc
+3
-3
UNetSender.h
extensions/UNetUDP/UNetSender.h
+1
-1
UObject_SK.h
extensions/include/UObject_SK.h
+2
-2
UObject_SK.cc
extensions/lib/UObject_SK.cc
+6
-6
Makefile.am
extensions/tests/SMemoryTest/Makefile.am
+2
-2
Mutex.h
include/Mutex.h
+3
-3
PassiveTimer.h
include/PassiveTimer.h
+0
-0
ModbusRTUMaster.cc
src/Communications/Modbus/ModbusRTUMaster.cc
+0
-0
ModbusTCPMaster.cc
src/Communications/Modbus/ModbusTCPMaster.cc
+0
-0
UniSetTypes.cc
src/ObjectRepository/UniSetTypes.cc
+0
-1
Mutex.cc
src/Various/Mutex.cc
+7
-8
No files found.
Utilities/codegen/ctl-cpp-common.xsl
View file @
705d6b82
...
...
@@ -234,7 +234,7 @@
inline const std::string getProp(const std::string
&
name) { return UniSetTypes::conf->getProp(confnode, name); }
int smReadyTimeout; /*!
<
время ожидания готовности SM */
bool
activated;
UniSetTypes::mutex_atomic_t
activated;
int activateTimeout; /*!
<
время ожидания готовности UniSetObject к работе */
PassiveTimer ptStartUpTimeout; /*!
<
время на блокировку обработки WatchDog, если недавно был StartUp */
int askPause; /*!
<
пауза между неудачными попытками заказать датчики */
...
...
@@ -350,10 +350,10 @@ bool <xsl:value-of select="$CLASSNAME"/>_SK::activateObject()
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated =
false
;
activated =
0
;
<xsl:if
test=
"normalize-space($BASECLASS)!=''"
><xsl:value-of
select=
"normalize-space($BASECLASS)"
/>
::activateObject();
</xsl:if>
<xsl:if
test=
"normalize-space($BASECLASS)=''"
>
UniSetObject::activateObject();
</xsl:if>
activated =
true
;
activated =
1
;
}
return true;
...
...
@@ -522,7 +522,7 @@ idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
smReadyTimeout(0),
activated(
false
),
activated(
0
),
askPause(2000),
<xsl:for-each
select=
"//variables/item"
>
<xsl:if
test=
"normalize-space(@private)!=''"
>
...
...
@@ -586,7 +586,7 @@ idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
smReadyTimeout(0),
activated(
false
),
activated(
0
),
askPause(conf->getPIntProp(cnode,"askPause",2000)),
<xsl:for-each
select=
"//variables/item"
>
<xsl:if
test=
"normalize-space(@private)!=''"
>
...
...
@@ -872,7 +872,7 @@ idLocalTestMode_S(DefaultObjectId),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(0),
activated(
false
),
activated(
0
),
askPause(2000)
{
ucrit
<<
"
<xsl:value-of
select=
"$CLASSNAME"
/>
: init failed!!!!!!!!!!!!!!!"
<<
endl;
...
...
@@ -906,7 +906,7 @@ in_LocalTestMode_S(false),
idHeartBeat(DefaultObjectId),
maxHeartBeat(10),
confnode(cnode),
activated(
false
),
activated(
0
),
askPause(conf->getPIntProp(cnode,"askPause",2000))
{
if( getId() == DefaultObjectId )
...
...
Utilities/codegen/tests/Makefile.am
View file @
705d6b82
noinst_PROGRAMS
=
test
test2
#test2
test_LDADD
=
$(top_builddir)
/lib/libUniSet.la
test_CXXFLAGS
=
-I
$(top_builddir)
/include
test_LDADD
=
$(top_builddir)
/lib/libUniSet.la
$(COMCPP_LIBS)
test_CXXFLAGS
=
-I
$(top_builddir)
/include
$(COMCPP_CGLAGS)
test_SOURCES
=
TestGen_SK.cc TestGen.cc TestGen-main.cc
test2_LDADD
=
$(top_builddir)
/lib/libUniSet.la
test2_CXXFLAGS
=
-I
$(top_builddir)
/include
test2_LDADD
=
$(top_builddir)
/lib/libUniSet.la
$(COMCPP_LIBS)
test2_CXXFLAGS
=
-I
$(top_builddir)
/include
$(COMCPP_CGLAGS)
test2_SOURCES
=
TestGenAlone_SK.cc TestGenAlone.cc TestGenAlone-main.cc
GENERATED
=
TestGen_SK.h TestGen_SK.cc TestGen-main.cc
...
...
extensions/IOControl/IOControl.cc
View file @
705d6b82
...
...
@@ -43,7 +43,7 @@ IOControl::IOControl( UniSetTypes::ObjectId id, UniSetTypes::ObjectId icID,
force
(
false
),
force_out
(
false
),
maxCardNum
(
10
),
activated
(
false
),
activated
(
0
),
readconf_ok
(
false
),
term
(
false
),
testMode_as
(
UniSetTypes
::
DefaultObjectId
),
...
...
@@ -783,9 +783,9 @@ bool IOControl::activateObject()
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated
=
false
;
activated
=
0
;
UniSetObject
::
activateObject
();
activated
=
true
;
activated
=
1
;
}
return
true
;
...
...
extensions/IOControl/IOControl.h
View file @
705d6b82
...
...
@@ -370,7 +370,7 @@ class IOControl:
int
maxCardNum
;
/*! максимально разрешённый номер для карты */
UniSetTypes
::
uniset_mutex
iopollMutex
;
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
bool
readconf_ok
;
int
activateTimeout
;
UniSetTypes
::
ObjectId
sidTestSMReady
;
...
...
extensions/ModbusMaster/MBExchange.cc
View file @
705d6b82
...
...
@@ -22,7 +22,7 @@ force_out(false),
mbregFromID
(
false
),
sidExchangeMode
(
DefaultObjectId
),
exchangeMode
(
emNone
),
activated
(
false
),
activated
(
0
),
noQueryOptimization
(
false
),
no_extimer
(
false
),
prefix
(
prefix
),
...
...
@@ -221,14 +221,12 @@ void MBExchange::step()
// -----------------------------------------------------------------------------
bool
MBExchange
::
checkProcActive
()
{
uniset_rwmutex_rlock
l
(
actMutex
);
return
activated
;
}
// -----------------------------------------------------------------------------
void
MBExchange
::
setProcActive
(
bool
st
)
{
uniset_rwmutex_wrlock
l
(
actMutex
);
activated
=
st
;
activated
=
(
st
?
1
:
0
);
}
// -----------------------------------------------------------------------------
void
MBExchange
::
sigterm
(
int
signo
)
...
...
@@ -2406,15 +2404,15 @@ void MBExchange::sysCommand( const UniSetTypes::SystemMessage *sm )
// см. activateObject()
msleep
(
initPause
);
PassiveTimer
ptAct
(
activateTimeout
);
while
(
!
activated
&&
!
ptAct
.
checkTime
()
)
while
(
!
checkProcActive
()
&&
!
ptAct
.
checkTime
()
)
{
cout
<<
myname
<<
"(sysCommand): wait activate..."
<<
endl
;
msleep
(
300
);
if
(
activated
)
if
(
checkProcActive
()
)
break
;
}
if
(
!
activated
)
if
(
!
checkProcActive
()
)
dcrit
<<
myname
<<
"(sysCommand): ************* don`t activate?! ************"
<<
endl
;
{
UniSetTypes
::
uniset_rwmutex_rlock
l
(
mutex_start
);
...
...
extensions/ModbusMaster/MBExchange.h
View file @
705d6b82
...
...
@@ -298,8 +298,7 @@ class MBExchange:
IOController
::
IOStateList
::
iterator
itExchangeMode
;
long
exchangeMode
;
/*!< режим работы см. ExchangeMode */
UniSetTypes
::
uniset_rwmutex
actMutex
;
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
int
activateTimeout
;
bool
noQueryOptimization
;
bool
no_extimer
;
...
...
extensions/ModbusSlave/MBSlave.cc
View file @
705d6b82
...
...
@@ -22,7 +22,7 @@ askcount_id(DefaultObjectId),
respond_id
(
DefaultObjectId
),
respond_invert
(
false
),
askCount
(
0
),
activated
(
false
),
activated
(
0
),
activateTimeout
(
500
),
pingOK
(
true
),
force
(
false
),
...
...
@@ -699,11 +699,11 @@ bool MBSlave::activateObject()
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated
=
false
;
activated
=
0
;
UniSetTypes
::
uniset_rwmutex_wrlock
l
(
mutex_start
);
UniSetObject_LT
::
activateObject
();
initIterators
();
activated
=
true
;
activated
=
1
;
}
return
true
;
...
...
@@ -711,8 +711,8 @@ bool MBSlave::activateObject()
// ------------------------------------------------------------------------------------------
void
MBSlave
::
sigterm
(
int
signo
)
{
cerr
<<
myname
<<
": ********* SIGTERM("
<<
signo
<<
") ********"
<<
endl
;
activated
=
false
;
dinfo
<<
myname
<<
": ********* SIGTERM("
<<
signo
<<
") ********"
<<
endl
;
activated
=
0
;
try
{
if
(
mbslot
)
...
...
extensions/ModbusSlave/MBSlave.h
View file @
705d6b82
...
...
@@ -189,7 +189,7 @@ class MBSlave:
typedef
std
::
map
<
ModbusRTU
::
mbErrCode
,
unsigned
int
>
ExchangeErrorMap
;
ExchangeErrorMap
errmap
;
/*!< статистика обмена */
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
int
activateTimeout
;
bool
pingOK
;
timeout_t
wait_msec
;
...
...
extensions/UNetUDP/UNetExchange.cc
View file @
705d6b82
...
...
@@ -11,7 +11,7 @@ UNetExchange::UNetExchange( UniSetTypes::ObjectId objId, UniSetTypes::ObjectId s
UniSetObject_LT
(
objId
),
shm
(
0
),
initPause
(
0
),
activated
(
false
),
activated
(
0
),
no_sender
(
false
),
sender
(
0
),
sender2
(
0
)
...
...
@@ -576,11 +576,11 @@ bool UNetExchange::activateObject()
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated
=
false
;
activated
=
0
;
UniSetTypes
::
uniset_rwmutex_wrlock
l
(
mutex_start
);
UniSetObject_LT
::
activateObject
();
initIterators
();
activated
=
true
;
activated
=
1
;
}
return
true
;
...
...
@@ -589,7 +589,7 @@ bool UNetExchange::activateObject()
void
UNetExchange
::
sigterm
(
int
signo
)
{
dinfo
<<
myname
<<
": ********* SIGTERM("
<<
signo
<<
") ********"
<<
endl
;
activated
=
false
;
activated
=
0
;
for
(
ReceiverList
::
iterator
it
=
recvlist
.
begin
();
it
!=
recvlist
.
end
();
++
it
)
{
try
...
...
extensions/UNetUDP/UNetExchange.h
View file @
705d6b82
...
...
@@ -134,7 +134,7 @@ class UNetExchange:
int
steptime
;
/*!< периодичность вызова step, [мсек] */
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
int
activateTimeout
;
struct
ReceiverInfo
...
...
extensions/UNetUDP/UNetReceiver.cc
View file @
705d6b82
...
...
@@ -31,7 +31,7 @@ lostPackets(0),
sidRespond
(
UniSetTypes
::
DefaultObjectId
),
respondInvert
(
false
),
sidLostPackets
(
UniSetTypes
::
DefaultObjectId
),
activated
(
false
),
activated
(
0
),
r_thr
(
0
),
u_thr
(
0
),
pnum
(
0
),
...
...
@@ -160,7 +160,7 @@ void UNetReceiver::start()
{
if
(
!
activated
)
{
activated
=
true
;
activated
=
1
;
u_thr
->
start
();
r_thr
->
start
();
}
...
...
@@ -348,10 +348,7 @@ void UNetReceiver::real_update()
// -----------------------------------------------------------------------------
void
UNetReceiver
::
stop
()
{
activated
=
false
;
// msleep(10);
// u_thr->stop();
// r_thr->stop();
activated
=
0
;
}
// -----------------------------------------------------------------------------
void
UNetReceiver
::
receive
()
...
...
extensions/UNetUDP/UNetReceiver.h
View file @
705d6b82
...
...
@@ -130,7 +130,7 @@ class UNetReceiver
UniSetTypes
::
ObjectId
sidLostPackets
;
IOController
::
IOStateList
::
iterator
itLostPackets
;
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
ThreadCreator
<
UNetReceiver
>*
r_thr
;
// receive thread
ThreadCreator
<
UNetReceiver
>*
u_thr
;
// update thread
...
...
extensions/UNetUDP/UNetSender.cc
View file @
705d6b82
...
...
@@ -15,7 +15,7 @@ s_fvalue(s_val),
shm
(
smi
),
s_host
(
s_host
),
sendpause
(
150
),
activated
(
false
),
activated
(
0
),
dlist
(
100
),
maxItem
(
0
),
packetnum
(
1
),
...
...
@@ -195,7 +195,7 @@ void UNetSender::real_send()
// -----------------------------------------------------------------------------
void
UNetSender
::
stop
()
{
activated
=
false
;
activated
=
0
;
// s_thr->stop();
}
// -----------------------------------------------------------------------------
...
...
@@ -203,7 +203,7 @@ void UNetSender::start()
{
if
(
!
activated
)
{
activated
=
true
;
activated
=
1
;
s_thr
->
start
();
}
}
...
...
extensions/UNetUDP/UNetSender.h
View file @
705d6b82
...
...
@@ -86,7 +86,7 @@ class UNetSender
std
::
string
myname
;
int
sendpause
;
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
UniSetTypes
::
uniset_rwmutex
pack_mutex
;
UniSetUDP
::
UDPMessage
mypack
;
...
...
extensions/include/UObject_SK.h
View file @
705d6b82
...
...
@@ -8,7 +8,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2014-01-2
4
+04:00
// generate timestamp: 2014-01-2
7
+04:00
// -----------------------------------------------------------------------------
#ifndef UObject_SK_H_
#define UObject_SK_H_
...
...
@@ -119,7 +119,7 @@ class UObject_SK:
inline
const
std
::
string
getProp
(
const
std
::
string
&
name
)
{
return
UniSetTypes
::
conf
->
getProp
(
confnode
,
name
);
}
int
smReadyTimeout
;
/*!< время ожидания готовности SM */
bool
activated
;
UniSetTypes
::
mutex_atomic_t
activated
;
int
activateTimeout
;
/*!< время ожидания готовности UniSetObject к работе */
PassiveTimer
ptStartUpTimeout
;
/*!< время на блокировку обработки WatchDog, если недавно был StartUp */
int
askPause
;
/*!< пауза между неудачными попытками заказать датчики */
...
...
extensions/lib/UObject_SK.cc
View file @
705d6b82
...
...
@@ -11,7 +11,7 @@
ВСЕ ВАШИ ИЗМЕНЕНИЯ БУДУТ ПОТЕРЯНЫ.
*/
// --------------------------------------------------------------------------
// generate timestamp: 2014-01-2
4
+04:00
// generate timestamp: 2014-01-2
7
+04:00
// -----------------------------------------------------------------------------
#include "Configuration.h"
#include "Exceptions.h"
...
...
@@ -38,7 +38,7 @@ idHeartBeat(DefaultObjectId),
maxHeartBeat
(
10
),
confnode
(
0
),
smReadyTimeout
(
0
),
activated
(
false
),
activated
(
0
),
askPause
(
2000
),
end_private
(
false
)
...
...
@@ -73,7 +73,7 @@ idHeartBeat(DefaultObjectId),
maxHeartBeat
(
10
),
confnode
(
cnode
),
smReadyTimeout
(
0
),
activated
(
false
),
activated
(
0
),
askPause
(
conf
->
getPIntProp
(
cnode
,
"askPause"
,
2000
)),
end_private
(
false
)
...
...
@@ -297,9 +297,9 @@ bool UObject_SK::activateObject()
// пока не пройдёт инициализация датчиков
// см. sysCommand()
{
activated
=
false
;
activated
=
0
;
UniSetObject
::
activateObject
();
activated
=
true
;
activated
=
1
;
}
return
true
;
...
...
@@ -360,7 +360,7 @@ void UObject_SK::callback()
}
// обработка сообщений (таймеров и т.п.)
for
(
int
i
=
0
;
i
<
20
;
i
++
)
for
(
unsigned
int
i
=
0
;
i
<
20
;
i
++
)
{
if
(
!
receiveMessage
(
msg
)
)
break
;
...
...
extensions/tests/SMemoryTest/Makefile.am
View file @
705d6b82
...
...
@@ -2,11 +2,11 @@ noinst_PROGRAMS = smemory-test
smemory_test_LDADD
=
$(top_builddir)
/lib/libUniSet.la
\
$(top_builddir)
/extensions/lib/libUniSetExtensions.la
\
$(top_builddir)
/extensions/SharedMemory/libUniSetSharedMemory.la
\
$(SIGC_LIBS)
$(SIGC_LIBS)
$(COMCPP_LIBS)
smemory_test_CPPFLAGS
=
-I
$(top_builddir)
/include
\
-I
$(top_builddir)
/extensions/include
\
-I
$(top_builddir)
/extensions/SharedMemory
\
$(SIGC_CFLAGS)
$(SIGC_CFLAGS)
$(COMCPP_CFLAGS)
smemory_test_SOURCES
=
TestProc_SK.cc TestProc.cc smemory-test.cc
TestProc_SK.cc
:
testproc.src.xml
...
...
include/Mutex.h
View file @
705d6b82
...
...
@@ -43,7 +43,7 @@ namespace UniSetTypes
{
public
:
uniset_mutex
();
uniset_mutex
(
std
::
string
name
);
uniset_mutex
(
const
std
::
string
&
name
);
~
uniset_mutex
();
bool
isRelease
();
...
...
@@ -110,7 +110,7 @@ namespace UniSetTypes
bool
tryrlock
();
bool
trywrlock
();
uniset_rwmutex
(
const
uniset_rwmutex
&
r
);
uniset_rwmutex
(
const
uniset_rwmutex
&
r
);
const
uniset_rwmutex
&
operator
=
(
const
uniset_rwmutex
&
r
);
inline
std
::
string
name
(){
return
nm
;
}
...
...
@@ -121,7 +121,7 @@ namespace UniSetTypes
friend
class
uniset_rwmutex_lock
;
ost
::
ThreadLock
m
;
ost
::
AtomicCounter
wr_wait
;
static
int
num
;
static
ost
::
AtomicCounter
num
;
};
std
::
ostream
&
operator
<<
(
std
::
ostream
&
os
,
uniset_rwmutex
&
m
);
...
...
include/PassiveTimer.h
View file @
705d6b82
src/Communications/Modbus/ModbusRTUMaster.cc
View file @
705d6b82
src/Communications/Modbus/ModbusTCPMaster.cc
View file @
705d6b82
src/ObjectRepository/UniSetTypes.cc
View file @
705d6b82
...
...
@@ -124,7 +124,6 @@ using namespace UniSetTypes;
lst
.
push_back
(
id
);
}
void
UniSetTypes
::
IDList
::
del
(
ObjectId
id
)
{
for
(
list
<
ObjectId
>::
iterator
it
=
lst
.
begin
();
it
!=
lst
.
end
();
++
it
)
...
...
src/Various/Mutex.cc
View file @
705d6b82
...
...
@@ -41,7 +41,7 @@ uniset_mutex::uniset_mutex():
cnd
=
new
omni_condition
(
&
mtx
);
}
// -----------------------------------------------------------------------------
uniset_mutex
::
uniset_mutex
(
string
name
)
:
uniset_mutex
::
uniset_mutex
(
const
string
&
name
)
:
cnd
(
0
),
nm
(
name
),
locked
(
0
)
...
...
@@ -63,7 +63,6 @@ void uniset_mutex::lock()
{
sem
.
wait
();
locked
=
1
;
MUTEX_DEBUG
(
cerr
<<
nm
<<
" Locked.."
<<
endl
;)
}
// -----------------------------------------------------------------------------
...
...
@@ -154,7 +153,7 @@ wr_wait(0)
}
int
uniset_rwmutex
::
num
=
0
;
ost
::
AtomicCounter
uniset_rwmutex
::
num
=
0
;
uniset_rwmutex
::
uniset_rwmutex
()
:
nm
(
""
),
...
...
@@ -193,24 +192,24 @@ nm(r.nm)
void
uniset_rwmutex
::
lock
()
{
MUTEX_DEBUG
(
cerr
<<
nm
<<
" prepare Locked.."
<<
endl
;)
wr_wait
+=
1
;
wr_wait
+=
1
;
m
.
writeLock
();
wr_wait
-=
1
;
wr_wait
-=
1
;
MUTEX_DEBUG
(
cerr
<<
nm
<<
" Locked.."
<<
endl
;)
}
void
uniset_rwmutex
::
wrlock
()
{
MUTEX_DEBUG
(
cerr
<<
nm
<<
" prepare WRLocked.."
<<
endl
;)
wr_wait
+=
1
;
wr_wait
+=
1
;
m
.
writeLock
();
wr_wait
-=
1
;
wr_wait
-=
1
;
MUTEX_DEBUG
(
cerr
<<
nm
<<
" WRLocked.."
<<
endl
;)
}
void
uniset_rwmutex
::
rlock
()
{
MUTEX_DEBUG
(
cerr
<<
nm
<<
" prepare RLocked.."
<<
endl
;)
while
(
wr_wait
>
0
)
while
(
wr_wait
)
msleep
(
2
);
m
.
readLock
();
...
...
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