部屋から出る時は transactLeaveRoom が呼ばれ、 この関数の中からさらに doLeaveRoom が呼ばれる。カスタマイズは doLeaveRoom のオーバーライドで行う。
inline void RoomModule::transactLeaveRoom(SessionHandle& hSession)
{
Room* pRoom = hSession.domain()->room();
if (! pRoom) { return; }
pRoom->lock();
{
doLeaveRoom(pRoom, hSession);
}
pRoom->unlock();
}
退室は基本的にはフレームワークから呼ばれるが、アプリケーション主導で呼びたいケースもある。 このような場合には、transactLeaveRoom() を呼ぶ。
doLeaveRoom では、退室処理を実装する。
void SampleRoomModule::doLeaveRoom(Room* _pRoom, SessionHandle& _hSession)
{
SampleRoom* pRoom = static_cast< SampleRoom* >(_pRoom);
SessionHandle hSession(_hSession);
if (! pRoom->leave(hSession)) {
return;
}
{
LeaveRoomNotify* pRes = new LeaveRoomNotify();
pRes->domainIndex = hSession.domain()->index();
hSession.session()->queueMessage(pRes);
}
if (0 == pRoom->countMembers()) {
pRoom->close();
} else {
notifyRoom(pRoom);
}
}
実際に入室情報を更新するのは SampleRoom::leave で実装しているので、これを呼ぶ。
SampleRoom* pRoom = static_cast< SampleRoom* >(_pRoom);
SessionHandle hSession(_hSession);
if (! pRoom->leave(hSession)) {
return;
}
ここで、引数に与えられた SessionHandle は参照渡しになっているので、どこ由来のものか分からない。 もしかしたら、Room が内部で持っているものかもしれない。
Room が持っている SessionHandle は、当然ながら Room が自由に扱える。leave() 呼び出しで中身が変更されるかもしれない。そうなると、その SessionHandle はもう使えなくなる。
このようなケースを避けるため、引数の SessionHandle はそのまま使わずにコピーして使っている。
leave は退室処理を行う関数である。
bool SampleRoom::leave(const SessionHandle& hSession)
{
lock();
bool b = removeMember(hSession);
unlock();
return b;
}
単に removeMember() を呼んでいるだけである。
removeMember は、ベースクラス Room で実装されている関数で、部屋のメンバーから削除する。 また、DomainContext の部屋情報もクリアする。
退室処理を終えたら、LeaveRoomNotify を送信する。
{
LeaveRoomNotify* pRes = new LeaveRoomNotify();
pRes->domainIndex = hSession.domain()->index();
hSession.session()->queueMessage(pRes);
}
まだ部屋に人がいる場合、残っている人に RoomInfoNotify を投げる。
if (0 == pRoom->countMembers()) {
...
} else {
notifyRoom(pRoom);
}
このサンプルでは、部屋に人がいなくなったら閉室とする。 そのため、退室後に部屋の人数を確認し、ゼロ人ならば transactCloseRoom を呼ぶ。
if (0 == pRoom->countMembers()) {
transactCloseRoom();
}
transactCloseRoom については、閉室処理で詳しく説明する。