rxqt icon indicating copy to clipboard operation
rxqt copied to clipboard

Using the rxqt::run_loop in a large code base

Open michalfapso opened this issue 4 years ago • 1 comments

Hi Tetsuro. Thanks for this library.

What is the preferred way to use the rxqt::run_loop in a larger codebase with a lot of classes?

As all qt gui related methods have to be run in the main (gui) thread, in all such cases, I need to add .observe_on(main_thread) before each .subscribe(...). I saw your example https://github.com/tetsurom/rxqt/blob/master/sample/thread/main.cpp, but when the code is spread among multiple source files, these options come to my mind:

  1. Encapsulate the rxqt::run_loop in a singleton and initialize it after QApplication
  2. Create the rxqt::run_loop after QApplication, and then put just the result of rxqt_run_loop.observe_on_run_loop() into a singleton.
  3. Before each place where I'd like to use .observe_on(main_thread), I'd put
    rxqt::run_loop rxqt_run_loop;
    auto main_thread = rxqt_run_loop.observe_on_run_loop();
    

Are these approaches equivalent in functionality? The 2. option would lead to the least code bloat. What would you prefer?

Thanks for any hints. Michal

michalfapso avatar Feb 23 '21 16:02 michalfapso

The singleton approach could look like this:

foo.cpp where we need to subscribe on the gui thread:

#include "rxqt_gui_thread.h"
#include <cassert>
...
some_request
.observe_on(RxqtGuiThread::GetInstance().Get()) // <-- This is the important part
.subscribe([](auto){
	assert(qApp->thread() == QThread::currentThread());
});
...

main.cpp:

int main(int argc, char** argv)
{
	QApplication app(argc, argv);
	RxqtGuiThread::GetInstance(); // Initialization must happen in the gui thread
	...
}

rxqt_gui_thread.h:

#ifndef RXQTGUITHREAD_H
#define RXQTGUITHREAD_H

#include "singleton.h"
#include "rxcpp/rx.hpp"
#include "rxqt.hpp"
#include <QCoreApplication>
#include <cassert>

namespace detail {
class RxqtGuiThread
{
	public:
		RxqtGuiThread()
			: mLoop()
			, mWorker(mLoop.observe_on_run_loop())
		{
			assert(qApp->thread() == QThread::currentThread());
		}

		rxcpp::observe_on_one_worker Get() const { return mWorker; }
	private:
		rxqt::run_loop mLoop;
		rxcpp::observe_on_one_worker mWorker;
};
}

typedef Singleton<detail::RxqtGuiThread> RxqtGuiThread;

#endif // RXQTGUITHREAD_H

singleton.h (just for completeness):

#ifndef SINGLETON_H
#define SINGLETON_H

template <class T>
class Singleton
{
	public:
		static T& GetInstance()
		{
			static T instance;
			return instance;
		}
    private:
        Singleton();                      // Don't implement
        Singleton(Singleton const&);      // Don't Implement
        void operator=(Singleton const&); // Don't implement
};

#endif // SINGLETON_H

It seems to work well :)

michalfapso avatar Feb 23 '21 17:02 michalfapso