mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
New class: HighResolutionTimer
This commit is contained in:
parent
2f3dd2261a
commit
359be4dc0c
7 changed files with 321 additions and 14 deletions
|
|
@ -421,16 +421,6 @@ public:
|
|||
|
||||
bool open()
|
||||
{
|
||||
#if JUCE_WINDOWS
|
||||
static bool timePeriodSet = false;
|
||||
|
||||
if (! timePeriodSet)
|
||||
{
|
||||
timePeriodSet = true;
|
||||
timeBeginPeriod (2);
|
||||
}
|
||||
#endif
|
||||
|
||||
pluginName = file.getFileNameWithoutExtension();
|
||||
|
||||
module.open (file.getFullPathName());
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@
|
|||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
#include <xlocale.h>
|
||||
#include <mach/mach.h>
|
||||
#endif
|
||||
|
||||
#if JUCE_ANDROID
|
||||
|
|
@ -91,9 +92,6 @@
|
|||
namespace juce
|
||||
{
|
||||
|
||||
// START_AUTOINCLUDE containers/*.cpp, files/*.cpp, json/*.cpp, logging/*.cpp, maths/*.cpp,
|
||||
// memory/*.cpp, misc/*.cpp, network/*.cpp, streams/*.cpp, system/*.cpp, text/*.cpp, threads/*.cpp,
|
||||
// time/*.cpp, unit_tests/*.cpp, xml/*.cpp, zip/juce_GZIPD*.cpp, zip/juce_GZIPC*.cpp, zip/juce_Zip*.cpp
|
||||
#include "containers/juce_AbstractFifo.cpp"
|
||||
#include "containers/juce_DynamicObject.cpp"
|
||||
#include "containers/juce_NamedValueSet.cpp"
|
||||
|
|
@ -148,7 +146,6 @@ namespace juce
|
|||
#include "zip/juce_GZIPDecompressorInputStream.cpp"
|
||||
#include "zip/juce_GZIPCompressorOutputStream.cpp"
|
||||
#include "zip/juce_ZipFile.cpp"
|
||||
// END_AUTOINCLUDE
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
|
|
@ -197,4 +194,7 @@ namespace juce
|
|||
#include "native/juce_android_Threads.cpp"
|
||||
|
||||
#endif
|
||||
|
||||
#include "threads/juce_HighResolutionTimer.cpp"
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,6 +376,9 @@ namespace juce
|
|||
#ifndef __JUCE_DYNAMICLIBRARY_JUCEHEADER__
|
||||
#include "threads/juce_DynamicLibrary.h"
|
||||
#endif
|
||||
#ifndef __JUCE_HIGHRESOLUTIONTIMER_JUCEHEADER__
|
||||
#include "threads/juce_HighResolutionTimer.h"
|
||||
#endif
|
||||
#ifndef __JUCE_INTERPROCESSLOCK_JUCEHEADER__
|
||||
#include "threads/juce_InterProcessLock.h"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1119,3 +1119,140 @@ bool ChildProcess::kill()
|
|||
{
|
||||
return activeProcess == nullptr || activeProcess->killProcess();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct HighResolutionTimer::Pimpl
|
||||
{
|
||||
Pimpl (HighResolutionTimer& t) : owner (t), thread (0), shouldStop (false)
|
||||
{
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
jassert (thread == 0);
|
||||
}
|
||||
|
||||
void start (int newPeriod)
|
||||
{
|
||||
periodMs = newPeriod;
|
||||
|
||||
if (thread == 0)
|
||||
{
|
||||
shouldStop = false;
|
||||
|
||||
if (pthread_create (&thread, nullptr, timerThread, this) == 0)
|
||||
setThreadToRealtime (thread, newPeriod);
|
||||
else
|
||||
jassertfalse;
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (thread != 0)
|
||||
{
|
||||
shouldStop = true;
|
||||
|
||||
while (thread != 0 && thread != pthread_self())
|
||||
Thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
HighResolutionTimer& owner;
|
||||
int volatile periodMs;
|
||||
|
||||
private:
|
||||
pthread_t thread;
|
||||
bool volatile shouldStop;
|
||||
|
||||
static void* timerThread (void* param)
|
||||
{
|
||||
int dummy;
|
||||
pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, &dummy);
|
||||
|
||||
reinterpret_cast<Pimpl*> (param)->timerThread();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void timerThread()
|
||||
{
|
||||
Clock clock (periodMs);
|
||||
|
||||
while (! shouldStop)
|
||||
{
|
||||
clock.wait();
|
||||
owner.hiResTimerCallback();
|
||||
}
|
||||
|
||||
periodMs = 0;
|
||||
thread = 0;
|
||||
}
|
||||
|
||||
struct Clock
|
||||
{
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
Clock (double millis)
|
||||
{
|
||||
mach_timebase_info_data_t timebase;
|
||||
(void) mach_timebase_info (&timebase);
|
||||
delta = (((uint64_t) (millis * 1000000.0)) * timebase.numer) / timebase.denom;
|
||||
time = mach_absolute_time();
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
time += delta;
|
||||
mach_wait_until (time);
|
||||
}
|
||||
|
||||
uint64_t time, delta;
|
||||
|
||||
#else
|
||||
Clock (double millis)
|
||||
: delta ((int64) (millis * 1000000))
|
||||
{
|
||||
struct timespec t;
|
||||
clock_gettime (CLOCK_MONOTONIC, &t);
|
||||
time = 1000000000 * (int64) t.tv_sec + t.tv_nsec;
|
||||
}
|
||||
|
||||
void wait()
|
||||
{
|
||||
time += delta;
|
||||
|
||||
struct timespec t;
|
||||
t.tv_sec = (time_t) (time / 1000000000);
|
||||
t.tv_nsec = (long) (time % 1000000000);
|
||||
|
||||
clock_nanosleep (CLOCK_MONOTONIC, TIMER_ABSTIME, &t, nullptr);
|
||||
}
|
||||
|
||||
int64 time, delta;
|
||||
#endif
|
||||
};
|
||||
|
||||
static bool setThreadToRealtime (pthread_t thread, uint64 periodMs)
|
||||
{
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
thread_time_constraint_policy_data_t policy;
|
||||
policy.period = (uint32_t) (periodMs * 1000000);
|
||||
policy.computation = 50000;
|
||||
policy.constraint = policy.period;
|
||||
policy.preemptible = true;
|
||||
|
||||
return thread_policy_set (pthread_mach_thread_np (thread),
|
||||
THREAD_TIME_CONSTRAINT_POLICY,
|
||||
(thread_policy_t) &policy,
|
||||
THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;
|
||||
|
||||
#else
|
||||
(void) periodMs;
|
||||
struct sched_param param;
|
||||
param.sched_priority = sched_get_priority_max (SCHED_RR);
|
||||
return pthread_setschedparam (thread, SCHED_RR, ¶m) == 0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (Pimpl)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -582,3 +582,55 @@ bool ChildProcess::kill()
|
|||
{
|
||||
return activeProcess == nullptr || activeProcess->killProcess();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct HighResolutionTimer::Pimpl
|
||||
{
|
||||
Pimpl (HighResolutionTimer& t) noexcept : owner (t), periodMs (0)
|
||||
{
|
||||
}
|
||||
|
||||
~Pimpl()
|
||||
{
|
||||
jassert (periodMs == 0);
|
||||
}
|
||||
|
||||
void start (int newPeriod)
|
||||
{
|
||||
if (newPeriod != periodMs)
|
||||
{
|
||||
stop();
|
||||
periodMs = newPeriod;
|
||||
|
||||
TIMECAPS tc;
|
||||
if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR)
|
||||
{
|
||||
const int actualPeriod = jlimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod);
|
||||
|
||||
timerID = timeSetEvent (actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this,
|
||||
TIME_PERIODIC | TIME_CALLBACK_FUNCTION | TIME_KILL_SYNCHRONOUS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
periodMs = 0;
|
||||
timeKillEvent (timerID);
|
||||
}
|
||||
|
||||
HighResolutionTimer& owner;
|
||||
int periodMs;
|
||||
|
||||
private:
|
||||
unsigned int timerID;
|
||||
|
||||
static void __stdcall callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR)
|
||||
{
|
||||
if (Pimpl* const timer = reinterpret_cast<Pimpl*> (userInfo))
|
||||
if (timer->periodMs != 0)
|
||||
timer->owner.hiResTimerCallback();
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (Pimpl)
|
||||
};
|
||||
|
|
|
|||
33
modules/juce_core/threads/juce_HighResolutionTimer.cpp
Normal file
33
modules/juce_core/threads/juce_HighResolutionTimer.cpp
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE 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 General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
HighResolutionTimer::HighResolutionTimer() { pimpl = new Pimpl (*this); }
|
||||
HighResolutionTimer::~HighResolutionTimer() { stopTimer(); }
|
||||
|
||||
void HighResolutionTimer::startTimer (int periodMs) { pimpl->start (jmax (1, periodMs)); }
|
||||
void HighResolutionTimer::stopTimer() { pimpl->stop(); }
|
||||
|
||||
bool HighResolutionTimer::isTimerRunning() const noexcept { return pimpl->periodMs != 0; }
|
||||
int HighResolutionTimer::getTimerInterval() const noexcept { return pimpl->periodMs; }
|
||||
92
modules/juce_core/threads/juce_HighResolutionTimer.h
Normal file
92
modules/juce_core/threads/juce_HighResolutionTimer.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-11 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE 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 General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_HIGHRESOLUTIONTIMER_JUCEHEADER__
|
||||
#define __JUCE_HIGHRESOLUTIONTIMER_JUCEHEADER__
|
||||
|
||||
class JUCE_API HighResolutionTimer
|
||||
{
|
||||
protected:
|
||||
/** Creates a HighResolutionTimer.
|
||||
When created, the timer is stopped, so use startTimer() to get it going.
|
||||
*/
|
||||
HighResolutionTimer();
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~HighResolutionTimer();
|
||||
|
||||
//==============================================================================
|
||||
/** The user-defined callback routine that actually gets called periodically.
|
||||
|
||||
This will be called on a dedicated timer thread, so make sure your
|
||||
implementation is thread-safe!
|
||||
|
||||
It's perfectly ok to call startTimer() or stopTimer() from within this
|
||||
callback to change the subsequent intervals.
|
||||
*/
|
||||
virtual void hiResTimerCallback() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Starts the timer and sets the length of interval required.
|
||||
|
||||
If the timer is already started, this will reset its counter, so the
|
||||
time between calling this method and the next timer callback will not be
|
||||
less than the interval length passed in.
|
||||
|
||||
@param intervalInMilliseconds the interval to use (any values less than 1 will be
|
||||
rounded up to 1)
|
||||
*/
|
||||
void startTimer (int intervalInMilliseconds);
|
||||
|
||||
/** Stops the timer.
|
||||
|
||||
This method may block while it waits for pending callbacks to complete. Once it
|
||||
returns, no more callbacks will be made. If it is called from the timer's own thread,
|
||||
it will cancel the timer after the current callback returns.
|
||||
*/
|
||||
void stopTimer();
|
||||
|
||||
/** Checks if the timer has been started.
|
||||
@returns true if the timer is running.
|
||||
*/
|
||||
bool isTimerRunning() const noexcept;
|
||||
|
||||
/** Returns the timer's interval.
|
||||
@returns the timer's interval in milliseconds if it's running, or 0 if it's not.
|
||||
*/
|
||||
int getTimerInterval() const noexcept;
|
||||
|
||||
private:
|
||||
struct Pimpl;
|
||||
friend struct Pimpl;
|
||||
friend class ScopedPointer<Pimpl>;
|
||||
ScopedPointer<Pimpl> pimpl;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HighResolutionTimer)
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_HIGHRESOLUTIONTIMER_JUCEHEADER__
|
||||
Loading…
Add table
Add a link
Reference in a new issue