View Single Post
  #3  
Old 07-29-2019, 01:02
chants chants is offline
VIP
 
Join Date: Jul 2016
Posts: 724
Rept. Given: 35
Rept. Rcvd 48 Times in 30 Posts
Thanks Given: 666
Thanks Rcvd at 1,050 Times in 475 Posts
chants Reputation: 48
Here is the final clean code of the above which is polling-free since polling technically should not be done in a waiting loop ever in modern OS code where the OS can always schedule that much more safely and efficiently:

Code:
	/// Execute code in the main thread - to be used with execute_sync().
	struct execFunctor : public exec_request_t
	{
		std::function<void()> fun;
		qsemaphore_t finishSem;
		int* taskNo;
		execFunctor(std::function<void()> f, qsemaphore_t qs, int* tsk) : fun(f), finishSem(qs), taskNo(tsk) {}
		virtual ~execFunctor(void) override {}
		/// Callback to be executed.
		/// If this function raises an exception, execute_sync() never returns.
		virtual int idaapi execute(void)
		{
			fun();
			*taskNo = -1;
			qsem_post(finishSem);
			return 0;
		}
	};
	void IdaCallback::executeOnMainThread(std::function<void()> fun)
	{
		execFunctor* ef = new execFunctor(fun, di->termSem, &di->uiExecutingTask);
		{ //must be a locked unit otherwise race condition can occur
			qmutex_locker_t lock(di->qm);
			if (di->exiting) return;
			di->uiExecutingTask = execute_sync(*ef, MFF_NOWAIT);
		}
		qsem_wait(di->termSem, -1);
		if (di->uiExecutingTask == -1) delete ef;
	}
Forced termination (of course the qsem_create/qsem_free must be called at program initialization and termination):
Code:
		{ //must be a locked unit otherwise race condition can occur
			qmutex_locker_t lock(decompInfo->qm);
			decompInfo->exiting = true;			
			if (decompInfo->uiExecutingTask != -1) {
				if (cancel_exec_request(decompInfo->uiExecutingTask)) {
					qsem_post(decompInfo->termSem);
				}
			}
		}
Note that qwait_for_handles despite the docs not making it clear works for semaphores so you can do a multiple wait (WaitForMultipleObjects/select) e.g.:
Code:
int idx = -1;
qhandle_t handles[2] = { finishSem, termSem };
while (qwait_for_handles(&idx, handles, 2, 0, -1), idx == -1) {}
Reply With Quote
The Following User Says Thank You to chants For This Useful Post:
nimaarek (08-11-2019)