はかせのラボ

私の頭の中を書いていく雑記ブログです

C++ タスクシステム⑨ ~能動的に動くSubject~

あいさつ

どうも、はかせです。
今回は前回予告した
「能動的に動くSubject」の実装をしていきます。

実装方法

基本は前回作ったSubjectです。
前回はmainで行っていたSubjectの操作を
クラス内に隠蔽することでmain側の操作なく
Subjectを動かします。

ではコードです。

class CountPerSecondSubject
{
public:
    CountPerSecondSubject() 
    {
        isEnd = false;
        mSubject = new Subject<int>();
	/*
	毎秒処理を行う
	*/
	mThread = std::thread ([&]() ->void
	{
	    auto count = 0;
	    while (true)
            {
                //1秒待機
		std::this_thread::sleep_for(std::chrono::seconds(1));
		//終了するか
		if (isEnd) 
		{
			std::cout << "カウント終了" << std::endl;
			break;
		}
		else
		{
			std::cout << "カウント" << std::endl;
		}
		//カウントアップして登録されている関数を呼び出す
		count++;
		mSubject->OnNext(count);
	    }
	});
    };
    /*
    関数登録
    */
    virtual void Subscribe
    (std::function<void(int value)> next) 
    {
        mSubject->Subscribe(next);
    }
    virtual void Subscribe
    (std::function<void(int value)> next, 
     std::function<void()> completed) 
    {
        mSubject->Subscribe(next, completed);
    }
    virtual void Subscribe
    (std::function<void(int value)> next, 
     std::function<void()> completed,
     std::function<void()> error) 
    {
        mSubject->Subscribe(next, completed, error);
    }
    /*
    終了処理
    */
    void Dispose()
    {
        isEnd = true;
        mThread.join();
        mSubject->OnCompleted();	
        delete this;
    }
private:
    Subject<int>* mSubject;
    std::thread mThread;
    bool isEnd;
    ~CountPerSecondSubject() 
    {
        std::cout << "Delete Count" << std::endl;
    };
};

今回は1秒ごとにカウントアップして
その値を通知します。

この処理は別スレッドで行っています。
理由は別の処理を行いながら
(入力を受けたり、処理を新しく追加したり)
カウントアップと通知を行いたいからです。

使い方です。

int main(int argc, char const* argv[])
{
#if _DEBUG
    _CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
#endif
    //1秒ごとにカウント結果を通知
    auto count = new CountPerSecondSubject();
    //通知された値を表示
    count->Subscribe
    (
	[&](int value) ->void {std::cout << "Count表示:" << value << std::endl; },
	[&]() -> void {std::cout << "OnCompleted1!" << std::endl; }
    );
    getchar();
    std::cout << "関数追加" << std::endl;
    //通知された値を倍にして表示
    count->Subscribe
    (
	[&](int value) ->void {std::cout << "Countを倍にして表示:" << value * 2<< std::endl; },
	[&]() -> void {std::cout << "OnCompleted2!" << std::endl; }
    );
    getchar();
    //countの終了処理
    count->Dispose();
	
    getchar();
}

インスタンスを生成し処理を登録、
キー入力を受けて処理を追加登録しています。
2回目の入力で処理を終了させています。
実行結果です。
f:id:hakase0274:20181227212519p:plain
前回みたくmain側で通知をしなくても
結果が表示されました。

あとがき

今回は能動的に動くSubjectの実装でした。
処理を登録すれば勝手に動いてくれるので、
勝手にやってくれるorやってほしい処理とかに使えると思います。
(タイマーとか、値が変わったらとか)

それでは今回はこの辺でノシ