mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 17:03:58 +02:00
Use GenericThread, and use usleep instead of QTimer (which is incompatible with GenericThread).
This commit is contained in:
parent
b0734a06f3
commit
54877cdd47
2 changed files with 29 additions and 94 deletions
|
@ -24,50 +24,22 @@
|
|||
// As it turns out, all the other subclasses of GenericThread (at this time) do not init
|
||||
// GenericThread(parent), so things work as expected. Here we explicitly init GenericThread(nullptr)
|
||||
// so that there is no confusion and no chance for a hillarious thread debugging session.
|
||||
AvatarUpdate::AvatarUpdate() : QObject(nullptr), _lastAvatarUpdate(0), _timer(nullptr), _thread(nullptr)/*FIXME remove*/ {
|
||||
AvatarUpdate::AvatarUpdate() : GenericThread(nullptr), _lastAvatarUpdate(0)/*, _timer(nullptr), _thread(nullptr)FIXME remove*/ {
|
||||
setObjectName("Avatar Update"); // GenericThread::initialize uses this to set the thread name.
|
||||
Settings settings;
|
||||
const int DEFAULT_TARGET_AVATAR_SIMRATE = 60;
|
||||
_targetInterval = USECS_PER_SECOND / settings.value("AvatarUpdateTargetSimrate", DEFAULT_TARGET_AVATAR_SIMRATE).toInt();
|
||||
_type = settings.value("AvatarUpdateType", UpdateType::Synchronous).toInt();
|
||||
qCDebug(interfaceapp) << "AvatarUpdate using" << _type << "at" << _targetInterval << "microseconds";
|
||||
_isToBeThreaded = settings.value("AvatarUpdateIsThreaded", true).toBool();
|
||||
if (_isToBeThreaded) {
|
||||
qCDebug(interfaceapp) << "AvatarUpdate threaded at" << _targetInterval << "microsecond interval.";
|
||||
} else {
|
||||
qCDebug(interfaceapp) << "AvatarUpdate unthreaded.";
|
||||
}
|
||||
}
|
||||
// We could have the constructor call initialize(), but GenericThread::initialize can take parameters.
|
||||
// Keeping it separately called by the client allows that client to pass those without our
|
||||
// constructor needing to know about them.
|
||||
|
||||
// GenericThread::terimate() calls terminating() only when _isThreaded, so it's not good enough
|
||||
// to just override terminating(). Instead, we extend terminate();
|
||||
void AvatarUpdate::terminate() {
|
||||
if (_timer) {
|
||||
_timer->stop();
|
||||
}
|
||||
// FIXME: GenericThread::terminate();
|
||||
if (_thread) {
|
||||
_thread->quit();
|
||||
}
|
||||
}
|
||||
|
||||
// QTimer runs in the thread that starts it.
|
||||
// threadRoutine() is called once within the separate thread (if any),
|
||||
// or on each main loop update via synchronousProcess();
|
||||
void AvatarUpdate::threadRoutine() {
|
||||
if (!_timer && (_type != UpdateType::Synchronous)) {
|
||||
initTimer();
|
||||
}
|
||||
if (!_timer) {
|
||||
process();
|
||||
}
|
||||
}
|
||||
void AvatarUpdate::initTimer() {
|
||||
_timer = new QTimer(this);
|
||||
/*FIXME connect(_timer, &QTimer::timeout, this, &AvatarUpdate::process);
|
||||
_timer->start(_targetInterval / USECS_PER_MSEC);*/
|
||||
while (true) {
|
||||
process();
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarUpdate::synchronousProcess() {
|
||||
|
||||
// Keep our own updated value, so that our asynchronous code can consult it.
|
||||
|
@ -78,14 +50,17 @@ void AvatarUpdate::synchronousProcess() {
|
|||
Application::getInstance()->getMyAvatar()->doUpdateBillboard();
|
||||
}
|
||||
|
||||
//threadRoutine();
|
||||
//process(); //fixme
|
||||
if (isThreaded()) {
|
||||
return;
|
||||
}
|
||||
process();
|
||||
}
|
||||
|
||||
bool AvatarUpdate::process() {
|
||||
PerformanceTimer perfTimer("AvatarUpdate");
|
||||
quint64 start = usecTimestampNow();
|
||||
quint64 deltaMicroseconds = start - _lastAvatarUpdate;
|
||||
_lastAvatarUpdate = start;
|
||||
float deltaSeconds = deltaMicroseconds / (float) USECS_PER_SECOND;
|
||||
Application::getInstance()->setAvatarSimrateSample(1.0f / deltaSeconds);
|
||||
|
||||
|
@ -96,29 +71,15 @@ bool AvatarUpdate::process() {
|
|||
Application::getInstance()->updateMyAvatarLookAtPosition();
|
||||
// Sample hardware, update view frustum if needed, and send avatar data to mixer/nodes
|
||||
DependencyManager::get<AvatarManager>()->updateMyAvatar(deltaSeconds);
|
||||
|
||||
if (isToBeThreaded()) {
|
||||
int elapsed = (usecTimestampNow() - start);
|
||||
int usecToSleep = _targetInterval - elapsed;
|
||||
if (usecToSleep < 0) {
|
||||
usecToSleep = 1; // always yield
|
||||
}
|
||||
usleep(usecToSleep);
|
||||
}
|
||||
_lastAvatarUpdate = start;
|
||||
|
||||
if (!isThreaded()) {
|
||||
return true;
|
||||
}
|
||||
int elapsed = (usecTimestampNow() - start);
|
||||
int usecToSleep = _targetInterval - elapsed;
|
||||
if (usecToSleep < 0) {
|
||||
usecToSleep = 1; // always yield
|
||||
}
|
||||
usleep(usecToSleep);
|
||||
return true;
|
||||
}
|
||||
|
||||
// To be removed with GenericThread
|
||||
void AvatarUpdate::initialize(bool isThreaded) { //fixme remove
|
||||
if (isThreaded) {
|
||||
initThread();
|
||||
}
|
||||
}
|
||||
void AvatarUpdate::initThread() {
|
||||
_thread = new QThread();
|
||||
_thread->setObjectName(objectName());
|
||||
this->moveToThread(_thread);
|
||||
connect(_thread, &QThread::started, this, &AvatarUpdate::threadRoutine);
|
||||
_thread->start();
|
||||
}
|
||||
|
|
|
@ -15,50 +15,24 @@
|
|||
#include <QtCore/QObject>
|
||||
#include <QTimer>
|
||||
|
||||
// There are a couple of ways we could do this.
|
||||
// Right now, the goals are:
|
||||
// 1. allow development to switch between UpdateType
|
||||
// e.g.: see uses of UpdateType.
|
||||
// 2. minimize changes everwhere, particularly outside of Avatars.
|
||||
// e.g.: we could make Application::isHMDMode() thread safe, but for now we just made AvatarUpdate::isHMDMode() thread safe.
|
||||
|
||||
|
||||
// Home for the avatarUpdate operations (e.g., whether on a separate thread, pipelined in various ways, etc.)
|
||||
// This might get folded into AvatarManager.
|
||||
class AvatarUpdate : public QObject {
|
||||
class AvatarUpdate : public GenericThread {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AvatarUpdate();
|
||||
void synchronousProcess();
|
||||
void setRequestBillboardUpdate(bool needsUpdate) { _updateBillboard = needsUpdate; }
|
||||
void terminate(); // Extends GenericThread::terminate to also kill timer.
|
||||
bool isToBeThreaded() { return _isToBeThreaded; }
|
||||
|
||||
private:
|
||||
virtual bool process(); // No reason for other classes to invoke this.
|
||||
void initTimer();
|
||||
quint64 _targetInterval; // microseconds
|
||||
bool _updateBillboard;
|
||||
quint64 _lastAvatarUpdate; // microsoeconds
|
||||
|
||||
// Goes away when we get rid of the ability to switch back and forth in settings:
|
||||
enum UpdateType {
|
||||
Synchronous = 1,
|
||||
Timer,
|
||||
Thread
|
||||
};
|
||||
int _type;
|
||||
public:
|
||||
bool isToBeThreaded() const { return _type == UpdateType::Thread; } // Currently set by constructor from settings.
|
||||
void threadRoutine();
|
||||
|
||||
// Goes away when using GenericThread:
|
||||
void initialize(bool isThreaded);
|
||||
private:
|
||||
QTimer* _timer;
|
||||
QThread* _thread;
|
||||
void initThread();
|
||||
|
||||
// Goes away if Applicaiton::isHMDMode() and friends are made thread safe:
|
||||
quint64 _targetInterval; // microseconds
|
||||
bool _isToBeThreaded;
|
||||
bool _updateBillboard;
|
||||
|
||||
// Goes away if Application::getActiveDisplayPlugin() and friends are made thread safe:
|
||||
public:
|
||||
bool isHMDMode() { return _isHMDMode; }
|
||||
glm::mat4 getHeadPose() { return _headPose; }
|
||||
|
|
Loading…
Reference in a new issue