<commit_before>// $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTHOMERLibManager.cxx
    @author Matthias Richter
    @date
    @brief  dynamic HLT HOMER reader/writer generation and destruction.   */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include <cerrno>
#include <cassert>
#include "AliHLTHOMERLibManager.h"
#include "AliHLTHOMERReader.h"
#include "AliHLTHOMERWriter.h"
#include "TString.h"
#include "TSystem.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTHOMERLibManager)

AliHLTHOMERLibManager::AliHLTHOMERLibManager()
  :
  fLibraryStatus(0),
  fFctCreateReaderFromTCPPort(NULL),
  fFctCreateReaderFromTCPPorts(NULL),
  fFctCreateReaderFromBuffer(NULL),
  fFctDeleteReader(NULL),
  fFctCreateWriter(NULL),
  fFctDeleteWriter(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTHOMERLibManager::~AliHLTHOMERLibManager()
{
  // see header file for class documentation
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsigned short port )
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromTCPPort!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPort_t)fFctCreateReaderFromTCPPort)(hostname, port)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPort);
  }

  return pReader;
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromTCPPorts!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPorts_t)fFctCreateReaderFromTCPPorts)(tcpCnt, hostnames, ports)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPorts);
  }

  return pReader;
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const AliHLTUInt8_t* pBuffer, int size)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromBuffer!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromBuffer_t)fFctCreateReaderFromBuffer)(pBuffer, size)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromBuffer);
  }

  return pReader;
}

int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return fLibraryStatus;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  if (fFctDeleteReader!=NULL) {
    ((AliHLTHOMERReaderDelete_t)fFctDeleteReader)(pReader);
  }

  return 0;
}

AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERWriter* pWriter=NULL;
//   if (fFctCreateWriter!=NULL && (pWriter=(((AliHLTHOMERWriterCreate_t)fFctCreateWriter)()))==NULL) {
//     HLTError("can not create instance of HOMER writer (function %p)", fFctCreateWriter);
//   }

  return pWriter;
}

int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return fLibraryStatus;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  if (fFctDeleteWriter!=NULL) {
    ((AliHLTHOMERWriterDelete_t)fFctDeleteWriter)(pWriter);
  }

  return 0;
}

int AliHLTHOMERLibManager::LoadHOMERLibrary()
{
  // see header file for class documentation
  int iResult=-EBADF;
  const char* libraries[]={"libAliHLTHOMER.so", "libHOMER.so", NULL};
  const char** library=&libraries[0];
  do {
    TString libs = gSystem->GetLibraries();
    if (libs.Contains(*library) ||
	(gSystem->Load(*library)) >= 0) {
      iResult=1;
      break;
    }
  } while (*(++library)!=NULL);

  if (iResult>0 && *library!=NULL) {
    // print compile info
    typedef void (*CompileInfo)( char*& date, char*& time);
    CompileInfo fctInfo=(CompileInfo)gSystem->DynFindSymbol(*library, "CompileInfo");
    if (fctInfo) {
      char* date="";
      char* time="";
      (*fctInfo)(date, time);
      if (!date) date="unknown";
      if (!time) time="unknown";
      //HLTInfo("%s build on %s (%s)", *library, date, time);
    } else {
      //HLTInfo("no build info available for %s", *library);
    }

    fFctCreateReaderFromTCPPort=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
    fFctCreateReaderFromTCPPorts=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
    fFctCreateReaderFromBuffer=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
    fFctDeleteReader=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
    fFctCreateWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
    fFctDeleteWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
    if (fFctCreateReaderFromTCPPort==NULL ||
	fFctCreateReaderFromTCPPorts==NULL ||
	fFctCreateReaderFromBuffer==NULL ||
	fFctDeleteReader==NULL ||
	fFctCreateWriter==NULL ||
	fFctDeleteWriter==NULL) {
      iResult=-ENOSYS;
    } else {
    }
  }
  if (iResult<0 || *library==NULL) {
    fFctCreateReaderFromTCPPort=NULL;
    fFctCreateReaderFromTCPPorts=NULL;
    fFctCreateReaderFromBuffer=NULL;
    fFctDeleteReader=NULL;
    fFctCreateWriter=NULL;
    fFctDeleteWriter=NULL;
  }

  return iResult;
}
<commit_msg>bugfix: call of creator function for HOMER writers<commit_after>// $Id$

/**************************************************************************
 * This file is property of and copyright by the ALICE HLT Project        *
 * ALICE Experiment at CERN, All rights reserved.                         *
 *                                                                        *
 * Primary Authors: Matthias Richter <Matthias.Richter@ift.uib.no>        *
 *                  for The ALICE HLT Project.                            *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/** @file   AliHLTHOMERLibManager.cxx
    @author Matthias Richter
    @date
    @brief  dynamic HLT HOMER reader/writer generation and destruction.   */

// see header file for class documentation
// or
// refer to README to build package
// or
// visit http://web.ift.uib.no/~kjeks/doc/alice-hlt

#include <cerrno>
#include <cassert>
#include "AliHLTHOMERLibManager.h"
#include "AliHLTHOMERReader.h"
#include "AliHLTHOMERWriter.h"
#include "TString.h"
#include "TSystem.h"

/** ROOT macro for the implementation of ROOT specific class methods */
ClassImp(AliHLTHOMERLibManager)

AliHLTHOMERLibManager::AliHLTHOMERLibManager()
  :
  fLibraryStatus(0),
  fFctCreateReaderFromTCPPort(NULL),
  fFctCreateReaderFromTCPPorts(NULL),
  fFctCreateReaderFromBuffer(NULL),
  fFctDeleteReader(NULL),
  fFctCreateWriter(NULL),
  fFctDeleteWriter(NULL)
{
  // see header file for class documentation
  // or
  // refer to README to build package
  // or
  // visit http://web.ift.uib.no/~kjeks/doc/alice-hlt
}

AliHLTHOMERLibManager::~AliHLTHOMERLibManager()
{
  // see header file for class documentation
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const char* hostname, unsigned short port )
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromTCPPort!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPort_t)fFctCreateReaderFromTCPPort)(hostname, port)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPort);
  }

  return pReader;
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(unsigned int tcpCnt, const char** hostnames, unsigned short* ports)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromTCPPorts!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromTCPPorts_t)fFctCreateReaderFromTCPPorts)(tcpCnt, hostnames, ports)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromTCPPorts);
  }

  return pReader;
}

AliHLTHOMERReader* AliHLTHOMERLibManager::OpenReader(const AliHLTUInt8_t* pBuffer, int size)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERReader* pReader=NULL;
  if (fFctCreateReaderFromBuffer!=NULL && (pReader=(((AliHLTHOMERReaderCreateFromBuffer_t)fFctCreateReaderFromBuffer)(pBuffer, size)))==NULL) {
    //HLTError("can not create instance of HOMER reader (function %p)", fFctCreateReaderFromBuffer);
  }

  return pReader;
}

int AliHLTHOMERLibManager::DeleteReader(AliHLTHOMERReader* pReader)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return fLibraryStatus;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  if (fFctDeleteReader!=NULL) {
    ((AliHLTHOMERReaderDelete_t)fFctDeleteReader)(pReader);
  }

  return 0;
}

AliHLTHOMERWriter* AliHLTHOMERLibManager::OpenWriter()
{
  // see header file for class documentation
  if (fLibraryStatus<0) return NULL;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  AliHLTHOMERWriter* pWriter=NULL;
  if (fFctCreateWriter!=NULL && (pWriter=(((AliHLTHOMERWriterCreate_t)fFctCreateWriter)()))==NULL) {
//     HLTError("can not create instance of HOMER writer (function %p)", fFctCreateWriter);
  }

  return pWriter;
}

int AliHLTHOMERLibManager::DeleteWriter(AliHLTHOMERWriter* pWriter)
{
  // see header file for class documentation
  if (fLibraryStatus<0) return fLibraryStatus;

  if (fLibraryStatus==0) {
    fLibraryStatus=LoadHOMERLibrary();
  }

  if (fFctDeleteWriter!=NULL) {
    ((AliHLTHOMERWriterDelete_t)fFctDeleteWriter)(pWriter);
  }

  return 0;
}

int AliHLTHOMERLibManager::LoadHOMERLibrary()
{
  // see header file for class documentation
  int iResult=-EBADF;
  const char* libraries[]={"libAliHLTHOMER.so", "libHOMER.so", NULL};
  const char** library=&libraries[0];
  do {
    TString libs = gSystem->GetLibraries();
    if (libs.Contains(*library) ||
	(gSystem->Load(*library)) >= 0) {
      iResult=1;
      break;
    }
  } while (*(++library)!=NULL);

  if (iResult>0 && *library!=NULL) {
    // print compile info
    typedef void (*CompileInfo)( char*& date, char*& time);
    CompileInfo fctInfo=(CompileInfo)gSystem->DynFindSymbol(*library, "CompileInfo");
    if (fctInfo) {
      char* date="";
      char* time="";
      (*fctInfo)(date, time);
      if (!date) date="unknown";
      if (!time) time="unknown";
      //HLTInfo("%s build on %s (%s)", *library, date, time);
    } else {
      //HLTInfo("no build info available for %s", *library);
    }

    fFctCreateReaderFromTCPPort=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORT);
    fFctCreateReaderFromTCPPorts=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_TCPPORTS);
    fFctCreateReaderFromBuffer=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_CREATE_FROM_BUFFER);
    fFctDeleteReader=gSystem->DynFindSymbol(*library, ALIHLTHOMERREADER_DELETE);
    fFctCreateWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_CREATE);
    fFctDeleteWriter=gSystem->DynFindSymbol(*library, ALIHLTHOMERWRITER_DELETE);
    if (fFctCreateReaderFromTCPPort==NULL ||
	fFctCreateReaderFromTCPPorts==NULL ||
	fFctCreateReaderFromBuffer==NULL ||
	fFctDeleteReader==NULL ||
	fFctCreateWriter==NULL ||
	fFctDeleteWriter==NULL) {
      iResult=-ENOSYS;
    } else {
    }
  }
  if (iResult<0 || *library==NULL) {
    fFctCreateReaderFromTCPPort=NULL;
    fFctCreateReaderFromTCPPorts=NULL;
    fFctCreateReaderFromBuffer=NULL;
    fFctDeleteReader=NULL;
    fFctCreateWriter=NULL;
    fFctDeleteWriter=NULL;
  }

  return iResult;
}
<|endoftext|>


<commit_before>#include "scantargetwidget.h"

#include <QDebug>
#include <QOpenGLContext>
#include <QTimer>

#include "../../ClockReceiver/TimeTypes.hpp"

ScanTargetWidget::ScanTargetWidget(QWidget *parent) : QOpenGLWidget(parent) {}
ScanTargetWidget::~ScanTargetWidget() {}

void ScanTargetWidget::initializeGL() {
	glClearColor(0.5, 0.5, 1.0, 1.0);

	// Follow each swapped frame with an additional update.
	connect(this, &QOpenGLWidget::frameSwapped, this, &ScanTargetWidget::vsync);
//	qDebug() << "share context: " << bool(context()->shareGroup());
}

void ScanTargetWidget::paintGL() {
	glClear(GL_COLOR_BUFFER_BIT);
	if(scanTarget) {
		vsync_predictor_.begin_redraw();
		scanTarget->update(width(), height());
		scanTarget->draw(width(), height());
		vsync_predictor_.end_redraw();

//		static int64_t start = 0;
//		static int frames = 0;
//		if(!start) start = Time::nanos_now();
//		else {
//			++frames;
//			const int64_t now = Time::nanos_now();
//			qDebug() << double(frames) * 1e9 / double(now - start);
//		}
	}
}

void ScanTargetWidget::vsync() {
	vsync_predictor_.announce_vsync();

	const auto time_now = Time::nanos_now();
	const auto delay_time = ((vsync_predictor_.suggested_draw_time() - time_now) / 1'000'000) - 5;	// TODO: the extra 5 is a random guess.
	if(delay_time > 0) {
		QTimer::singleShot(delay_time, this, SLOT(repaint()));
	} else {
		repaint();
	}
}

void ScanTargetWidget::resizeGL(int w, int h) {
	glViewport(0,0,w,h);
}

Outputs::Display::OpenGL::ScanTarget *ScanTargetWidget::getScanTarget() {
	makeCurrent();
	if(!scanTarget) {
		scanTarget = std::make_unique<Outputs::Display::OpenGL::ScanTarget>(defaultFramebufferObject());
	}
	return scanTarget.get();
}
<commit_msg>Retains the default window background colour until a machine is running.<commit_after>#include "scantargetwidget.h"

#include <QDebug>
#include <QOpenGLContext>
#include <QTimer>

#include "../../ClockReceiver/TimeTypes.hpp"

ScanTargetWidget::ScanTargetWidget(QWidget *parent) : QOpenGLWidget(parent) {}
ScanTargetWidget::~ScanTargetWidget() {}

void ScanTargetWidget::initializeGL() {
	// Retain the default background colour.
	const QColor backgroundColour = palette().color(QWidget::backgroundRole());
	glClearColor(backgroundColour.redF(), backgroundColour.greenF(), backgroundColour.blueF(), 1.0);

	// Follow each swapped frame with an additional update.
	connect(this, &QOpenGLWidget::frameSwapped, this, &ScanTargetWidget::vsync);
}

void ScanTargetWidget::paintGL() {
	glClear(GL_COLOR_BUFFER_BIT);
	if(scanTarget) {
		vsync_predictor_.begin_redraw();
		scanTarget->update(width(), height());
		scanTarget->draw(width(), height());
		vsync_predictor_.end_redraw();
	}
}

void ScanTargetWidget::vsync() {
	vsync_predictor_.announce_vsync();

	const auto time_now = Time::nanos_now();
	const auto delay_time = ((vsync_predictor_.suggested_draw_time() - time_now) / 1'000'000) - 5;	// TODO: the extra 5 is a random guess.
	if(delay_time > 0) {
		QTimer::singleShot(delay_time, this, SLOT(repaint()));
	} else {
		repaint();
	}
}

void ScanTargetWidget::resizeGL(int w, int h) {
	glViewport(0,0,w,h);
}

Outputs::Display::OpenGL::ScanTarget *ScanTargetWidget::getScanTarget() {
	makeCurrent();
	if(!scanTarget) {
		scanTarget = std::make_unique<Outputs::Display::OpenGL::ScanTarget>(defaultFramebufferObject());
	}
	return scanTarget.get();
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <iostream>

#include <gtest/gtest.h>

#include <qi/clock.hpp>
#include <qi/os.hpp>
#include <boost/chrono/chrono_io.hpp>

namespace chrono = boost::chrono;

TEST(QiClock, initialization)
{
  qi::Duration d0;
  EXPECT_EQ(0, d0.count());

  qi::Duration d1 = qi::Duration::zero();
  EXPECT_EQ(0, d1.count());

  qi::Duration d2 = qi::Duration();
  EXPECT_EQ(0, d2.count());

  qi::Duration d3(0);
  EXPECT_EQ(0, d3.count());

  qi::Clock::time_point t0;
  EXPECT_EQ(0, t0.time_since_epoch().count());

  qi::Clock::time_point t1(qi::Duration::zero());
  EXPECT_EQ(0, t1.time_since_epoch().count());

  qi::Clock::time_point t2 = qi::Clock::time_point();
  EXPECT_EQ(0, t2.time_since_epoch().count());
}

//TEST(QiClock, clock_sleep)
//{
//  typedef chrono::duration<int64_t, boost::pico> picoseconds;
//  qi::sleepFor(chrono::milliseconds(1));
//  qi::sleepFor(chrono::milliseconds(1) + picoseconds(1));
//  qi::sleepFor(picoseconds(1));

//  qi::sleepUntil(qi::SteadyClock::now() + chrono::seconds(1));
//  qi::sleepUntil(qi::SteadyClock::now());
//  qi::sleepUntil(qi::SteadyClock::now() - chrono::seconds(1));

//  qi::sleepUntil(qi::SystemClock::now() + chrono::seconds(1));
//  qi::sleepUntil(qi::SystemClock::now());
//  qi::sleepUntil(qi::SystemClock::now() - chrono::seconds(1));
//}

TEST(QiClock, clock_sleep_our)
{
  qi::sleepFor(qi::MilliSeconds(1));

  qi::sleepUntil(qi::SteadyClock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::SteadyClock::now());
  qi::sleepUntil(qi::SteadyClock::now() - qi::Seconds(1));

  qi::sleepUntil(qi::Clock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::Clock::now());
  qi::sleepUntil(qi::Clock::now() - qi::Seconds(1));

  qi::sleepUntil(qi::SystemClock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::SystemClock::now());
  qi::sleepUntil(qi::SystemClock::now() - qi::Seconds(1));
}

template<class Clock>
void clock_output_()
{
  typename Clock::duration d(1);
  typename Clock::time_point t = Clock::now();
  std::cout << "name: " << boost::chrono::clock_string<Clock, char>::name() << ",\t"
            << "tick: " << d << ",\t"
            << "now: " << t << "\n";
  // same, using wide chars
  std::wcout << "name: " << boost::chrono::clock_string<Clock, wchar_t>::name() << ",\t"
             << "tick: " << d << ",\t"
             << "now: " << t << "\n";
}

TEST(QiClock, clock_output)
{
  clock_output_<qi::SteadyClock>();
  clock_output_<qi::Clock>();
  clock_output_<qi::SystemClock>();
}

typedef chrono::duration<uint32_t, boost::milli > uint32ms;

TEST(QiClock, tofromUint32ms)
{
  // a test to show how we can convert from 32-bits guess-what-my-epoch-is
  // time stamps to qi::SteadyClock::time_point
  qi::Clock::duration period =
      qi::Clock::duration(uint32ms::max()) + qi::Clock::duration(uint32ms(1));
  qi::Clock::duration eps = chrono::milliseconds(4);

  // check sum-ms "noise" is removed
  qi::Clock::duration noise = chrono::nanoseconds(654321);
  qi::Clock::time_point t(period/4);
  uint32_t input_ms = chrono::duration_cast<uint32ms>(t.time_since_epoch()).count();
  EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t+noise, qi::Clock::Expect_SoonerOrLater));
  EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t-noise, qi::Clock::Expect_SoonerOrLater));

  // check we get the expected values
  for (int i = 0; i<8; ++i) {
    t = qi::Clock::time_point((i*period)/4);
    input_ms = chrono::duration_cast<uint32ms>(t.time_since_epoch()).count();

    EXPECT_EQ(input_ms, qi::Clock::toUint32ms(t));

    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period/2, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period/2 + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period/2 + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period/2, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period/2 - eps, qi::Clock::Expect_SoonerOrLater));

    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + period - eps, qi::Clock::Expect_Sooner));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period, qi::Clock::Expect_Sooner));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period + eps, qi::Clock::Expect_Sooner));

    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period - eps, qi::Clock::Expect_Later));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period + eps, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_Later));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_Later));
  }
}

TEST(QiClock, toIso8601String)
{
  qi::SystemClockTimePoint t0(qi::Duration(0));
  EXPECT_EQ("1970-01-01T000000.000Z", qi::toISO8601String(t0));
  // we do not round, we ceil:
  EXPECT_EQ("1970-01-01T000000.000Z", qi::toISO8601String(t0 + qi::MicroSeconds(999)));
  EXPECT_EQ("1970-01-01T000001.042Z", qi::toISO8601String(t0 + qi::MilliSeconds(1042)));
  EXPECT_EQ("1970-02-01T010203.000Z", qi::toISO8601String(t0 + qi::Hours(24*31+1)+qi::Minutes(2)+qi::Seconds(3)));
}

TEST(QiClock, durationSince)
{
  qi::SteadyClock::time_point tp = qi::SteadyClock::now();

  const qi::Duration sleepDuration = qi::MilliSeconds(500);
  const qi::MilliSeconds sleepDurationMs = boost::chrono::duration_cast<qi::MilliSeconds>(sleepDuration);
  const qi::MicroSeconds sleepDurationUs = boost::chrono::duration_cast<qi::MicroSeconds>(sleepDuration);

  qi::sleepFor(sleepDuration);
  const qi::MilliSeconds durMs = qi::durationSince<qi::MilliSeconds>(tp);
  const qi::MicroSeconds durUs = qi::durationSince<qi::MicroSeconds>(tp);
  const qi::Duration tol = qi::MilliSeconds(1); // only needed on Windows
  EXPECT_GE(durMs + tol, sleepDurationMs);
  EXPECT_GE(durUs + tol, sleepDurationUs);
}
<commit_msg>chrono::duration is not zero-initialized #31991<commit_after>/*
 * Copyright (c) 2013 Aldebaran Robotics. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the COPYING file.
 */

#include <iostream>

#include <gtest/gtest.h>

#include <qi/clock.hpp>
#include <qi/os.hpp>
#include <boost/chrono/chrono_io.hpp>

namespace chrono = boost::chrono;

TEST(QiClock, initialization)
{
  qi::Duration d0 = qi::Duration::zero();
  EXPECT_EQ(0, d0.count());

  qi::Duration d1(0);
  EXPECT_EQ(0, d1.count());

  qi::Clock::time_point t0;
  EXPECT_EQ(0, t0.time_since_epoch().count());

  qi::Clock::time_point t1(qi::Duration::zero());
  EXPECT_EQ(0, t1.time_since_epoch().count());

  qi::Clock::time_point t2 = qi::Clock::time_point();
  EXPECT_EQ(0, t2.time_since_epoch().count());
}

//TEST(QiClock, clock_sleep)
//{
//  typedef chrono::duration<int64_t, boost::pico> picoseconds;
//  qi::sleepFor(chrono::milliseconds(1));
//  qi::sleepFor(chrono::milliseconds(1) + picoseconds(1));
//  qi::sleepFor(picoseconds(1));

//  qi::sleepUntil(qi::SteadyClock::now() + chrono::seconds(1));
//  qi::sleepUntil(qi::SteadyClock::now());
//  qi::sleepUntil(qi::SteadyClock::now() - chrono::seconds(1));

//  qi::sleepUntil(qi::SystemClock::now() + chrono::seconds(1));
//  qi::sleepUntil(qi::SystemClock::now());
//  qi::sleepUntil(qi::SystemClock::now() - chrono::seconds(1));
//}

TEST(QiClock, clock_sleep_our)
{
  qi::sleepFor(qi::MilliSeconds(1));

  qi::sleepUntil(qi::SteadyClock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::SteadyClock::now());
  qi::sleepUntil(qi::SteadyClock::now() - qi::Seconds(1));

  qi::sleepUntil(qi::Clock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::Clock::now());
  qi::sleepUntil(qi::Clock::now() - qi::Seconds(1));

  qi::sleepUntil(qi::SystemClock::now() + qi::Seconds(1));
  qi::sleepUntil(qi::SystemClock::now());
  qi::sleepUntil(qi::SystemClock::now() - qi::Seconds(1));
}

template<class Clock>
void clock_output_()
{
  typename Clock::duration d(1);
  typename Clock::time_point t = Clock::now();
  std::cout << "name: " << boost::chrono::clock_string<Clock, char>::name() << ",\t"
            << "tick: " << d << ",\t"
            << "now: " << t << "\n";
  // same, using wide chars
  std::wcout << "name: " << boost::chrono::clock_string<Clock, wchar_t>::name() << ",\t"
             << "tick: " << d << ",\t"
             << "now: " << t << "\n";
}

TEST(QiClock, clock_output)
{
  clock_output_<qi::SteadyClock>();
  clock_output_<qi::Clock>();
  clock_output_<qi::SystemClock>();
}

typedef chrono::duration<uint32_t, boost::milli > uint32ms;

TEST(QiClock, tofromUint32ms)
{
  // a test to show how we can convert from 32-bits guess-what-my-epoch-is
  // time stamps to qi::SteadyClock::time_point
  qi::Clock::duration period =
      qi::Clock::duration(uint32ms::max()) + qi::Clock::duration(uint32ms(1));
  qi::Clock::duration eps = chrono::milliseconds(4);

  // check sum-ms "noise" is removed
  qi::Clock::duration noise = chrono::nanoseconds(654321);
  qi::Clock::time_point t(period/4);
  uint32_t input_ms = chrono::duration_cast<uint32ms>(t.time_since_epoch()).count();
  EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t+noise, qi::Clock::Expect_SoonerOrLater));
  EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t-noise, qi::Clock::Expect_SoonerOrLater));

  // check we get the expected values
  for (int i = 0; i<8; ++i) {
    t = qi::Clock::time_point((i*period)/4);
    input_ms = chrono::duration_cast<uint32ms>(t.time_since_epoch()).count();

    EXPECT_EQ(input_ms, qi::Clock::toUint32ms(t));

    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period/2, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period/2 + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period/2 + eps, qi::Clock::Expect_SoonerOrLater));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period/2, qi::Clock::Expect_SoonerOrLater));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period/2 - eps, qi::Clock::Expect_SoonerOrLater));

    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_Sooner));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t + period - eps, qi::Clock::Expect_Sooner));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period, qi::Clock::Expect_Sooner));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + period + eps, qi::Clock::Expect_Sooner));

    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period - eps, qi::Clock::Expect_Later));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t - period, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - period + eps, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t - eps, qi::Clock::Expect_Later));
    EXPECT_TRUE(t == qi::Clock::fromUint32ms(input_ms, t, qi::Clock::Expect_Later));
    EXPECT_FALSE(t == qi::Clock::fromUint32ms(input_ms, t + eps, qi::Clock::Expect_Later));
  }
}

TEST(QiClock, toIso8601String)
{
  qi::SystemClockTimePoint t0(qi::Duration(0));
  EXPECT_EQ("1970-01-01T000000.000Z", qi::toISO8601String(t0));
  // we do not round, we ceil:
  EXPECT_EQ("1970-01-01T000000.000Z", qi::toISO8601String(t0 + qi::MicroSeconds(999)));
  EXPECT_EQ("1970-01-01T000001.042Z", qi::toISO8601String(t0 + qi::MilliSeconds(1042)));
  EXPECT_EQ("1970-02-01T010203.000Z", qi::toISO8601String(t0 + qi::Hours(24*31+1)+qi::Minutes(2)+qi::Seconds(3)));
}

TEST(QiClock, durationSince)
{
  qi::SteadyClock::time_point tp = qi::SteadyClock::now();

  const qi::Duration sleepDuration = qi::MilliSeconds(500);
  const qi::MilliSeconds sleepDurationMs = boost::chrono::duration_cast<qi::MilliSeconds>(sleepDuration);
  const qi::MicroSeconds sleepDurationUs = boost::chrono::duration_cast<qi::MicroSeconds>(sleepDuration);

  qi::sleepFor(sleepDuration);
  const qi::MilliSeconds durMs = qi::durationSince<qi::MilliSeconds>(tp);
  const qi::MicroSeconds durUs = qi::durationSince<qi::MicroSeconds>(tp);
  const qi::Duration tol = qi::MilliSeconds(1); // only needed on Windows
  EXPECT_GE(durMs + tol, sleepDurationMs);
  EXPECT_GE(durUs + tol, sleepDurationUs);
}
<|endoftext|>


<commit_before>/*
qgvdial is a cross platform Google Voice Dialer
Copyright (C) 2009-2014  Yuvraaj Kelkar

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Contact: yuvraaj@gmail.com
*/

#include "OSDCipher.h"

// 32 character key
//                     "01234567890123456789012345678901"
#define QGV_CIPHER_KEY "__THIS_IS_MY_EXTREMELY_LONG_KEY_"

bool
OsdCipher::_cipher(const QByteArray &byIn, QByteArray &byOut, bool bEncrypt)
{
    return (true);
}//OsdCipher::cipher
<commit_msg>wp8: no encytion for you :P<commit_after>/*
qgvdial is a cross platform Google Voice Dialer
Copyright (C) 2009-2014  Yuvraaj Kelkar

This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

Contact: yuvraaj@gmail.com
*/

#include "OSDCipher.h"

// 32 character key
//                     "01234567890123456789012345678901"
#define QGV_CIPHER_KEY "__THIS_IS_MY_EXTREMELY_LONG_KEY_"

bool
OsdCipher::_cipher(const QByteArray &byIn, QByteArray &byOut, bool bEncrypt)
{
    // Do I reeealy need to encrypt anything when the app is entirely sandboxed?

    if (bEncrypt) {
        byOut = byIn.toBase64();
    } else {
        byOut = QByteArray::fromBase64(byIn);
    }

    return (true);
}//OsdCipher::cipher
<|endoftext|>


<commit_before>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/*
 * foregroundservice.cpp
 */

#include <taslogger.h>
#include <tascoreutils.h>
#include <tasdatashare.h>
#include "tasnativeutils.h"
#include "foregroundservice.h"

ForegroundService::ForegroundService() {}

ForegroundService::~ForegroundService() {}

bool ForegroundService::executeService(TasCommandModel& model, TasResponse& response)
{
    bool status = false;
    if(model.service() == serviceName()) {
        status = true;
        TasCommand* command = getCommandParameters(model, "BringToForeground");
        if(command){
            // Find app from client manager
            TasClientManager* clientManager = TasClientManager::instance();
            TasClient* app = 0;
            app = clientManager->findByProcessId(command->parameter("pid"));

            if (app) {
                TasLogger::logger()->debug("   App found from client manager, PID: " + app->processId());
                // Bring to foreground using native utils
                int error = TasNativeUtils::bringAppToForeground(*app);
                if (TAS_ERROR_NONE == error) {
                    TasLogger::logger()->debug("   App brought to foreground");
                }
                else {
                    TasLogger::logger()->error("   Couldn't bring app to foreground, error: " + error);
                    response.setErrorMessage("   Couldn't bring app to foreground, error: " + error);
                }
            }
            else {
                TasLogger::logger()->error("   App not found from client manager, PID: " + model.id());
                response.setErrorMessage("   App not found from client manager, PID: " + model.id());
            }
        }
        else {
            TasLogger::logger()->error("   Unknown command: " + model.name());
            response.setErrorMessage("   Unknown command: " + model.name());
        }
    }
    else if (model.service() == "changeOrientation" ){
        TasCommand* command = getCommandParameters(model, "changeOrientation");
        if(command){
            TasNativeUtils::changeOrientation(command->parameter("direction"));
        }
    }
    return status;
}
<commit_msg>Change orientation for symbian<commit_after>/***************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (testabilitydriver@nokia.com)
**
** This file is part of Testability Driver Qt Agent
**
** If you have questions regarding the use of this file, please contact
** Nokia at testabilitydriver@nokia.com .
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation
** and appearing in the file LICENSE.LGPL included in the packaging
** of this file.
**
****************************************************************************/

/*
 * foregroundservice.cpp
 */

#include <taslogger.h>
#include <tascoreutils.h>
#include <tasdatashare.h>
#include "tasnativeutils.h"
#include "foregroundservice.h"

ForegroundService::ForegroundService() {}

ForegroundService::~ForegroundService() {}

bool ForegroundService::executeService(TasCommandModel& model, TasResponse& response)
{
    bool status = false;
    if(model.service() == serviceName()) {
        status = true;
        TasCommand* command = getCommandParameters(model, "BringToForeground");
        if(command){
            // Find app from client manager
            TasClientManager* clientManager = TasClientManager::instance();
            TasClient* app = 0;
            app = clientManager->findByProcessId(command->parameter("pid"));

            if (app) {
                TasLogger::logger()->debug("   App found from client manager, PID: " + app->processId());
                // Bring to foreground using native utils
                int error = TasNativeUtils::bringAppToForeground(*app);
                if (TAS_ERROR_NONE == error) {
                    TasLogger::logger()->debug("   App brought to foreground");
                }
                else {
                    TasLogger::logger()->error("   Couldn't bring app to foreground, error: " + error);
                    response.setErrorMessage("   Couldn't bring app to foreground, error: " + error);
                }
            }
            else {
                TasLogger::logger()->error("   App not found from client manager, PID: " + model.id());
                response.setErrorMessage("   App not found from client manager, PID: " + model.id());
            }
        }
        else {
            TasLogger::logger()->error("   Unknown command: " + model.name());
            response.setErrorMessage("   Unknown command: " + model.name());
        }
    }
    else if (model.service() == "changeOrientation" ){
        status = true;
        TasCommand* command = getCommandParameters(model, "ChangeOrientation");
        if(command){
            TasNativeUtils::changeOrientation(command->parameter("direction"));
        }
    }
    return status;
}
<|endoftext|>


<commit_before>#include <QtWidgets>
#include <QtConcurrent>
#include <random>

std::default_random_engine reng;

int ilog2(qint64 val) {
  Q_ASSERT(val >= 0);
  int ret = -1;
  while (val != 0) { val >>= 1; ret++; }
  return ret;
}

/// The value binned to contain at most \a binaryDigits significant digits.
/// The less significant digits are reset to zero.
qint64 binned(qint64 value, int binaryDigits)
{
  Q_ASSERT(binaryDigits > 0);
  qint64 mask = -1;
  int clrBits = ilog2(value) - binaryDigits;
  if (clrBits > 0) mask <<= clrBits;
  return value & mask;
}

/// A safely destructible thread for perusal by QObjects.
class Thread : public QThread {
  using QThread::run;
public:
  explicit Thread(QObject * parent = 0) : QThread(parent) {}
  ~Thread() { quit(); wait(); }
};

/// An application that monitors event loops in all threads.
class MonitoringApp : public QApplication {
  Q_OBJECT
  Q_PROPERTY(int timeout READ timeout WRITE setTimeout MEMBER m_timeout)
  Q_PROPERTY(int updatePeriod READ updatePeriod WRITE setUpdatePeriod MEMBER m_updatePeriod)
public:
  typedef QMap<qint64, uint> Histogram;
  typedef QApplication Base;
private:
  struct ThreadData {
    /// A saturating, binned histogram of event handling durations for given thread.
    Histogram histogram;
    /// Number of milliseconds between the epoch and when the event handler on this thread
    /// was entered, or zero if no event handler is running.
    qint64 ping;
    /// Number of milliseconds between the epoch and when the last histogram update for
    /// this thread was broadcast
    qint64 update;
    /// Whether the thread's event loop is considered stuck at the moment
    bool stuck;
    ThreadData() : ping(0), update(0), stuck(false) {}
  };
  typedef QMap<QThread*, ThreadData> Threads;
  QMutex m_mutex;
  Threads m_threads;
  int m_timeout;
  int m_updatePeriod;

  class StuckEventLoopNotifier : public QObject {
    MonitoringApp * m_app;
    QBasicTimer m_timer;
    void timerEvent(QTimerEvent * ev) Q_DECL_OVERRIDE {
      if (ev->timerId() != m_timer.timerId()) return;
      int timeout = m_app->m_timeout;
      auto now = QDateTime::currentMSecsSinceEpoch();
      QList<QPair<QThread*, int>> toEmit;
      QMutexLocker lock(&m_app->m_mutex);
      for (auto it = m_app->m_threads.begin(); it != m_app->m_threads.end(); ++it) {
        if (it->ping == 0) continue;
        qint64 elapsed = now - it->ping;
        if (elapsed > timeout) {
          it->stuck = true;
          toEmit << qMakePair(it.key(), elapsed);
        } else {
          if (it->stuck) toEmit << qMakePair(it.key(), 0);
          it->stuck = false;
        }
      }
      lock.unlock();
      for (auto & sig : toEmit) emit m_app->loopStateChanged(sig.first, sig.second);
    }
  public:
    explicit StuckEventLoopNotifier(MonitoringApp * app) : m_app(app) {
      m_timer.start(100, Qt::CoarseTimer, this);
    }
  };
  StuckEventLoopNotifier m_notifier;
  Thread m_notifierThread;
  Q_SLOT void threadFinishedSlot() {
    auto const thread = qobject_cast<QThread*>(QObject::sender());
    QMutexLocker lock(&m_mutex);
    typename Threads::iterator it = m_threads.find(thread);
    if (it == m_threads.end()) return;
    auto const histogram(it->histogram);
    bool stuck = it->stuck;
    m_threads.erase(it);
    lock.unlock();
    emit newHistogram(thread, histogram);
    if (stuck) emit loopStateChanged(thread, 0);
    emit threadFinished(thread);
  }
  Q_SIGNAL void newThreadSignal(QThread*, const QString &);
protected:
  bool notify(QObject * receiver, QEvent * event) Q_DECL_OVERRIDE {
    auto const curThread = QThread::currentThread();
    QElapsedTimer timer;
    auto now = QDateTime::currentMSecsSinceEpoch();
    QMutexLocker lock(&m_mutex);
    typename Threads::iterator it = m_threads.find(curThread);
    bool newThread = it == m_threads.end();
    if (newThread) it = m_threads.insert(curThread, ThreadData());
    it->ping = now;
    lock.unlock();
    if (newThread) {
      connect(curThread, &QThread::finished, this, &MonitoringApp::threadFinishedSlot);
      emit newThreadSignal(curThread, curThread->objectName());
    }
    timer.start();
    auto result = Base::notify(receiver, event); // This is where the event loop can get "stuck".
    auto duration = binned(timer.elapsed(), 3);
    now += duration;
    lock.relock();
    auto & thread = m_threads[curThread];
    if (thread.histogram[duration] < std::numeric_limits<Histogram::mapped_type>::max())
      ++thread.histogram[duration];
    thread.ping = 0;
    qint64 sinceLastUpdate = now - thread.update;
    if (sinceLastUpdate >= m_updatePeriod) {
      auto const histogram = thread.histogram;
      thread.update = now;
      lock.unlock();
      emit newHistogram(curThread, histogram);
    }
    return result;
  }
public:
  explicit MonitoringApp(int & argc, char ** argv);
  /// The event loop for a given thread has gotten stuck, or unstuck.
  /** A zero elapsed time indicates that the loop is not stuck. The signal will be
    * emitted periodically with increasing values of `elapsed` for a given thread as long
    * as the loop is stuck. The thread might not exist when this notification is received. */
  Q_SIGNAL void loopStateChanged(QThread *, int elapsed);
  /// The first event was received in a newly started thread's event loop.
  /** The thread might not exist when this notification is received. */
  Q_SIGNAL void newThread(QThread *, const QString & threadName);
  /// The thread has a new histogram available.
  /** This signal is not sent more often than each updatePeriod().
    * The thread might not exist when this notification is received. */
  Q_SIGNAL void newHistogram(QThread *, const MonitoringApp::Histogram &);
  /// The thread has finished.
  /** The thread might not exist when this notification is received. A newHistogram
    * signal is always emitted prior to this signal's emission. */
  Q_SIGNAL void threadFinished(QThread *);
  /// The maximum number of milliseconds an event handler can run before the event loop
  /// is considered stuck.
  int timeout() const { return m_timeout; }
  Q_SLOT void setTimeout(int timeout) { m_timeout = timeout; }
  int updatePeriod() const { return m_updatePeriod; }
  Q_SLOT void setUpdatePeriod(int updatePeriod) { m_updatePeriod = updatePeriod; }
};
Q_DECLARE_METATYPE(QThread*)
Q_DECLARE_METATYPE(MonitoringApp::Histogram)

MonitoringApp::MonitoringApp(int & argc, char ** argv) :
  MonitoringApp::Base(argc, argv),
  m_timeout(1000), m_updatePeriod(250), m_notifier(this)
{
  qRegisterMetaType<QThread*>();
  qRegisterMetaType<MonitoringApp::Histogram>();
  connect(this, &MonitoringApp::newThreadSignal, this, &MonitoringApp::newThread,
          Qt::QueuedConnection);
  m_notifier.moveToThread(&m_notifierThread);
  m_notifierThread.start();
}

QImage renderHistogram(const MonitoringApp::Histogram & h) {
  const int blockX = 2, blockY = 2;
  QImage img(1 + h.size() * blockX, 32 * blockY, QImage::Format_ARGB32_Premultiplied);
  img.fill(Qt::white);
  QPainter p(&img);
  int x = 0;
  for (auto it = h.begin(); it != h.end(); ++it) {
    qreal key = it.key() > 0 ? log2(it.key()) : 0.0;
    QBrush b = QColor::fromHsv(qRound(240.0*(1.0 - key/32.0)), 255, 255);
    p.fillRect(QRectF(x, img.height(), blockX, -log2(it.value()) * blockY), b);
    x += blockX;
  }
  return img;
}

class MonitoringViewModel : public QStandardItemModel {
  Q_OBJECT
  QMap<QThread*, QPair<QStandardItem*, QStandardItem*>> m_threadItems;
  Q_SLOT void newThread(QThread * thread, const QString & threadName) {
    auto const caption = QString("0x%1 \"%2\"").arg(std::intptr_t(thread), 0, 16).arg(threadName);
    int row = rowCount() ? 1 : 0;
    insertRow(row);
    auto captionItem = new QStandardItem(caption);
    captionItem->setEditable(false);
    setItem(row, 0, captionItem);
    auto histogram = new QStandardItem;
    histogram->setEditable(false);
    setItem(row, 1, histogram);
    m_threadItems[thread] = qMakePair(captionItem, histogram);
    newHistogram(thread, MonitoringApp::Histogram());
  }
  Q_SLOT void newHistogramImage(QThread * thread, const QImage & img) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->second->setSizeHint(img.size());
    it->second->setData(img, Qt::DecorationRole);
  }
  Q_SIGNAL void newHistogramImageSignal(QThread * thread, const QImage & img);
  Q_SLOT void newHistogram(QThread * thread, const MonitoringApp::Histogram & histogram) {
    QtConcurrent::run([this, thread, histogram]{
      emit newHistogramImageSignal(thread, renderHistogram(histogram));
    });
  }
  Q_SLOT void loopStateChanged(QThread * thread, int elapsed) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->first->setData(elapsed ? QColor(Qt::red) : QColor(Qt::transparent), Qt::BackgroundColorRole);
  }
  Q_SLOT void threadFinished(QThread * thread) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->first->setText(QString("Finished %1").arg(it->first->text()));
    m_threadItems.remove(thread);
  }
public:
  MonitoringViewModel(QObject *parent = 0) : QStandardItemModel(parent) {
    connect(this, &MonitoringViewModel::newHistogramImageSignal,
            this, &MonitoringViewModel::newHistogramImage);
    auto app = qobject_cast<MonitoringApp*>(qApp);
    connect(app, &MonitoringApp::newThread, this, &MonitoringViewModel::newThread);
    connect(app, &MonitoringApp::newHistogram,  this, &MonitoringViewModel::newHistogram);
    connect(app, &MonitoringApp::threadFinished, this, &MonitoringViewModel::threadFinished);
    connect(app, &MonitoringApp::loopStateChanged, this, &MonitoringViewModel::loopStateChanged);
  }
};

class WorkerObject : public QObject {
  Q_OBJECT
  int m_trials;
  double m_probability;
  QBasicTimer m_timer;
  void timerEvent(QTimerEvent * ev) {
    if (ev->timerId() != m_timer.timerId()) return;
    QThread::msleep(std::binomial_distribution<>(m_trials, m_probability)(reng));
  }
public:
  WorkerObject(QObject * parent = 0) : QObject(parent), m_trials(2000), m_probability(0.2) {}
  Q_SLOT void start() { m_timer.start(0, this); }
  int trials() const { return m_trials; }
  Q_SLOT void setTrials(int trials) { m_trials = trials; }
  double probability() const { return m_probability; }
  Q_SLOT void setProbability(double p) { m_probability = p; }
};

int main(int argc, char *argv[])
{
  MonitoringApp app(argc, argv);
  MonitoringViewModel model;
  WorkerObject workerObject;
  Thread workerThread;

  QWidget w;
  QGridLayout layout(&w);
  QTableView view;
  QLabel timeoutLabel;
  QSlider timeout(Qt::Horizontal);
  QGroupBox worker("Worker Thread");
  worker.setCheckable(true);
  worker.setChecked(false);
  QGridLayout wLayout(&worker);
  QLabel rangeLabel, probabilityLabel;
  QSlider range(Qt::Horizontal), probability(Qt::Horizontal);

  timeoutLabel.setMinimumWidth(50);
  QObject::connect(&timeout, &QSlider::valueChanged, &timeoutLabel, (void(QLabel::*)(int))&QLabel::setNum);
  timeout.setMinimum(50);
  timeout.setMaximum(5000);
  timeout.setValue(app.timeout());
  view.setModel(&model);
  view.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

  layout.addWidget(&view, 0, 0, 1, 3);
  layout.addWidget(new QLabel("Timeout"), 1, 0);
  layout.addWidget(&timeoutLabel, 1, 1);
  layout.addWidget(&timeout, 1, 2);
  layout.addWidget(&worker, 2, 0, 1, 3);

  QObject::connect(&range, &QAbstractSlider::valueChanged, [&](int p){
    rangeLabel.setText(QString("Range %1 ms").arg(p));
    workerObject.setTrials(p);
  });
  QObject::connect(&probability, &QAbstractSlider::valueChanged, [&](int p){
    double prob = p / (double)probability.maximum();
    probabilityLabel.setText(QString("Probability %1").arg(prob, 0, 'g', 2));
    workerObject.setProbability(prob);
  });
  range.setMaximum(10000);
  range.setValue(workerObject.trials());
  probability.setValue(workerObject.probability() * probability.maximum());

  wLayout.addWidget(new QLabel("Sleep Time Binomial Distribution"), 0, 0, 1, 2);
  wLayout.addWidget(&rangeLabel, 1, 0);
  wLayout.addWidget(&range, 2, 0);
  wLayout.addWidget(&probabilityLabel, 1, 1);
  wLayout.addWidget(&probability, 2, 1);

  QObject::connect(&worker, &QGroupBox::toggled, [&](bool run) {
    if (run) {
      workerThread.start();
      QMetaObject::invokeMethod(&workerObject, "start");
    } else workerThread.quit();
  });
  QObject::connect(&timeout, &QAbstractSlider::valueChanged, &app, &MonitoringApp::setTimeout);
  workerObject.moveToThread(&workerThread);
  w.show();
  return app.exec();
}

#include "main.moc"
<commit_msg>Fix orphaned timer errors.<commit_after>#include <QtWidgets>
#include <QtConcurrent>
#include <random>

std::default_random_engine reng;

int ilog2(qint64 val) {
  Q_ASSERT(val >= 0);
  int ret = -1;
  while (val != 0) { val >>= 1; ret++; }
  return ret;
}

/// The value binned to contain at most \a binaryDigits significant digits.
/// The less significant digits are reset to zero.
qint64 binned(qint64 value, int binaryDigits)
{
  Q_ASSERT(binaryDigits > 0);
  qint64 mask = -1;
  int clrBits = ilog2(value) - binaryDigits;
  if (clrBits > 0) mask <<= clrBits;
  return value & mask;
}

/// A safely destructible thread for perusal by QObjects.
class Thread final : public QThread {
  Q_OBJECT
  void run() override {
    connect(QAbstractEventDispatcher::instance(this),
            &QAbstractEventDispatcher::aboutToBlock,
            this, &Thread::aboutToBlock);
    QThread::run();
  }
  QAtomicInt inDestructor;
public:
  using QThread::QThread;
  /// Take an object and prevent timer resource leaks when the object is about
  /// to become threadless.
  void takeObject(QObject *obj) {
    // Work around to prevent
    // QBasicTimer::stop: Failed. Possibly trying to stop from a different thread
    static constexpr char kRegistered[] = "__ThreadRegistered";
    static constexpr char kMoved[] = "__Moved";
    if (!obj->property(kRegistered).isValid()) {
      QObject::connect(this, &Thread::finished, obj, [this, obj]{
        if (!inDestructor.load() || obj->thread() != this)
          return;
        // The object is about to become threadless
        Q_ASSERT(obj->thread() == QThread::currentThread());
        obj->setProperty(kMoved, true);
        obj->moveToThread(this->thread());
      }, Qt::DirectConnection);
      QObject::connect(this, &QObject::destroyed, obj, [obj]{
        if (!obj->thread()) {
          obj->moveToThread(QThread::currentThread());
          obj->setProperty(kRegistered, {});
        }
        else if (obj->thread() == QThread::currentThread() && obj->property(kMoved).isValid()) {
          obj->setProperty(kMoved, {});
          QCoreApplication::sendPostedEvents(obj, QEvent::MetaCall);
        }
        else if (obj->thread()->eventDispatcher())
          QTimer::singleShot(0, obj, [obj]{ obj->setProperty(kRegistered, {}); });
      }, Qt::DirectConnection);

      obj->setProperty(kRegistered, true);
    }
    obj->moveToThread(this);
  }
  ~Thread() override {
    inDestructor.store(1);
    requestInterruption();
    quit();
    wait();
  }
  Q_SIGNAL void aboutToBlock();
};

/// An application that monitors event loops in all threads.
class MonitoringApp : public QApplication {
  Q_OBJECT
  Q_PROPERTY(int timeout READ timeout WRITE setTimeout MEMBER m_timeout)
  Q_PROPERTY(int updatePeriod READ updatePeriod WRITE setUpdatePeriod MEMBER m_updatePeriod)
public:
  typedef QMap<qint64, uint> Histogram;
  typedef QApplication Base;
private:
  struct ThreadData {
    /// A saturating, binned histogram of event handling durations for given thread.
    Histogram histogram;
    /// Number of milliseconds between the epoch and when the event handler on this thread
    /// was entered, or zero if no event handler is running.
    qint64 ping;
    /// Number of milliseconds between the epoch and when the last histogram update for
    /// this thread was broadcast
    qint64 update;
    /// Whether the thread's event loop is considered stuck at the moment
    bool stuck;
    ThreadData() : ping(0), update(0), stuck(false) {}
  };
  typedef QMap<QThread*, ThreadData> Threads;
  QMutex m_mutex;
  Threads m_threads;
  int m_timeout;
  int m_updatePeriod;

  class StuckEventLoopNotifier : public QObject {
    MonitoringApp * m_app;
    QBasicTimer m_timer;
    void timerEvent(QTimerEvent * ev) Q_DECL_OVERRIDE {
      if (ev->timerId() != m_timer.timerId()) return;
      int timeout = m_app->m_timeout;
      auto now = QDateTime::currentMSecsSinceEpoch();
      QList<QPair<QThread*, int>> toEmit;
      QMutexLocker lock(&m_app->m_mutex);
      for (auto it = m_app->m_threads.begin(); it != m_app->m_threads.end(); ++it) {
        if (it->ping == 0) continue;
        qint64 elapsed = now - it->ping;
        if (elapsed > timeout) {
          it->stuck = true;
          toEmit << qMakePair(it.key(), elapsed);
        } else {
          if (it->stuck) toEmit << qMakePair(it.key(), 0);
          it->stuck = false;
        }
      }
      lock.unlock();
      for (auto & sig : toEmit) emit m_app->loopStateChanged(sig.first, sig.second);
    }
  public:
    explicit StuckEventLoopNotifier(MonitoringApp * app) : m_app(app) {
      m_timer.start(100, Qt::CoarseTimer, this);
    }
  };
  StuckEventLoopNotifier m_notifier;
  Thread m_notifierThread;
  Q_SLOT void threadFinishedSlot() {
    auto const thread = qobject_cast<QThread*>(QObject::sender());
    QMutexLocker lock(&m_mutex);
    typename Threads::iterator it = m_threads.find(thread);
    if (it == m_threads.end()) return;
    auto const histogram(it->histogram);
    bool stuck = it->stuck;
    m_threads.erase(it);
    lock.unlock();
    emit newHistogram(thread, histogram);
    if (stuck) emit loopStateChanged(thread, 0);
    emit threadFinished(thread);
  }
  Q_SIGNAL void newThreadSignal(QThread*, const QString &);
protected:
  bool notify(QObject * receiver, QEvent * event) Q_DECL_OVERRIDE {
    auto const curThread = QThread::currentThread();
    QElapsedTimer timer;
    auto now = QDateTime::currentMSecsSinceEpoch();
    QMutexLocker lock(&m_mutex);
    typename Threads::iterator it = m_threads.find(curThread);
    bool newThread = it == m_threads.end();
    if (newThread) it = m_threads.insert(curThread, ThreadData());
    it->ping = now;
    lock.unlock();
    if (newThread) {
      connect(curThread, &QThread::finished, this, &MonitoringApp::threadFinishedSlot);
      emit newThreadSignal(curThread, curThread->objectName());
    }
    timer.start();
    auto result = Base::notify(receiver, event); // This is where the event loop can get "stuck".
    auto duration = binned(timer.elapsed(), 3);
    now += duration;
    lock.relock();
    auto & thread = m_threads[curThread];
    if (thread.histogram[duration] < std::numeric_limits<Histogram::mapped_type>::max())
      ++thread.histogram[duration];
    thread.ping = 0;
    qint64 sinceLastUpdate = now - thread.update;
    if (sinceLastUpdate >= m_updatePeriod) {
      auto const histogram = thread.histogram;
      thread.update = now;
      lock.unlock();
      emit newHistogram(curThread, histogram);
    }
    return result;
  }
public:
  explicit MonitoringApp(int & argc, char ** argv);
  /// The event loop for a given thread has gotten stuck, or unstuck.
  /** A zero elapsed time indicates that the loop is not stuck. The signal will be
    * emitted periodically with increasing values of `elapsed` for a given thread as long
    * as the loop is stuck. The thread might not exist when this notification is received. */
  Q_SIGNAL void loopStateChanged(QThread *, int elapsed);
  /// The first event was received in a newly started thread's event loop.
  /** The thread might not exist when this notification is received. */
  Q_SIGNAL void newThread(QThread *, const QString & threadName);
  /// The thread has a new histogram available.
  /** This signal is not sent more often than each updatePeriod().
    * The thread might not exist when this notification is received. */
  Q_SIGNAL void newHistogram(QThread *, const MonitoringApp::Histogram &);
  /// The thread has finished.
  /** The thread might not exist when this notification is received. A newHistogram
    * signal is always emitted prior to this signal's emission. */
  Q_SIGNAL void threadFinished(QThread *);
  /// The maximum number of milliseconds an event handler can run before the event loop
  /// is considered stuck.
  int timeout() const { return m_timeout; }
  Q_SLOT void setTimeout(int timeout) { m_timeout = timeout; }
  int updatePeriod() const { return m_updatePeriod; }
  Q_SLOT void setUpdatePeriod(int updatePeriod) { m_updatePeriod = updatePeriod; }
};
Q_DECLARE_METATYPE(QThread*)
Q_DECLARE_METATYPE(MonitoringApp::Histogram)

MonitoringApp::MonitoringApp(int & argc, char ** argv) :
  MonitoringApp::Base(argc, argv),
  m_timeout(1000), m_updatePeriod(250), m_notifier(this)
{
  qRegisterMetaType<QThread*>();
  qRegisterMetaType<MonitoringApp::Histogram>();
  connect(this, &MonitoringApp::newThreadSignal, this, &MonitoringApp::newThread,
          Qt::QueuedConnection);
  m_notifier.moveToThread(&m_notifierThread);
  m_notifierThread.start();
}

QImage renderHistogram(const MonitoringApp::Histogram & h) {
  const int blockX = 2, blockY = 2;
  QImage img(1 + h.size() * blockX, 32 * blockY, QImage::Format_ARGB32_Premultiplied);
  img.fill(Qt::white);
  QPainter p(&img);
  int x = 0;
  for (auto it = h.begin(); it != h.end(); ++it) {
    qreal key = it.key() > 0 ? log2(it.key()) : 0.0;
    QBrush b = QColor::fromHsv(qRound(240.0*(1.0 - key/32.0)), 255, 255);
    p.fillRect(QRectF(x, img.height(), blockX, -log2(it.value()) * blockY), b);
    x += blockX;
  }
  return img;
}

class MonitoringViewModel : public QStandardItemModel {
  Q_OBJECT
  QMap<QThread*, QPair<QStandardItem*, QStandardItem*>> m_threadItems;
  Q_SLOT void newThread(QThread * thread, const QString & threadName) {
    auto const caption = QString("0x%1 \"%2\"").arg(std::intptr_t(thread), 0, 16).arg(threadName);
    int row = rowCount() ? 1 : 0;
    insertRow(row);
    auto captionItem = new QStandardItem(caption);
    captionItem->setEditable(false);
    setItem(row, 0, captionItem);
    auto histogram = new QStandardItem;
    histogram->setEditable(false);
    setItem(row, 1, histogram);
    m_threadItems[thread] = qMakePair(captionItem, histogram);
    newHistogram(thread, MonitoringApp::Histogram());
  }
  Q_SLOT void newHistogramImage(QThread * thread, const QImage & img) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->second->setSizeHint(img.size());
    it->second->setData(img, Qt::DecorationRole);
  }
  Q_SIGNAL void newHistogramImageSignal(QThread * thread, const QImage & img);
  Q_SLOT void newHistogram(QThread * thread, const MonitoringApp::Histogram & histogram) {
    QtConcurrent::run([this, thread, histogram]{
      emit newHistogramImageSignal(thread, renderHistogram(histogram));
    });
  }
  Q_SLOT void loopStateChanged(QThread * thread, int elapsed) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->first->setData(elapsed ? QColor(Qt::red) : QColor(Qt::transparent), Qt::BackgroundColorRole);
  }
  Q_SLOT void threadFinished(QThread * thread) {
    auto it = m_threadItems.find(thread);
    if (it == m_threadItems.end()) return;
    it->first->setText(QString("Finished %1").arg(it->first->text()));
    m_threadItems.remove(thread);
  }
public:
  MonitoringViewModel(QObject *parent = 0) : QStandardItemModel(parent) {
    connect(this, &MonitoringViewModel::newHistogramImageSignal,
            this, &MonitoringViewModel::newHistogramImage);
    auto app = qobject_cast<MonitoringApp*>(qApp);
    connect(app, &MonitoringApp::newThread, this, &MonitoringViewModel::newThread);
    connect(app, &MonitoringApp::newHistogram,  this, &MonitoringViewModel::newHistogram);
    connect(app, &MonitoringApp::threadFinished, this, &MonitoringViewModel::threadFinished);
    connect(app, &MonitoringApp::loopStateChanged, this, &MonitoringViewModel::loopStateChanged);
  }
};

class WorkerObject : public QObject {
  Q_OBJECT
  int m_trials = 2000;
  double m_probability = 0.2;
  QBasicTimer m_timer;
  void timerEvent(QTimerEvent * ev) override {
    if (ev->timerId() != m_timer.timerId()) return;
    QThread::msleep(std::binomial_distribution<>(m_trials, m_probability)(reng));
  }
public:
  using QObject::QObject;
  Q_SIGNAL void stopped();
  Q_SLOT void start() { m_timer.start(0, this); }
  Q_SLOT void stop() { m_timer.stop(); emit stopped(); }
  int trials() const { return m_trials; }
  Q_SLOT void setTrials(int trials) { m_trials = trials; }
  double probability() const { return m_probability; }
  Q_SLOT void setProbability(double p) { m_probability = p; }
};

int main(int argc, char *argv[])
{
  MonitoringApp app(argc, argv);
  MonitoringViewModel model;
  WorkerObject workerObject;
  Thread workerThread;

  QWidget w;
  QGridLayout layout(&w);
  QTableView view;
  QLabel timeoutLabel;
  QSlider timeout(Qt::Horizontal);
  QGroupBox worker("Worker Thread");
  worker.setCheckable(true);
  worker.setChecked(false);
  QGridLayout wLayout(&worker);
  QLabel rangeLabel, probabilityLabel;
  QSlider range(Qt::Horizontal), probability(Qt::Horizontal);

  timeoutLabel.setMinimumWidth(50);
  QObject::connect(&timeout, &QSlider::valueChanged, &timeoutLabel, (void(QLabel::*)(int))&QLabel::setNum);
  timeout.setMinimum(50);
  timeout.setMaximum(5000);
  timeout.setValue(app.timeout());
  view.setModel(&model);
  view.verticalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);

  layout.addWidget(&view, 0, 0, 1, 3);
  layout.addWidget(new QLabel("Timeout"), 1, 0);
  layout.addWidget(&timeoutLabel, 1, 1);
  layout.addWidget(&timeout, 1, 2);
  layout.addWidget(&worker, 2, 0, 1, 3);

  QObject::connect(&range, &QAbstractSlider::valueChanged, [&](int p){
    rangeLabel.setText(QString("Range %1 ms").arg(p));
    workerObject.setTrials(p);
  });
  QObject::connect(&probability, &QAbstractSlider::valueChanged, [&](int p){
    double prob = p / (double)probability.maximum();
    probabilityLabel.setText(QString("Probability %1").arg(prob, 0, 'g', 2));
    workerObject.setProbability(prob);
  });
  range.setMaximum(10000);
  range.setValue(workerObject.trials());
  probability.setValue(workerObject.probability() * probability.maximum());

  wLayout.addWidget(new QLabel("Sleep Time Binomial Distribution"), 0, 0, 1, 2);
  wLayout.addWidget(&rangeLabel, 1, 0);
  wLayout.addWidget(&range, 2, 0);
  wLayout.addWidget(&probabilityLabel, 1, 1);
  wLayout.addWidget(&probability, 2, 1);

  QObject::connect(&workerObject, &WorkerObject::stopped, &workerThread, &Thread::quit);
  QObject::connect(&worker, &QGroupBox::toggled, [&](bool run) {
    if (run) {
      workerThread.start();
      QMetaObject::invokeMethod(&workerObject, "start");
    } else
      QMetaObject::invokeMethod(&workerObject, "stop");
  });
  QObject::connect(&timeout, &QAbstractSlider::valueChanged, &app, &MonitoringApp::setTimeout);
  workerThread.takeObject(&workerObject);
  w.show();
  return app.exec();
}

#include "main.moc"
<|endoftext|>


<commit_before>#ifndef MIMOSA_REF_COUNTABLE_HH
# define MIMOSA_REF_COUNTABLE_HH

# include <cassert>

# include "ref-counted-ptr.hh"

namespace mimosa
{
  class RefCountableBase
  {
  public:
    inline RefCountableBase()
      : ref_count_(0)
    {
    }

    inline RefCountableBase(const RefCountableBase & /*other*/)
      : ref_count_(0)
    {
    }

    virtual ~RefCountableBase() {}

    inline RefCountableBase & operator=(const RefCountableBase & /*other*/)
    {
      return *this;
    }

    inline int addRef() const
    {
      auto ret = __sync_add_and_fetch(&ref_count_, 1);
      assert(ret >= 1);
      return ret;
    }

    inline int releaseRef() const
    {
      auto ret = __sync_add_and_fetch(&ref_count_, -1);
      assert(ret >= 0);
      return ret;
    }

    mutable int ref_count_;
  };

  inline void addRef(const RefCountableBase * obj)
  {
    obj->addRef();
  }

  inline void releaseRef(const RefCountableBase * obj)
  {
    if (obj->releaseRef() == 0)
      delete obj;
  }

# define MIMOSA_DEF_PTR(T...)                   \
  typedef RefCountedPtr<T > Ptr;                \
  typedef RefCountedPtr<const T > ConstPtr

  template <typename T >
  class RefCountable : public RefCountableBase
  {
  public:
    MIMOSA_DEF_PTR(T);
  };
}

#endif /* !MIMOSA_REF_COUNTABLE_HH */
<commit_msg>Fixed MIMOSA_DEF_PTR by using ::mimosa::<commit_after>#ifndef MIMOSA_REF_COUNTABLE_HH
# define MIMOSA_REF_COUNTABLE_HH

# include <cassert>

# include "ref-counted-ptr.hh"

namespace mimosa
{
  class RefCountableBase
  {
  public:
    inline RefCountableBase()
      : ref_count_(0)
    {
    }

    inline RefCountableBase(const RefCountableBase & /*other*/)
      : ref_count_(0)
    {
    }

    virtual ~RefCountableBase() {}

    inline RefCountableBase & operator=(const RefCountableBase & /*other*/)
    {
      return *this;
    }

    inline int addRef() const
    {
      auto ret = __sync_add_and_fetch(&ref_count_, 1);
      assert(ret >= 1);
      return ret;
    }

    inline int releaseRef() const
    {
      auto ret = __sync_add_and_fetch(&ref_count_, -1);
      assert(ret >= 0);
      return ret;
    }

    mutable int ref_count_;
  };

  inline void addRef(const RefCountableBase * obj)
  {
    obj->addRef();
  }

  inline void releaseRef(const RefCountableBase * obj)
  {
    if (obj->releaseRef() == 0)
      delete obj;
  }

# define MIMOSA_DEF_PTR(T...)                           \
  typedef ::mimosa::RefCountedPtr<T > Ptr;              \
  typedef ::mimosa::RefCountedPtr<const T > ConstPtr

  template <typename T >
  class RefCountable : public ::mimosa::RefCountableBase
  {
  public:
    MIMOSA_DEF_PTR(T);
  };
}

#endif /* !MIMOSA_REF_COUNTABLE_HH */
<|endoftext|>


<commit_before>/******************************************************************************
 * root_bind.cpp - bindings for Ogre::Root
 ******************************************************************************
 * This file is part of
 *     __ __              _
 *    / // /_____ ____   (_)
 *   / // // ___// __ \ / /
 *  / // // /__ / /_/ // /
 * /_//_/ \___/ \____//_/
 *
 * Low Level C Ogre Interface (llcoi)
 *
 * See http://code.google.com/p/llcoi/ for more information.
 *
 * Copyright (c) 2011, Llcoi Team
 *
 * License: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/
#include "ogre_interface.h"

#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreWindowEventUtilities.h>
#include <OgreConfigFile.h>
#include "ogre_manager.h"

template<> OgreManager* Ogre::Singleton<OgreManager>::ms_Singleton = 0;

void load_ogre_plugin(const char* plugin);

void default_engine_options(engine_options* options)
{
    options->renderer_s = "OpenGL";
#ifdef PLATFORM_WIN
    options->plugin_folder_s = ".";
#else
    options->plugin_folder_s = "/usr/local/lib/OGRE";
#endif
    options->window_title = "Renderwindow";
    options->width = 800;
    options->height = 600;
    options->auto_window = 1;
    options->log_name = "Ogre.log";
}

void init_engine(const engine_options options)
{
    new OgreManager();

    OgreManager::getSingletonPtr()->set_plugin_folder(options.plugin_folder_s);
    // suppress console logging
    Ogre::LogManager * log_man = new Ogre::LogManager();
    Ogre::Log * vge_log = log_man->createLog(options.log_name, true, false);
    Ogre::Root * root = new Ogre::Root("", "", "");

    // default
    const char * renderer = "OpenGL Rendering Subsystem";
    const char * render_plugin = "RenderSystem_GL";

    if (strstr(options.renderer_s,"Direct") || strstr(options.renderer_s,"D3D")) {
        renderer = "Direct3D9 Rendering Subsystem";
        render_plugin = "RenderSystem_Direct3D9";
    } else if (!strstr(options.renderer_s,"GL"))
        Ogre::LogManager::getSingleton().logMessage(
            "Can't parse renderer string, using default (OpenGL)");

    load_ogre_plugin(render_plugin);
    Ogre::RenderSystem* rs = root->getRenderSystemByName( Ogre::String(renderer) );
    rs->setConfigOption("Full Screen", "No");
    rs->setConfigOption("VSync", "No");
    //rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit");
    rs->setConfigOption("Video Mode", Ogre::StringConverter::toString(options.width) + " x " +
                        Ogre::StringConverter::toString(options.height) + " @ 32-bit");

    root->setRenderSystem(rs);

    load_ogre_plugin("Plugin_OctreeSceneManager");

    Ogre::SceneManager * scene_manager =
        root->createSceneManager(Ogre::ST_GENERIC, "scene-manager");

    if (options.auto_window) {
        OgreManager::getSingletonPtr()->setActiveRenderWindow(root->initialise(true , options.window_title));
    } else {
        root->initialise(false , options.window_title);
    }
}

void release_engine()
{
    delete Ogre::Root::getSingletonPtr();
}

// Ogre::Root::initialise(bool, std::string const&, std::string const&)
RenderWindowHandle root_initialise(int auto_create_window, const char* render_window_title)
{
    Ogre::RenderWindow* window = Ogre::Root::getSingletonPtr()->initialise(auto_create_window, render_window_title);
    if(auto_create_window)
        OgreManager::getSingletonPtr()->setActiveRenderWindow(window);
    return reinterpret_cast<RenderWindowHandle>(window);
}

// Ogre::Root::isInitialised() const
DLL int root_is_initialised()
{
    if(Ogre::Root::getSingletonPtr()->isInitialised())
        return 1;
    return 0;
}

// Ogre::Root::Root(std::string const&, std::string const&, std::string const&)
RootHandle create_root(const char* pluginFileName, const char* configFileName, const char* logFileName)
{
    new OgreManager();
    Ogre::Root* root = new Ogre::Root(Ogre::String(pluginFileName), Ogre::String(configFileName), Ogre::String(logFileName));
    return reinterpret_cast<RootHandle>(root);
}

void save_config()
{
    Ogre::Root::getSingletonPtr()->saveConfig();
}

// Ogre::Root::restoreConfig()
int restore_config()
{
    if(Ogre::Root::getSingletonPtr()->restoreConfig())
        return 1;
    return 0;
}

// Ogre::Root::showConfigDialog()
int show_config_dialog()
{
    if(Ogre::Root::getSingletonPtr()->showConfigDialog())
        return 1;
    return 0;
}

// Ogre::Root::loadPlugin(std::string const&)
void load_ogre_plugin(const char* plugin)
{
#if defined( WIN32 ) || defined( _WINDOWS )
    Ogre::String pluginString(plugin);
#ifdef _DEBUG
    Ogre::Root::getSingleton().loadPlugin(pluginString + Ogre::String("_d"));
#else
    Ogre::Root::getSingleton().loadPlugin(plugin);
#endif
#else
    Ogre::Root::getSingleton().loadPlugin( Ogre::String(OgreManager::getSingletonPtr()->get_plugin_folder()) + "/" + plugin );
#endif
}

// Ogre::Root::renderOneFrame()
int render_one_frame()
{
    if(Ogre::Root::getSingletonPtr()->renderOneFrame())
        return 1;
    return 0;
}

// Ogre::Root::renderOneFrame(float)
int render_one_frame_ex(float time_since_last_frame)
{
    if(Ogre::Root::getSingletonPtr()->renderOneFrame(time_since_last_frame))
        return 1;
    return 0;
}

void pump_messages()
{
	Ogre::WindowEventUtilities::messagePump();
}

static bool do_render = 1;

void render_loop()
{
    while (do_render)
    {
        // Pump window messages for nice behaviour
        Ogre::WindowEventUtilities::messagePump();

        // Render a frame
        if(!Ogre::Root::getSingletonPtr()->renderOneFrame())
        {
            do_render = 0;
        }

        if (OgreManager::getSingletonPtr()->getActiveRenderWindow()->isClosed())
        {
            do_render = 0;
        }
    }
}

/*
Ogre::Root::~Root()
Ogre::Root::saveConfig()
Ogre::Root::addRenderSystem(Ogre::RenderSystem*)
Ogre::Root::getAvailableRenderers()
Ogre::Root::getRenderSystemByName(std::string const&)
Ogre::Root::setRenderSystem(Ogre::RenderSystem*)
Ogre::Root::getRenderSystem()
Ogre::Root::useCustomRenderSystemCapabilities(Ogre::RenderSystemCapabilities*)
Ogre::Root::getRemoveRenderQueueStructuresOnClear() const
Ogre::Root::setRemoveRenderQueueStructuresOnClear(bool)
Ogre::Root::addSceneManagerFactory(Ogre::SceneManagerFactory*)
Ogre::Root::removeSceneManagerFactory(Ogre::SceneManagerFactory*)
Ogre::Root::getSceneManagerMetaData(std::string const&) const
Ogre::Root::getSceneManagerMetaDataIterator() const
Ogre::Root::createSceneManager(std::string const&, std::string const&)
Ogre::Root::createSceneManager(unsigned short, std::string const&)
Ogre::Root::destroySceneManager(Ogre::SceneManager*)
Ogre::Root::getSceneManager(std::string const&) const
Ogre::Root::hasSceneManager(std::string const&) const
Ogre::Root::getSceneManagerIterator()
Ogre::Root::getTextureManager()
Ogre::Root::getMeshManager()
Ogre::Root::getErrorDescription(long)
Ogre::Root::addFrameListener(Ogre::FrameListener*)
Ogre::Root::removeFrameListener(Ogre::FrameListener*)
Ogre::Root::queueEndRendering()
Ogre::Root::startRendering()
Ogre::Root::shutdown()
Ogre::Root::addResourceLocation(std::string const&, std::string const&, std::string const&, bool)
Ogre::Root::removeResourceLocation(std::string const&, std::string const&)
Ogre::Root::createFileStream(std::string const&, std::string const&, bool, std::string const&)
Ogre::Root::openFileStream(std::string const&, std::string const&, std::string const&)
Ogre::Root::convertColourValue(Ogre::ColourValue const&, unsigned int*)
Ogre::Root::getAutoCreatedWindow()
Ogre::Root::createRenderWindow(std::string const&, unsigned int, unsigned int, bool, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const*)
Ogre::Root::createRenderWindows(std::vector<Ogre::RenderWindowDescription, Ogre::STLAllocator<Ogre::RenderWindowDescription, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&, std::vector<Ogre::RenderWindow*, Ogre::STLAllocator<Ogre::RenderWindow*, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > >&)
Ogre::Root::detachRenderTarget(Ogre::RenderTarget*)
Ogre::Root::detachRenderTarget(std::string const&)
Ogre::Root::getRenderTarget(std::string const&)
Ogre::Root::unloadPlugin(std::string const&)
Ogre::Root::installPlugin(Ogre::Plugin*)
Ogre::Root::uninstallPlugin(Ogre::Plugin*)
Ogre::Root::getInstalledPlugins() const
Ogre::Root::getTimer()
Ogre::Root::_fireFrameStarted(Ogre::FrameEvent&)
Ogre::Root::_fireFrameRenderingQueued(Ogre::FrameEvent&)
Ogre::Root::_fireFrameEnded(Ogre::FrameEvent&)
Ogre::Root::_fireFrameStarted()
Ogre::Root::_fireFrameRenderingQueued()
Ogre::Root::_fireFrameEnded()
Ogre::Root::getNextFrameNumber() const
Ogre::Root::_getCurrentSceneManager() const
Ogre::Root::_pushCurrentSceneManager(Ogre::SceneManager*)
Ogre::Root::_popCurrentSceneManager(Ogre::SceneManager*)
Ogre::Root::_updateAllRenderTargets()
Ogre::Root::_updateAllRenderTargets(Ogre::FrameEvent&)
Ogre::Root::createRenderQueueInvocationSequence(std::string const&)
Ogre::Root::getRenderQueueInvocationSequence(std::string const&)
Ogre::Root::destroyRenderQueueInvocationSequence(std::string const&)
Ogre::Root::destroyAllRenderQueueInvocationSequences()
Ogre::Root::getSingleton()
Ogre::Root::getSingletonPtr()
Ogre::Root::clearEventTimes()
Ogre::Root::setFrameSmoothingPeriod(float)
Ogre::Root::getFrameSmoothingPeriod() const
Ogre::Root::addMovableObjectFactory(Ogre::MovableObjectFactory*, bool)
Ogre::Root::removeMovableObjectFactory(Ogre::MovableObjectFactory*)
Ogre::Root::hasMovableObjectFactory(std::string const&) const
Ogre::Root::getMovableObjectFactory(std::string const&)
Ogre::Root::_allocateNextMovableObjectTypeFlag()
Ogre::Root::getMovableObjectFactoryIterator() const
Ogre::Root::getDisplayMonitorCount() const
Ogre::Root::getWorkQueue() const
Ogre::Root::setWorkQueue(Ogre::WorkQueue*)
Ogre::Root::setBlendIndicesGpuRedundant(bool)
Ogre::Root::isBlendIndicesGpuRedundant() const
Ogre::Root::setBlendWeightsGpuRedundant(bool)
Ogre::Root::isBlendWeightsGpuRedundant() const
*/
<commit_msg>make compile with 1.8 and above<commit_after>/******************************************************************************
 * root_bind.cpp - bindings for Ogre::Root
 ******************************************************************************
 * This file is part of
 *     __ __              _
 *    / // /_____ ____   (_)
 *   / // // ___// __ \ / /
 *  / // // /__ / /_/ // /
 * /_//_/ \___/ \____//_/
 *
 * Low Level C Ogre Interface (llcoi)
 *
 * See http://code.google.com/p/llcoi/ for more information.
 *
 * Copyright (c) 2011, Llcoi Team
 *
 * License: MIT
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/
#include "ogre_interface.h"

#include <OgreRoot.h>
#include <OgreRenderWindow.h>
#include <OgreWindowEventUtilities.h>
#include <OgreConfigFile.h>
#include "ogre_manager.h"

template<> OgreManager* Ogre::Singleton<OgreManager>::msSingleton = 0;

void load_ogre_plugin(const char* plugin);

void default_engine_options(engine_options* options)
{
    options->renderer_s = "OpenGL";
#ifdef PLATFORM_WIN
    options->plugin_folder_s = ".";
#else
    options->plugin_folder_s = "/usr/local/lib/OGRE";
#endif
    options->window_title = "Renderwindow";
    options->width = 800;
    options->height = 600;
    options->auto_window = 1;
    options->log_name = "Ogre.log";
}

void init_engine(const engine_options options)
{
    new OgreManager();

    OgreManager::getSingletonPtr()->set_plugin_folder(options.plugin_folder_s);
    // suppress console logging
    Ogre::LogManager * log_man = new Ogre::LogManager();
    Ogre::Log * vge_log = log_man->createLog(options.log_name, true, false);
    Ogre::Root * root = new Ogre::Root("", "", "");

    // default
    const char * renderer = "OpenGL Rendering Subsystem";
    const char * render_plugin = "RenderSystem_GL";

    if (strstr(options.renderer_s,"Direct") || strstr(options.renderer_s,"D3D")) {
        renderer = "Direct3D9 Rendering Subsystem";
        render_plugin = "RenderSystem_Direct3D9";
    } else if (!strstr(options.renderer_s,"GL"))
        Ogre::LogManager::getSingleton().logMessage(
            "Can't parse renderer string, using default (OpenGL)");

    load_ogre_plugin(render_plugin);
    Ogre::RenderSystem* rs = root->getRenderSystemByName( Ogre::String(renderer) );
    rs->setConfigOption("Full Screen", "No");
    rs->setConfigOption("VSync", "No");
    //rs->setConfigOption("Video Mode", "800 x 600 @ 32-bit");
    rs->setConfigOption("Video Mode", Ogre::StringConverter::toString(options.width) + " x " +
                        Ogre::StringConverter::toString(options.height) + " @ 32-bit");

    root->setRenderSystem(rs);

    load_ogre_plugin("Plugin_OctreeSceneManager");

    Ogre::SceneManager * scene_manager =
        root->createSceneManager(Ogre::ST_GENERIC, "scene-manager");

    if (options.auto_window) {
        OgreManager::getSingletonPtr()->setActiveRenderWindow(root->initialise(true , options.window_title));
    } else {
        root->initialise(false , options.window_title);
    }
}

void release_engine()
{
    delete Ogre::Root::getSingletonPtr();
}

// Ogre::Root::initialise(bool, std::string const&, std::string const&)
RenderWindowHandle root_initialise(int auto_create_window, const char* render_window_title)
{
    Ogre::RenderWindow* window = Ogre::Root::getSingletonPtr()->initialise(auto_create_window, render_window_title);
    if(auto_create_window)
        OgreManager::getSingletonPtr()->setActiveRenderWindow(window);
    return reinterpret_cast<RenderWindowHandle>(window);
}

// Ogre::Root::isInitialised() const
DLL int root_is_initialised()
{
    if(Ogre::Root::getSingletonPtr()->isInitialised())
        return 1;
    return 0;
}

// Ogre::Root::Root(std::string const&, std::string const&, std::string const&)
RootHandle create_root(const char* pluginFileName, const char* configFileName, const char* logFileName)
{
    new OgreManager();
    Ogre::Root* root = new Ogre::Root(Ogre::String(pluginFileName), Ogre::String(configFileName), Ogre::String(logFileName));
    return reinterpret_cast<RootHandle>(root);
}

void save_config()
{
    Ogre::Root::getSingletonPtr()->saveConfig();
}

// Ogre::Root::restoreConfig()
int restore_config()
{
    if(Ogre::Root::getSingletonPtr()->restoreConfig())
        return 1;
    return 0;
}

// Ogre::Root::showConfigDialog()
int show_config_dialog()
{
    if(Ogre::Root::getSingletonPtr()->showConfigDialog())
        return 1;
    return 0;
}

// Ogre::Root::loadPlugin(std::string const&)
void load_ogre_plugin(const char* plugin)
{
#if defined( WIN32 ) || defined( _WINDOWS )
    Ogre::String pluginString(plugin);
#ifdef _DEBUG
    Ogre::Root::getSingleton().loadPlugin(pluginString + Ogre::String("_d"));
#else
    Ogre::Root::getSingleton().loadPlugin(plugin);
#endif
#else
    Ogre::Root::getSingleton().loadPlugin( Ogre::String(OgreManager::getSingletonPtr()->get_plugin_folder()) + "/" + plugin );
#endif
}

// Ogre::Root::renderOneFrame()
int render_one_frame()
{
    if(Ogre::Root::getSingletonPtr()->renderOneFrame())
        return 1;
    return 0;
}

// Ogre::Root::renderOneFrame(float)
int render_one_frame_ex(float time_since_last_frame)
{
    if(Ogre::Root::getSingletonPtr()->renderOneFrame(time_since_last_frame))
        return 1;
    return 0;
}

void pump_messages()
{
	Ogre::WindowEventUtilities::messagePump();
}

static bool do_render = 1;

void render_loop()
{
    while (do_render)
    {
        // Pump window messages for nice behaviour
        Ogre::WindowEventUtilities::messagePump();

        // Render a frame
        if(!Ogre::Root::getSingletonPtr()->renderOneFrame())
        {
            do_render = 0;
        }

        if (OgreManager::getSingletonPtr()->getActiveRenderWindow()->isClosed())
        {
            do_render = 0;
        }
    }
}

/*
Ogre::Root::~Root()
Ogre::Root::saveConfig()
Ogre::Root::addRenderSystem(Ogre::RenderSystem*)
Ogre::Root::getAvailableRenderers()
Ogre::Root::getRenderSystemByName(std::string const&)
Ogre::Root::setRenderSystem(Ogre::RenderSystem*)
Ogre::Root::getRenderSystem()
Ogre::Root::useCustomRenderSystemCapabilities(Ogre::RenderSystemCapabilities*)
Ogre::Root::getRemoveRenderQueueStructuresOnClear() const
Ogre::Root::setRemoveRenderQueueStructuresOnClear(bool)
Ogre::Root::addSceneManagerFactory(Ogre::SceneManagerFactory*)
Ogre::Root::removeSceneManagerFactory(Ogre::SceneManagerFactory*)
Ogre::Root::getSceneManagerMetaData(std::string const&) const
Ogre::Root::getSceneManagerMetaDataIterator() const
Ogre::Root::createSceneManager(std::string const&, std::string const&)
Ogre::Root::createSceneManager(unsigned short, std::string const&)
Ogre::Root::destroySceneManager(Ogre::SceneManager*)
Ogre::Root::getSceneManager(std::string const&) const
Ogre::Root::hasSceneManager(std::string const&) const
Ogre::Root::getSceneManagerIterator()
Ogre::Root::getTextureManager()
Ogre::Root::getMeshManager()
Ogre::Root::getErrorDescription(long)
Ogre::Root::addFrameListener(Ogre::FrameListener*)
Ogre::Root::removeFrameListener(Ogre::FrameListener*)
Ogre::Root::queueEndRendering()
Ogre::Root::startRendering()
Ogre::Root::shutdown()
Ogre::Root::addResourceLocation(std::string const&, std::string const&, std::string const&, bool)
Ogre::Root::removeResourceLocation(std::string const&, std::string const&)
Ogre::Root::createFileStream(std::string const&, std::string const&, bool, std::string const&)
Ogre::Root::openFileStream(std::string const&, std::string const&, std::string const&)
Ogre::Root::convertColourValue(Ogre::ColourValue const&, unsigned int*)
Ogre::Root::getAutoCreatedWindow()
Ogre::Root::createRenderWindow(std::string const&, unsigned int, unsigned int, bool, std::map<std::string, std::string, std::less<std::string>, Ogre::STLAllocator<std::pair<std::string const, std::string>, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const*)
Ogre::Root::createRenderWindows(std::vector<Ogre::RenderWindowDescription, Ogre::STLAllocator<Ogre::RenderWindowDescription, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > > const&, std::vector<Ogre::RenderWindow*, Ogre::STLAllocator<Ogre::RenderWindow*, Ogre::CategorisedAllocPolicy<(Ogre::MemoryCategory)0> > >&)
Ogre::Root::detachRenderTarget(Ogre::RenderTarget*)
Ogre::Root::detachRenderTarget(std::string const&)
Ogre::Root::getRenderTarget(std::string const&)
Ogre::Root::unloadPlugin(std::string const&)
Ogre::Root::installPlugin(Ogre::Plugin*)
Ogre::Root::uninstallPlugin(Ogre::Plugin*)
Ogre::Root::getInstalledPlugins() const
Ogre::Root::getTimer()
Ogre::Root::_fireFrameStarted(Ogre::FrameEvent&)
Ogre::Root::_fireFrameRenderingQueued(Ogre::FrameEvent&)
Ogre::Root::_fireFrameEnded(Ogre::FrameEvent&)
Ogre::Root::_fireFrameStarted()
Ogre::Root::_fireFrameRenderingQueued()
Ogre::Root::_fireFrameEnded()
Ogre::Root::getNextFrameNumber() const
Ogre::Root::_getCurrentSceneManager() const
Ogre::Root::_pushCurrentSceneManager(Ogre::SceneManager*)
Ogre::Root::_popCurrentSceneManager(Ogre::SceneManager*)
Ogre::Root::_updateAllRenderTargets()
Ogre::Root::_updateAllRenderTargets(Ogre::FrameEvent&)
Ogre::Root::createRenderQueueInvocationSequence(std::string const&)
Ogre::Root::getRenderQueueInvocationSequence(std::string const&)
Ogre::Root::destroyRenderQueueInvocationSequence(std::string const&)
Ogre::Root::destroyAllRenderQueueInvocationSequences()
Ogre::Root::getSingleton()
Ogre::Root::getSingletonPtr()
Ogre::Root::clearEventTimes()
Ogre::Root::setFrameSmoothingPeriod(float)
Ogre::Root::getFrameSmoothingPeriod() const
Ogre::Root::addMovableObjectFactory(Ogre::MovableObjectFactory*, bool)
Ogre::Root::removeMovableObjectFactory(Ogre::MovableObjectFactory*)
Ogre::Root::hasMovableObjectFactory(std::string const&) const
Ogre::Root::getMovableObjectFactory(std::string const&)
Ogre::Root::_allocateNextMovableObjectTypeFlag()
Ogre::Root::getMovableObjectFactoryIterator() const
Ogre::Root::getDisplayMonitorCount() const
Ogre::Root::getWorkQueue() const
Ogre::Root::setWorkQueue(Ogre::WorkQueue*)
Ogre::Root::setBlendIndicesGpuRedundant(bool)
Ogre::Root::isBlendIndicesGpuRedundant() const
Ogre::Root::setBlendWeightsGpuRedundant(bool)
Ogre::Root::isBlendWeightsGpuRedundant() const
*/
<|endoftext|>