Я, может, тоже не совсем понял задачу.
Не совсем понятны эти троеточия в CData, как там все связано. Ну раз видно только mCube, DoCalc(), SetupCube(), DoSomethingWithCubes(), значит методы выполняются последовательно, и извне не используются SetupCube() и DoSomethingWithCubes(), наверное хост будет юзать mCube после этих вычислений.
Почему бы не выделить это все в отдельный воркер и помещать его в пулл потоков для вычислений.
Псевдокод (очень упрощенно):
C++ (Qt)
QThread *th = getIdleThred();
CubeWorker *worker = new CubeWorker();
worker->moveToThread(th);
connect(worker, SIGNAL(ready(CData*)), this, SLOT(proceed(CData*));
connect(this, SIGNAL(calc(CData*)), worker, SLOT(doCalc(CData*)));
emit calc(data);
Те хост говорит начать вычисления и ловит сигнал окончания, потом использует. Если нужно выполнить синхронно, то указываем дополнительные параметры в connect().
Если нет, то пулл должен организовывать очередь запросов, если все потоки заняты.
В принципе мы тут не используем всякие блокировки напрямую - все делает фреймворк (вопрос, насколько оптимально).
Не могу сказать, сколько займет процесс подготовки воркера (перемещение в поток и вызов слота doCalc).
Вот такая вот идея.
PS Забавно, об этом топике узнал из эпического "Нежелание новичков изучать документацию", похоже "показать новые сообщения" работает избирательно