I tried to describe my problem here Issue to resolve (c++ 11 concurrency) but I feel I need to provide a fuller example of what I'm trying to solve. So I'll put my actual code in this post with some un-relevant details intentionally omitted.
First, the class that represents song position (Class A from the old post):
class SongPosition
{
public:
SongPosition (uint8_t ticks = 0U, uint8_t beats = 0U, uint16_t measures = 0U)
: _ticks (ticks)
, _beats (beats)
, _measures (measures)
{}
uint8_t getTicks () const { return _ticks; }
uint8_t getBeats () const { return _beats; }
uint16_t getMeasures () const { return _measures; }
void resetTicks () { _ticks = 0U; }
void resetBeats () { _beats = 0U; }
void incrementTicks () { ++_ticks; }
void incrementBeats () { ++_beats; }
void incrementMeasures () { ++_measures; }
void decrementMeasures () { --_measures; }
private:
uint8_t _ticks;
uint8_t _beats;
uint16_t _measures;
};
Secondly, there is a ticker class which main purpose is to invoke on a separate thread a callback function on every tick:
class Ticker
{
public:
// Tickings interval type in nanoseconds
typedef std::chrono::nanoseconds interval_t;
// OnTickCallback type
typedef std::function<void()> on_tick_callback_t;
explicit Ticker (interval_t interval)
: _onTickCallback ()
, _interval (interval)
, _running (false)
{}
void setinterval (interval_t interval)
{
_interval = interval;
}
void setOnTickCallback (on_tick_callback_t onTickCallback)
{
_onTickCallback = onTickCallback;
}
// Starts the ticker
void start ()
{
if (_running) return;
_running = true;
std::thread trd (&Ticker::loop, this);
trd.detach();
}
// Stops the ticker
void stop () { _running = false; }
private:
on_tick_callback_t _onTickCallback; // OnTick callback, called every tick
std::atomic<interval_t> _interval; // Tick interval between every tick
std::atomic<bool> _running; // Ticker running flag
// Inner loop executed on a separate thread to produce ticks
void loop ()
{
while (_running) {
_onTickCallback();
std::this_thread::sleep_for( _interval.load() );
}
}
};
And finally, a class that will be living on ui thread:
class BeatClock
{
public:
BeatClock ()
: _bpm (120UL)
, _ticker (Ticker::kDefaultInterval)
, _songpos ()
, _precount ()
{
// The callback will be invoked on a separate thread by Ticker class!
_ticker.setOnTickCallback( [this] ()
{
_songpos.incrementTicks();
if (_songpos.getTicks() == 96U) {
_songpos.resetTicks();
_songpos.incrementBeats();
// And here I need to notify my gui about the change!!
if (_songpos.getBeats() == 4U) {
_songpos.resetBeats();
_songpos.incrementMeasures();
}
}
if (_precount == 0U) {
_precount = 4U;
}
--_precount;
} );
}
private:
uint64_t _bpm;
Ticker _ticker;
SongPosition _songpos;
uint8_t _precount;
};
The issues I have with this scenario:
_songpos
is modified from a non ui thread but should be used in the ui thread.- on
_songpos
modification, ui thread need to be notified about that.
Regards, Mike.
Aucun commentaire:
Enregistrer un commentaire