TimeSliceClient and TimeSliceThread


#1

I want to use the TimeSliceThread and TimeSliceClient classes to create a kind of “system timer” which regularly updates some objects (im assuming this is how these classes are used).

So, I’ve started a little test app to work things out and have come across some problems.

I have a custom widget which inherits Component, ButtonListener, ChangeListener, and TimeSliceClient. I have implemented useTimeSlice().
I then create a TimeSliceThread in another component, and call addTimeSliceClient().

Here is pretty much how I setup the TimeSliceThread:

mTimeSliceThread = new TimeSliceThread();
mTimeSliceThread->addTimeSliceClient((TimeSliceClient*const)mMetronome);
mTimeSliceThread->startThread();

This is what my MetronomeWidget class looks like:

class MetronomeWidget : public Component,
                        public ButtonListener,
                        public ChangeListener,
                        public TimeSliceClient
{
[...]

And this is my implementation of useTimeSlice():

bool useTimeSlice()
{
    return false;
}

When I compile and run this code, using visual c++ and debug settings, I get a run-time exception:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

It then opens juice_timeslicethread.cpp and points to line 132:

             if (clientBeingCalled->useTimeSlice())

Here is a zip of the complete project http://www.puresimplicity.net/~ldb/hacks/juce/SoundMachine.zip

Any help would be greatly appreciated! I have a feeling im probably doing something really stupid, I just cant see what at the moment.

Levi


#2

Nevermind, I appear to have solved my problems.

useTimeSlice() is getting called from my MetronomeWidget now. I also had to pepper it with a couple MessageManagerLocks.

I hate threads.


#3

Are you sure you need to use a thread? I’ve not looked at your project, but if you’re just making things tick, isn’t the Timer class enough?

The TimeSliceThread’s really for running a continuous background process that works its way through a set of tasks.


#4

[quote=“jules”]Are you sure you need to use a thread? I’ve not looked at your project, but if you’re just making things tick, isn’t the Timer class enough?

The TimeSliceThread’s really for running a continuous background process that works its way through a set of tasks.[/quote]

I just needed a way to tell gui objects to update themselves. I ended up using a class derived from Thread and ActionBroadcaster that looks like this:

class GuiUpdateThread : public Thread, public ActionBroadcaster
{
public:
    GuiUpdateThread(int updateInterval = 33)
        : mUpdateInterval(updateInterval)
    {
    }

    ~GuiUpdateThread()
    {
        stopThread(2000);
    }

    void setUpdateInterval(int updateInterval)
    {
        mUpdateInterval = updateInterval;
    }

    void run()
    {
        while (!threadShouldExit())
        {
            sendActionMessage(T("GuiUpdateThread::Update"));
            wait(mUpdateInterval);
        }
    }

private:
    int mUpdateInterval;
};

I subclass ActionListener in my components, then add the component to GuiUpdateThread with GuiUpdateThread::addActionListener().

This peice of code seems to work exactly the way I want:

void actionListenerCallback(const String& message)
{
    if (message == T("GuiUpdateThread::Update"))
    {
        int curTime = Time::getApproximateMillisecondCounter();
        mTimeLabel->setText(String::formatted(T("%d"), curTime), false);
    } 
}

Does that make sense? Or, am I doing something completely assinine (im pretty crappy with thread programming!)

Thanks!


#5

Jeez… that’s the most convoluted thing I’ve ever seen!

try this:

class MyTimer  : public Timer
{
    MyTimer()
    {
        startTimer (2000);
    }

    void timerCallback()
    {
        timeLabel->setText (...etc)
    }
};

No threads, no locks, no messing about.


#6

[quote=“jules”]Jeez… that’s the most convoluted thing I’ve ever seen!
[/quote]

I don’t know if I should laugh or cry. =)

Anyway, yeah, it seems like im doing more than is necessary. A long time ago I hacked a little on the Muse sequencer for Linux, and it was heavily threaded. The mechanics of updating the user interface were similar to my approach, which is where I got the idea in the first place.
At least I think it was similar (it’s been a while).

My rationale behind such an approach was that I could:
[list]

  1. Control the update frequency of the user interface thread;
  2. Control the scheduling priority of the user interface thread;
  3. Do all this at run-time.
    [/list]

I figured since im sending messages via the message queue that I dont have to do any locking – is this a naive approach?

Another thing I was worried about was, yeah, I can tell my thread to update every 33ms, but since im sending messages via message queue, just how precise will the updating be? But, in the case of gui objects, im not too concerned with the precision of the timing.

Levi


#7

yes, sending messages is thread-safe, but for GUI programming you should avoid threads wherever possible - Timers are accurate to about 10ms, and messages will arrive very quickly if it’s not busy doing a slow repaint or something.


#8

you are right, using Timer is better. i was trying to be way too clever.


#9