読者です 読者をやめる 読者になる 読者になる

Let's write β

趣味で書いたこととか、RustとLispが好き

Synergyのソースを読んだNo.1

 友人にSynergyを紹介していて、自分でも非常に便利なソフトだとおもったので、その仕組みを知る為にソースコードを読んでいました。読んだといっても核心の部分だけで、具体的にタイマーの処理だとかの部分は読んでいません。仕組みが知りたかっただけなので。



 まず、読み始めたのはcmd/synergys/synergys.cppのmainです。これはソースコード名からも解るようにsynergyのサーバーの処理のmainのようです。

result = run(argc, argv, NULL, &standardStartup);

という部分があり、runの中ではstarndardStartupを実行しているようです。そこで、standardStartupを追っていきます。すると、mainLoop()に処理が投げられている事が解ります。

else {
                return mainLoop();
}

ではmainLoop()の中を追ってきます。内部ではMutexなどを作ったり、 ディスプレイ名のCanonicalizeをしたりして、

EVENTQUEUE->getEvent(event);
while (event.getType() != CEvent::kQuit) {
                EVENTQUEUE->dispatchEvent(event);
                CEvent::deleteData(event);
                EVENTQUEUE->getEvent(event);
}

という部分にたどり着きます。見れば解るようにeventをdispatchしている部分のようです。dispatchEventを追ってみましょう。

CEventQueue::dispatchEvent(const CEvent& event)
{
        void* target   = event.getTarget();
        IEventJob* job = getHandler(event.getType(), target);
        if (job == NULL) {
                job = getHandler(CEvent::kUnknown, target);
        }
        if (job != NULL) {
                job->run(event);
                return true;
        }
        return false;
}

この様な処理です。getHandlerという物がevenのTypeに併せてハンドルを返し、それをrunしているようですね。
ではgetHandlerはどのように処理を見つけているのでしょう。

CEventQueue::getHandler(CEvent::Type type, void* target) const
{
        CArchMutexLock lock(m_mutex);
        CHandlerTable::const_iterator index = m_handlers.find(target);
        if (index != m_handlers.end()) {
                const CTypeHandlerTable& typeHandlers = index->second;
                CTypeHandlerTable::const_iterator index2 = typeHandlers.find(type);
                if (index2 != typeHandlers.end()) {
                        return index2->second;
                }
        }
        return NULL;
}

このような処理のようです。CHandlerTableに登録されている物をfindしているようですね。ではどの様な記述で登録しているのでしょうか?

CEventQueue::adoptHandler(CEvent::Type type, void* target, IEventJob* handler)
{
        CArchMutexLock lock(m_mutex);
        IEventJob*& job = m_handlers[target][type];
        delete job;
        job = handler;
}

名前から察するにこの辺りですね。見ると同じm_handlersというのが登場しています。



これでどのような部分をgrepすれば具体的にイベントの定義が行われているか解りました。では

grep 'EVENTQUEUE->adoptHandler' **/*.{c,h,cpp} | lv

して、どの様なイベントがあるか確認しましょう。



ちょっと長くなったので一旦この記事はここまでです。

僕が働いているAzit.incでは一緒に働けるエンジニアを募集しています!
採用情報 — 株式会社アジット|Azit Inc.