The function below is run on an std::thread that is detached. The code itself is written using the JUCE API (Hence Array<> object & MidiMessage).
void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle)
{
//for each group of messages (bar) within the bundle
for(int bar = 0; bar < messageBundle.size(); bar ++)
{
//store our message from the bundle for playback
Array<MidiMessage> messages;
messages.clear();
messages = messageBundle[bar];
//intialise start time
double timestart = Time::getMillisecondCounterHiRes();
//for each midi inside a single "gene"
for(int i = 0; i <= messages.size();)
{
double elapsedTime = Time::getMillisecondCounterHiRes() - timestart;
//output message whens appropriate
if(elapsedTime > messages[i].getTimeStamp())
{
//output this message
masterMidiOutput->sendMessageNow(messages[i]);
//increment through the array
i++;
}
}
}
}
I need the midi messages to be output in real time but without having to run through the loop condition so much that the CPU runs super hot.
Any ideas? I'm stuck for how to playback the messages in such an order that doesn't require constant checking with a timer.
Thanks in advance.
//=====================================================================
update trying to sleep the thread...
void triggerMidiMessages(Array<Array<MidiMessage>> messageBundle)
{
//for each group of messages (bar) within a bundle
for(int bar = 0; bar < messageBundle.size(); bar ++)
{
//store our message from the bundle for playback
Array<MidiMessage> messages;
messages.clear();
messages = messageBundle[bar];
}
//intialise start time
double previousTimeStamp = 0;
//for each midi inside a single "gene"
for(int i = 0; i <= messages.size();)
{
//fire off all note on messages
while(messages[i].isNoteOn())
{
masterMidiOutput->sendMessageNow(messages[i]);
i++; //increment to the next
}
//fire off all note off messages
while(!messages[i].isNoteOn())
{
masterMidiOutput->sendMessageNow(messages[i]);
i++; // do the next one
//if the next message is back to a note on command
if(messages[i+1].isNoteOn() == true)
{
//sleep for x amount of time
int sleepTime = messages[i].getTimeStamp() - previousTimeStamp;
std::this_thread::sleep_for(std::chrono::milliseconds(sleepTime));
previousTimeStamp = messages[i].getTimeStamp();
}
}
}
}
}
To stop the build up within the thread it is better to turn on and off a timer object and trigger each message one by one.
Broadcast messages (Action Broadcaster )can then be used to keep track of the index.
Here is some example code to give the general idea :
MIDIThing::MIDIThing ()
{
startTimer(1); //start a timer
}
void MIDIThing::start ()
{
playstate = 1;
startTime = Time::getCurrentTime().toMilliseconds();
}
void MIDIThing::timerCallback()
{
if (playstate == 1) {
Time::getMillisecondCounterHiRes();
int64 target;
if (Time::getCurrentTime().toMilliseconds() > target) {
//fire off the message
}
//ended (possibly on a condition)
ActionBroadcaster::sendActionMessage(FINISHED_PLAYBACK);
}
}
Related
Is there a function in C++ that delays the function it is running in for an amount of time, similar to WaitForSeconds in C#? I am aware of Sleep, but that pauses the entire program, I only want to pause a single function.
It depends on your programs architecture, if you let the function run on its own thread then yes you can use std::this_thread::sleep_for function to pause that function without affecting the whole program e.g.
void mythread()
{
int sum = 0;
for(int i = 0; i < 10; ++i)
{
std::this_thread::sleep_for(1s);
sum += i;
}
return sum;
}
int main()
{
std::future<int> result = new std::async(mythread);
// do something else
// ...
result.get();
}
In Qt 4.7 Reference for QThreadPool, we find:
void QThreadPool::releaseThread()
Releases a thread previously reserved by a call to reserveThread().
Note: Calling this function without previously reserving a thread
temporarily increases maxThreadCount(). This is useful when a thread
goes to sleep waiting for more work, allowing other threads to
continue. Be sure to call reserveThread() when done waiting, so that
the thread pool can correctly maintain the activeThreadCount().
See also reserveThread().
void QThreadPool::reserveThread()
Reserves one thread, disregarding activeThreadCount() and
maxThreadCount().
Once you are done with the thread, call releaseThread() to allow it to
be reused.
Note: This function will always increase the number of active threads.
This means that by using this function, it is possible for
activeThreadCount() to return a value greater than maxThreadCount().
See also releaseThread().
I want to use releaseThread() to make it possible to use nested concurrent map, but in the following code, it hangs in waitForFinished():
#include <QApplication>
#include <QMainWindow>
#include <QtConcurrentMap>
#include <QtConcurrentRun>
#include <QFuture>
#include <QThreadPool>
#include <QtTest/QTest>
#include <QFutureSynchronizer>
struct Task2 { // only calculation
typedef void result_type;
void operator()(int count) {
int k = 0;
for (int i = 0; i < count * 10; ++i) {
for (int j = 0; j < count * 10; ++j) {
k++;
}
}
assert(k >= 0);
}
};
struct Task1 { // will launch some other concurrent map
typedef void result_type;
void operator()(int count) {
QVector<int> vec;
for (int i = 0; i < 5; ++i) {
vec.push_back(i+count);
}
Task2 task;
QFuture<void> f = QtConcurrent::map(vec.begin(), vec.end(), task);
{
// with out releaseThread before wait, it will hang directly
QThreadPool::globalInstance()->releaseThread();
f.waitForFinished(); // BUG: may hang there
QThreadPool::globalInstance()->reserveThread();
}
}
};
int main() {
QThreadPool* gtpool = QThreadPool::globalInstance();
gtpool->setExpiryTimeout(50);
int count = 0;
for (;;) {
QVector<int> vec;
for (int i = 0; i < 40 ; i++) {
vec.push_back(i);
}
// launch a task with nested map
Task1 task; // Task1 will have nested concurrent map
QFuture<void> f = QtConcurrent::map(vec.begin(), vec.end(),task);
f.waitForFinished(); // BUG: may hang there
count++;
// waiting most of thread in thread pool expire
while (QThreadPool::globalInstance()->activeThreadCount() > 0) {
QTest::qSleep(50);
}
// launch a task only calculation
Task2 task2;
QFuture<void> f2 = QtConcurrent::map(vec.begin(), vec.end(), task2);
f2.waitForFinished(); // BUG: may hang there
qDebug() << count;
}
return 0;
}
This code will not run forever; it will hang in after many loops (1~10000), with all threads waiting for condition variable.
My questions are:
Why does it hang?
Can I fix it and keep the nested concurrent map?
dev env:
Linux version 2.6.32-696.18.7.el6.x86_64; Qt4.7.4; GCC 3.4.5
Windows 7; Qt4.7.4; mingw 4.4.0
The program hangs because of the race condition in QThreadPool when you try to deal with expiryTimeout. Here is the analysis in detail :
The problem in QThreadPool - source
When starting a task, QThreadPool did something along the lines of:
QMutexLocker locker(&mutex);
taskQueue.append(task); // Place the task on the task queue
if (waitingThreads > 0) {
// there are already running idle thread. They are waiting on the 'runnableReady'
// QWaitCondition. Wake one up them up.
waitingThreads--;
runnableReady.wakeOne();
} else if (runningThreadCount < maxThreadCount) {
startNewThread(task);
}
And the the thread's main loop looks like this:
void QThreadPoolThread::run()
{
QMutexLocker locker(&manager->mutex);
while (true) {
/* ... */
if (manager->taskQueue.isEmpty()) {
// no pending task, wait for one.
bool expired = !manager->runnableReady.wait(locker.mutex(),
manager->expiryTimeout);
if (expired) {
manager->runningThreadCount--;
return;
} else {
continue;
}
}
QRunnable *r = manager->taskQueue.takeFirst();
// run the task
locker.unlock();
r->run();
locker.relock();
}
}
The idea is that the thread will wait for a given amount of second for
a task, but if no task was added in a given amount of time, the thread
expires and is terminated. The problem here is that we rely on the
return value of runnableReady. If there is a task that is scheduled at
exactly the same time as the thread expires, then the thread will see
false and will expire. But the main thread will not restart any other
thread. That might let the application hang as the task will never be
run.
The quick workaround is to use a long expiryTime (30000 by default) and remove the while loop that waits for the threads expired.
Here is the main function modified, the program runs smoothly in Windows 7, 4 threads used by default :
int main() {
QThreadPool* gtpool = QThreadPool::globalInstance();
//gtpool->setExpiryTimeout(50); <-- don't set the expiry Timeout, use the default one.
qDebug() << gtpool->maxThreadCount();
int count = 0;
for (;;) {
QVector<int> vec;
for (int i = 0; i < 40 ; i++) {
vec.push_back(i);
}
// launch a task with nested map
Task1 task; // Task1 will have nested concurrent map
QFuture<void> f = QtConcurrent::map(vec.begin(), vec.end(),task);
f.waitForFinished(); // BUG: may hang there
count++;
/*
// waiting most of thread in thread pool expire
while (QThreadPool::globalInstance()->activeThreadCount() > 0)
{
QTest::qSleep(50);
}
*/
// launch a task only calculation
Task2 task2;
QFuture<void> f2 = QtConcurrent::map(vec.begin(), vec.end(), task2);
f2.waitForFinished(); // BUG: may hang there
qDebug() << count ;
}
return 0;
}
#tungIt's answer is good enough, I found the qtbug and fix commit, just for reference:
https://bugreports.qt.io/browse/QTBUG-3786
https://github.com/qt/qtbase/commit/a9b6a78e54670a70b96c122b10ad7bd64d166514#diff-6d5794cef91df41c39b5e7cc6b71d041
I had to create timelapse function to wait for X amount of time in a loop.
The following code checks the boolean value of m_abortTimeLapseThread but after running for an hour I noticed the execution time of this code created 10 seconds delay. Is there a way to check m_abortTimeLapseThread as frequently as possible and wait for X amount of time in the function without the kind of delay I observed ?
void Acquisition::TimeLapseCount() {
int max10msWaitTimes = m_timeLapseInMs / 10;
while (true) {
m_timeLapseImageSaved = true;
for (int i = 0; i < max10msWaitTimes; i++)
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
}
Thanks,
You could measure total time elapsed.
void Acquisition::TimeLapseCount() {
auto waitUntil = std::chrono::system_clock::now() + std::chrono::milliseconds(m_timeLapseInMs);
while (true) {
m_timeLapseImageSaved = true;
while (waitUntil > std::chrono::system_clock::now())
{
if (m_abortTimeLapseThread) {
return;
}
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
waitUntil += std::chrono::milliseconds(m_timeLapseInMs);
}
}
I have n number of jobs, which there is no shared resource between them, and mthreads. I want to efficiently divide number of jobs in threads in such a way that there is no idle thread untill everything is processed?
This is a prototype of my program:
class Job {
//constructor and other stuff
//...
public: doWork();
};
struct JobParams{
int threadId;
Job job;
};
void* doWorksOnThread(void* job) {
JobParams* j = // cast argument
cout << "Thread #" << j->threadId << " started" << endl;
j->job->doWork();
return (void*)0;
}
Then in my main file I have something like:
int main() {
vector<Job> jobs; // lets say it has 17 jobs
int numThreads = 4;
pthread_t* threads = new pthread_t[numThreads];
JobParams* jps = new JubParams[jobs.size()];
for(int i = 0; i < jobs.size(); i++) {
jps[i]->job = jobs[i];
}
for(int i = 0; i < numThread; i++) {
pthread_create(&t[i], null, doWorkOnThread, &jps[0])
}
//another for loop and call join on 4 threads...
return 0;
}
how can I efficiently make sure that there is no idle thread until all jobs are completed?
You'll need to add a loop to identify the threads that completed and then start new ones, making sure you always have up to 4 threads running.
Here is a very basic way to do that. Using a sleep as proposed could be a good start and will do the job (even if adding an extra delay before you'll figure out the last thread completed). Ideally, you should use a condition variable notified by the thread when job is done to wake up the main loop (then sleep instruction would be replaced by a wait condition instruction).
struct JobParams{
int threadId;
Job job;
std::atomic<bool> done; // flag to know when job is done, could also be an attribute of Job class!
};
void* doWorksOnThread(void* job) {
JobParams* j = // cast argument
cout << "Thread #" << j->threadId << " started" << endl;
j->job->doWork();
j->done = true; // signal job completed
return (void*)0;
}
int main() {
....
std::map<JobParams*,pthread_t*> runningThreads; // to keep track of running jobs
for(int i = 0; i < jobs.size(); i++) {
jps[i]->job = jobs[i];
jps[i]->done = false; // mark as not done yet
}
while ( true )
{
vector<JobParams*> todo;
for( int i = 0; i < jobs.size(); i++ )
{
if ( !jps[i]->done )
{
if ( runningThreads.find(jps[i]) == runningThreads.end() )
todo.push_back( &jps[i] ); // job not started yet, mask as to be done
// else, a thread is already processing the job and did not complete it yet
}
else
{
if ( runningThreads.find(jps[i]) != runningThreads.end() )
{
// thread just completed the job!
// let's join to wait for the thread to end cleanly
// I'm not familiar with pthread, hope this is correct
void* res;
pthread_join(runningThreads[jps[i]], &res);
runningThreads.erase(jps[i]); // not running anymore
}
// else, job was already done and thread joined from a previous iteration
}
}
if ( todo.empty() && runningThreads.empty() )
break; // done all jobs
// some jobs remain undone
if ( runningThreads.size() < numThreads && !todo.empty() )
{
// some new threads shall be started...
int newThreadsToBeCreatedCount = numThreads - runningThreads.size();
// make sure you don't end up with too many threads running
if ( todo.size() > newThreadsToBeCreatedCount )
todo.resize( newThreadsToBeCreatedCount );
for ( auto jobParam : todo )
{
pthread_t* thread = runningThreads[&jobParam];
pthread_create(thread, null, doWorkOnThread, &jobParam );
}
}
// else: you already have 4 runnign jobs
// sanity check that everything went as expected:
assert( runningThreads.size() <= numThreads );
msleep( 100 ); // give a chance for some jobs to complete (100ms)
// adjust sleep duration if necessary
}
}
Note: I'm not very familiar with pthread. Hope the syntax is correct.
I am creating a program that reads in data about fireworks from an XML file (such as type, colour, time in milliseconds it launches and how long it lasts for etc). This then displays the fireworks display using openGL in a loop.
My approach to this is to have a manager class, that takes in a vector of the xml read fireworks and moves them between 3 different vectors: inactiveFireworks (those that are yet to fire), activeFireworks (those that need to be animated) and depletedFireworks (those that will be pushed back to inactiveFireworks when the display is run).
To check to see if a firework needs to be fired, I need to work out the difference between the time the firework manager was called and the current time of the program and multiply that by 1000 to get milliseconds.
eg: if a firework is due to fire at 3000, it will be called 3 seconds in to the existence of the fire work manager.
Unfortunately, I get an unhandled exception error at this point and I'm not sure why...
timeDifference = difftime(time(¤tTime),initTime) * 1000;
here is the header file:
#ifndef FWORKMANAGER_H
#define FWORKMANAGER_H
#include <Time.h>
#include <vector>
#include "firework.h"
class fworkManager
{
private:
time_t initTime;
time_t currentTime;
double timeDifference;
std::vector<firework*> inactiveFireworks;
std::vector<firework*> activeFireworks;
std::vector<firework*> depletedFireworks;
public:
fworkManager(std::vector<firework*> fListIn);
void drawAllFireworks();
void evolve();
void fireInactiveFireworks();
void moveActiveFireworks();
void moveDepletedFireworks();
void reset();
};
#endif
And here is the CPP.
#include <vector>
#include "LUtil.h"
#include "fworkManager.h"
fworkManager :: fworkManager(std::vector<firework*> fListIn){
inactiveFireworks = fListIn;
time (&initTime);
}
//animates fireworks
void fworkManager::evolve(){
//check time against inactiveFireworks
fireInactiveFireworks();
moveActiveFireworks();
moveDepletedFireworks();
reset();
}
//draws fireworks as they come up
void fworkManager::drawAllFireworks()
{
std::vector<firework*>::iterator i;
for(i=activeFireworks.begin(); i != activeFireworks.end(); i ++)
{
(*i) -> draw();
}
}
//if fireworks are ready to fire, push them to active list
void fworkManager::fireInactiveFireworks()
{
timeDifference = difftime(time(¤tTime),initTime) * 1000;
std::vector<firework*>::iterator i;
for(i = inactiveFireworks.begin(); i != inactiveFireworks.end();)
{
if((*i) -> getBegin() <= timeDifference)
{
activeFireworks.push_back(*i);
(*i) -> explode();
i = inactiveFireworks.erase(i);
}else{
++i;
}
}
}
//animate each firework in the active list
void fworkManager::moveActiveFireworks()
{
std::vector<firework*>::iterator i;
for(i = activeFireworks.begin(); i != activeFireworks.end(); i++)
{
(*i) -> evolve();
}
}
//move fireworks that have met their duration requirement to the depleted list.
void fworkManager::moveDepletedFireworks()
{
std::vector<firework*>::iterator i;
for(i = activeFireworks.begin(); i != activeFireworks.end();)
{
if((*i) -> getLifeSpan() >= (*i) -> getDuration() )
{
depletedFireworks.push_back(*i);
i = activeFireworks.erase(i);
}else{
++i;
}
}
}
//repopulates the inactive firework list and resets the time difference. Allows animation to loop.
void fworkManager::reset()
{
if(inactiveFireworks.empty() && activeFireworks.empty())
{
time (&initTime);
std::vector<firework*>::iterator i;
for(i=depletedFireworks.begin(); i != depletedFireworks.end();)
{
(*i) -> reset();
inactiveFireworks.push_back(*i);
i = depletedFireworks.erase(i);
}
}
}
Many Thanks for any insight offered.