[beast: 24/95] BSE: add TickStamp class, use Bse::TickStamp instead of old gsl API
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 24/95] BSE: add TickStamp class, use Bse::TickStamp instead of old gsl API
- Date: Mon, 25 Mar 2013 00:38:31 +0000 (UTC)
commit f357e41f30fb6d31026565ae9db33236ce30f454
Author: Tim Janik <timj gnu org>
Date: Sat Mar 16 19:54:51 2013 +0100
BSE: add TickStamp class, use Bse::TickStamp instead of old gsl API
bse/bseengine.cc | 26 ++++----
bse/bseenginemaster.cc | 26 ++++----
bse/bseenginenode.hh | 2 +-
bse/bseengineschedule.cc | 4 +-
bse/bseengineutils.cc | 4 +-
bse/bsepcmdevice-null.cc | 2 +-
bse/bseprobe.cc | 4 +-
bse/bseproject.cc | 2 +-
bse/bsesequencer.cc | 40 ++++++-----
bse/bsesequencer.hh | 9 ++-
bse/bsesong.proc | 2 +-
bse/bsewaveosc.cc | 2 +-
bse/gslcommon.cc | 173 ++++++++++++++++++++++++++++++++--------------
bse/gslcommon.hh | 57 +++++++++++----
14 files changed, 231 insertions(+), 122 deletions(-)
---
diff --git a/bse/bseengine.cc b/bse/bseengine.cc
index 10e37c1..0084f52 100644
--- a/bse/bseengine.cc
+++ b/bse/bseengine.cc
@@ -69,9 +69,9 @@ bse_module_new (const BseModuleClass *klass,
* @return the module's tick stamp, indicating its process status
*
* Any thread may call this function on a valid engine module.
- * The module specific tick stamp is updated to gsl_tick_stamp() +
+ * The module specific tick stamp is updated to Bse::TickStamp::current() +
* @a n_values every time its BseProcessFunc() function was
- * called. See also gsl_tick_stamp().
+ * called. See also Bse::TickStamp::current().
* This function is MT-safe and may be called from any thread.
*/
guint64
@@ -499,7 +499,7 @@ bse_job_flow_access (BseModule *module,
BseJob *job;
g_return_val_if_fail (module != NULL, NULL);
g_return_val_if_fail (ENGINE_MODULE_IS_VIRTUAL (module) == FALSE, NULL);
- g_return_val_if_fail (tick_stamp < GSL_MAX_TICK_STAMP, NULL);
+ g_return_val_if_fail (tick_stamp < Bse::TickStamp::max_stamp(), NULL);
g_return_val_if_fail (access_func != NULL, NULL);
EngineTimedJob *tjob = (EngineTimedJob*) g_malloc0 (sizeof (tjob->access));
tjob->type = ENGINE_JOB_FLOW_JOB;
@@ -540,7 +540,7 @@ bse_job_boundary_access (BseModule *module,
BseJob *job;
g_return_val_if_fail (module != NULL, NULL);
g_return_val_if_fail (ENGINE_MODULE_IS_VIRTUAL (module) == FALSE, NULL);
- g_return_val_if_fail (tick_stamp < GSL_MAX_TICK_STAMP, NULL);
+ g_return_val_if_fail (tick_stamp < Bse::TickStamp::max_stamp(), NULL);
g_return_val_if_fail (access_func != NULL, NULL);
EngineTimedJob *tjob = (EngineTimedJob*) g_malloc0 (sizeof (tjob->access));
tjob->type = ENGINE_JOB_BOUNDARY_JOB;
@@ -609,7 +609,7 @@ bse_job_suspend_now (BseModule *module)
BseJob *job = sfi_new_struct0 (BseJob, 1);
job->job_id = ENGINE_JOB_SUSPEND;
job->tick.node = ENGINE_NODE (module);
- job->tick.stamp = GSL_MAX_TICK_STAMP;
+ job->tick.stamp = Bse::TickStamp::max_stamp();
return job;
}
/**
@@ -633,7 +633,7 @@ bse_job_resume_at (BseModule *module,
{
g_return_val_if_fail (module != NULL, NULL);
g_return_val_if_fail (ENGINE_MODULE_IS_VIRTUAL (module) == FALSE, NULL);
- g_return_val_if_fail (tick_stamp < GSL_MAX_TICK_STAMP, NULL);
+ g_return_val_if_fail (tick_stamp < Bse::TickStamp::max_stamp(), NULL);
BseJob *job = sfi_new_struct0 (BseJob, 1);
job->job_id = ENGINE_JOB_RESUME;
job->tick.node = ENGINE_NODE (module);
@@ -863,7 +863,7 @@ bse_trans_merge (BseTrans *trans1,
* Close the transaction and commit it to the engine. The engine
* will execute the jobs contained in this transaction as soon as
* it has completed its current processing cycle, at which point
- * gsl_tick_stamp() matches the returned tick stamp.
+ * Bse::TickStamp::current() matches the returned tick stamp.
* The jobs will be executed in the exact order they were added
* to the transaction.
* This function is MT-safe and may be called from any thread.
@@ -930,7 +930,7 @@ bse_trans_commit_delayed (BseTrans *trans,
{
g_return_if_fail (trans != NULL);
g_return_if_fail (trans->comitted == FALSE);
- if (tick_stamp <= gsl_tick_stamp ())
+ if (tick_stamp <= Bse::TickStamp::current())
bse_trans_commit (trans);
else
{
@@ -1110,7 +1110,7 @@ guint bse_engine_exvar_control_mask = 0;
* @a sample_freq. It determines how often control values are to be
* checked when calculating blocks of sample values.
* The block size determines the amount by which the global tick
- * stamp (see gsl_tick_stamp()) is updated everytime the whole
+ * stamp (see Bse::TickStamp::current()) is updated everytime the whole
* module network completed processing block size values.
* This function is MT-safe and may be called prior to engine initialization.
*/
@@ -1228,8 +1228,8 @@ bse_engine_configure (guint latency_ms,
bse_engine_exvar_sample_freq = sample_freq;
bse_engine_exvar_control_mask = control_raster - 1;
/* fixup timer */
- _gsl_tick_stamp_set_leap (bse_engine_block_size());
- _gsl_tick_stamp_inc (); /* ensure stamp validity (>0 and systime mark) */
+ Bse::TickStamp::_set_leap (bse_engine_block_size());
+ Bse::TickStamp::_increment(); // ensure stamp validity (>0 and systime mark)
success = TRUE;
}
/* unblock master */
@@ -1380,7 +1380,7 @@ bse_engine_get_threads (guint *n_threads)
guint64
bse_engine_tick_stamp_from_systime (guint64 systime)
{
- GslTickStampUpdate ustamp = gsl_tick_stamp_last ();
+ Bse::TickStamp::Update ustamp = Bse::TickStamp::get_last ();
guint64 tick_stamp;
/* FIXME: we should add special guards here
* for sfi_time_system() - ustamp.system_time ~> (44100 / bse_engine_block_size ())
@@ -1407,7 +1407,7 @@ bse_engine_tick_stamp_from_systime (guint64 systime)
" last-update-systime = %llu\n"
" last-update-tickstamp = %llu\n"
" sample-freq = %u\n",
- tick_stamp, systime, sfi_time_system (), gsl_tick_stamp (),
+ tick_stamp, systime, sfi_time_system (), Bse::TickStamp::get_current (),
ustamp.system_time, ustamp.tick_stamp,
bse_engine_sample_freq ());
#endif
diff --git a/bse/bseenginemaster.cc b/bse/bseenginemaster.cc
index ccb76f2..c2f4abf 100644
--- a/bse/bseenginemaster.cc
+++ b/bse/bseenginemaster.cc
@@ -238,7 +238,7 @@ node_peek_flow_job_stamp (EngineNode *node)
EngineTimedJob *tjob = node->flow_jobs;
if (UNLIKELY (tjob != NULL))
return tjob->tick_stamp;
- return GSL_MAX_TICK_STAMP;
+ return Bse::TickStamp::max_stamp();
}
static inline guint64
node_peek_boundary_job_stamp (EngineNode *node)
@@ -246,7 +246,7 @@ node_peek_boundary_job_stamp (EngineNode *node)
EngineTimedJob *tjob = node->boundary_jobs;
if (UNLIKELY (tjob != NULL))
return tjob->tick_stamp;
- return GSL_MAX_TICK_STAMP;
+ return Bse::TickStamp::max_stamp();
}
/* --- job processing --- */
static void
@@ -281,7 +281,7 @@ master_process_job (BseJob *job)
_engine_mnl_integrate (node);
if (ENGINE_NODE_IS_CONSUMER (node))
add_consumer (node);
- node->counter = GSL_TICK_STAMP;
+ node->counter = Bse::TickStamp::current();
NODE_FLAG_RECONNECT (node);
node->local_active = 0; /* by default not suspended */
node->update_suspend = TRUE;
@@ -334,10 +334,10 @@ master_process_job (BseJob *job)
}
else
_engine_mnl_remove (node);
- node->counter = GSL_MAX_TICK_STAMP;
+ node->counter = Bse::TickStamp::max_stamp();
/* nuke pending timed jobs */
do
- tjob = node_pop_flow_job (node, GSL_MAX_TICK_STAMP);
+ tjob = node_pop_flow_job (node, Bse::TickStamp::max_stamp());
while (tjob);
/* nuke probe jobs */
if (node->probe_jobs)
@@ -353,7 +353,7 @@ master_process_job (BseJob *job)
/* nuke boundary jobs */
if (node->boundary_jobs)
do
- tjob = node_pop_boundary_job (node, GSL_MAX_TICK_STAMP, sfi_ring_find (boundary_node_list, node));
+ tjob = node_pop_boundary_job (node, Bse::TickStamp::max_stamp(), sfi_ring_find
(boundary_node_list, node));
while (tjob);
_engine_node_collect_jobs (node);
break;
@@ -483,14 +483,14 @@ master_process_job (BseJob *job)
node = job->data.node;
JOB_DEBUG ("reset(%p)", node);
g_return_if_fail (node->integrated == TRUE);
- node->counter = GSL_TICK_STAMP;
+ node->counter = Bse::TickStamp::current();
node->needs_reset = TRUE;
break;
case ENGINE_JOB_ACCESS:
node = job->access.node;
JOB_DEBUG ("access node(%p): %p(%p)", node, job->access.access_func, job->access.data);
g_return_if_fail (node->integrated == TRUE);
- node->counter = GSL_TICK_STAMP;
+ node->counter = Bse::TickStamp::current();
job->access.access_func (&node->module, job->access.data);
break;
case ENGINE_JOB_PROBE_JOB:
@@ -632,8 +632,8 @@ master_tick_stamp_inc (void)
{
Timer *timer, *last = NULL;
guint64 new_stamp;
- _gsl_tick_stamp_inc ();
- new_stamp = GSL_TICK_STAMP;
+ Bse::TickStamp::_increment();
+ new_stamp = Bse::TickStamp::current();
timer = master_timer_list;
while (timer)
{
@@ -743,7 +743,7 @@ static void
master_process_locked_node (EngineNode *node,
guint n_values)
{
- const guint64 current_stamp = GSL_TICK_STAMP;
+ const guint64 current_stamp = Bse::TickStamp::current();
guint64 next_counter, new_counter, final_counter = current_stamp + n_values;
guint i, j, diff;
bool needs_probe_reset = node->probe_jobs != NULL;
@@ -820,7 +820,7 @@ static gboolean gsl_profile_modules = 0; /* set to 1 in gdb to get profile outpu
static void
master_process_flow (void)
{
- const guint64 current_stamp = GSL_TICK_STAMP;
+ const guint64 current_stamp = Bse::TickStamp::current();
guint n_values = bse_engine_block_size();
guint64 final_counter = current_stamp + n_values;
guint64 profile_maxtime = 0;
@@ -981,7 +981,7 @@ _engine_master_check (const BseEngineLoop *loop)
void
_engine_master_dispatch_jobs (void)
{
- const guint64 current_stamp = GSL_TICK_STAMP;
+ const guint64 current_stamp = Bse::TickStamp::current();
guint64 last_block_tick = current_stamp + bse_engine_block_size() - 1;
BseJob *job = _engine_pop_job (boundary_node_list == NULL);
/* here, we have to process _all_ pending jobs in a row. a popped job
diff --git a/bse/bseenginenode.hh b/bse/bseenginenode.hh
index dac9e2e..3372bcc 100644
--- a/bse/bseenginenode.hh
+++ b/bse/bseenginenode.hh
@@ -159,7 +159,7 @@ struct _EngineNode /* fields sorted by order of processing access */
{
BseModule module;
BirnetRecMutex rec_mutex; /* processing lock */
- guint64 counter; /* <= GSL_TICK_STAMP */
+ guint64 counter; /* <= Bse::TickStamp::current() */
EngineInput *inputs; /* [ENGINE_NODE_N_ISTREAMS()] */
EngineJInput **jinputs; /* [ENGINE_NODE_N_JSTREAMS()][jstream->jcount] */
EngineOutput *outputs; /* [ENGINE_NODE_N_OSTREAMS()] */
diff --git a/bse/bseengineschedule.cc b/bse/bseengineschedule.cc
index 2e53dd0..4d1fc3b 100644
--- a/bse/bseengineschedule.cc
+++ b/bse/bseengineschedule.cc
@@ -363,7 +363,7 @@ determine_suspension_state (EngineNode *node,
{
node->in_suspend_call = TRUE;
SfiRing *ring; /* calculate outer suspend constraints */
- stamp = ENGINE_NODE_IS_CONSUMER (node) ? 0 : GSL_MAX_TICK_STAMP;
+ stamp = ENGINE_NODE_IS_CONSUMER (node) ? 0 : Bse::TickStamp::max_stamp();
gboolean keep_state = FALSE;
for (ring = node->output_nodes; ring; ring = sfi_ring_walk (ring, node->output_nodes))
{
@@ -687,7 +687,7 @@ subschedule_query_node (EngineSchedule *schedule,
guint child_ostream = node->jinputs[j][i].real_stream;
subschedule_child (schedule, node, query, child, child_ostream);
}
- node->counter = GSL_TICK_STAMP;
+ node->counter = Bse::TickStamp::current();
node->sched_recurse_tag = FALSE;
/* SCHED_DEBUG ("sched_done(%p)", node); */
}
diff --git a/bse/bseengineutils.cc b/bse/bseengineutils.cc
index dd84036..ed1662f 100644
--- a/bse/bseengineutils.cc
+++ b/bse/bseengineutils.cc
@@ -278,7 +278,7 @@ _engine_pop_job (gboolean update_commit_stamp)
cqueue_trans_pending_tail = NULL;
cqueue_trans_job = cqueue_trans_active_head ? cqueue_trans_active_head->jobs_head : NULL;
if (!cqueue_trans_job && update_commit_stamp)
- cqueue_commit_base_stamp = gsl_tick_stamp(); /* last job has been handed out */
+ cqueue_commit_base_stamp = Bse::TickStamp::current(); /* last job has been handed out */
GSL_SPIN_UNLOCK (&cqueue_trans);
sfi_cond_broadcast (&cqueue_trans_cond);
}
@@ -301,7 +301,7 @@ _engine_pop_job (gboolean update_commit_stamp)
cqueue_trans_pending_tail = NULL;
cqueue_trans_job = cqueue_trans_active_head ? cqueue_trans_active_head->jobs_head : NULL;
if (!cqueue_trans_job && update_commit_stamp)
- cqueue_commit_base_stamp = gsl_tick_stamp(); /* last job has been handed out */
+ cqueue_commit_base_stamp = Bse::TickStamp::current(); /* last job has been handed out */
GSL_SPIN_UNLOCK (&cqueue_trans);
}
}
diff --git a/bse/bsepcmdevice-null.cc b/bse/bsepcmdevice-null.cc
index 7bc5f40..088b41a 100644
--- a/bse/bsepcmdevice-null.cc
+++ b/bse/bsepcmdevice-null.cc
@@ -71,7 +71,7 @@ null_device_check_io (BsePcmHandle *handle,
glong *timeoutp)
{
/* keep the sequencer busy or we will constantly timeout */
- sfi_thread_wakeup (bse_sequencer_thread);
+ bse_sequencer_wakeup();
*timeoutp = 1;
/* ensure sequencer fairness */
return !bse_sequencer_thread_lagging (2);
diff --git a/bse/bseprobe.cc b/bse/bseprobe.cc
index bdcc4af..112d0dc 100644
--- a/bse/bseprobe.cc
+++ b/bse/bseprobe.cc
@@ -2,7 +2,7 @@
#include "bseprobe.genidl.hh"
#include "bseengine.hh"
#include "bseblockutils.hh"
-#include "gslcommon.hh" /* for gsl_tick_stamp() */
+#include "gslcommon.hh" /* for Bse::TickStamp::current() */
#include "gslfft.hh"
#include "bsemain.hh"
#include "bsesequencer.hh"
@@ -687,7 +687,7 @@ source_mass_request::exec (const ProbeRequestSeq &cprseq)
Num
source_get_tick_stamp::exec (BseSource *self)
{
- return gsl_tick_stamp ();
+ return Bse::TickStamp::current();
}
Int
source_get_mix_freq::exec (BseSource *self)
diff --git a/bse/bseproject.cc b/bse/bseproject.cc
index ba4c04e..ff9a314 100644
--- a/bse/bseproject.cc
+++ b/bse/bseproject.cc
@@ -654,7 +654,7 @@ bse_project_state_changed (BseProject *self,
self->state = state;
if (self->state == BSE_PROJECT_ACTIVE && self->deactivate_usecs >= 0)
{
- SfiTime stamp = gsl_tick_stamp ();
+ SfiTime stamp = Bse::TickStamp::current();
SfiTime delay_usecs = 0;
if (SfiTime (self->deactivate_min_tick) > stamp)
delay_usecs = (self->deactivate_min_tick - stamp) * 1000000 / bse_engine_sample_freq ();
diff --git a/bse/bsesequencer.cc b/bse/bsesequencer.cc
index 293da74..e1ca94f 100644
--- a/bse/bsesequencer.cc
+++ b/bse/bsesequencer.cc
@@ -15,15 +15,18 @@
#include <errno.h>
#include <string.h>
#include <vector>
+using namespace std; // FIXME
+
/* due to a linker/compiler bug on SuSE 9.2, we need to
* define extern "C" symbols outside of any C++ namespace,
* in order for C code to link against it.
*/
extern "C" { BirnetThread *bse_sequencer_thread = NULL; }
-using namespace std;
+
#define CHECKTRACE() UNLIKELY (bse_trace_args.sequencer)
#define SEQTRACE(...) do { if (CHECKTRACE()) sfi_debug_channel_printf (bse_trace_args.sequencer, NULL,
__VA_ARGS__); } while (0)
#define BSE_SEQUENCER_FUTURE_BLOCKS (7)
+
/* --- prototypes --- */
static void bse_sequencer_thread_main (gpointer data);
static void bse_sequencer_process_song_SL (BseSong *song,
@@ -32,6 +35,7 @@ static void bse_sequencer_process_song_SL (BseSong *song,
static BseSequencer *global_sequencer = NULL;
static BirnetCond current_watch_cond = { 0, };
static gint sequencer_wake_up_pipe[2] = { -1, -1 };
+
/* --- functions --- */
extern "C" void
bse_sequencer_init_thread (void)
@@ -46,15 +50,16 @@ bse_sequencer_init_thread (void)
fcntl (sequencer_wake_up_pipe[1], F_SETFL, O_NONBLOCK | flags);
/* initialize BseSequencer */
static BseSequencer sseq = { 0, };
- sseq.stamp = gsl_tick_stamp ();
+ sseq.stamp = Bse::TickStamp::current();
g_assert (sseq.stamp > 0);
global_sequencer = &sseq;
bse_sequencer_thread = sfi_thread_run ("Sequencer", bse_sequencer_thread_main, NULL);
if (!bse_sequencer_thread)
g_error ("failed to create sequencer thread");
}
-static void
-sequencer_wake_up (gpointer wake_up_data)
+
+void
+bse_sequencer_wakeup ()
{
guint8 wake_up_message = 'W';
gint err;
@@ -62,6 +67,7 @@ sequencer_wake_up (gpointer wake_up_data)
err = write (sequencer_wake_up_pipe[1], &wake_up_message, 1);
while (err < 0 && errno == EINTR);
}
+
namespace { // Anon
class PollPool {
public:
@@ -221,7 +227,7 @@ bse_sequencer_remove_io_watch (BseIOWatch watch_func,
{
removal_success = sequencer_poll_pool.remove_watch (watch_func, watch_data);
/* wake up sequencer thread, so it stops polling on fds it doesn't own anymore */
- sfi_thread_wakeup (bse_sequencer_thread);
+ bse_sequencer_wakeup();
}
BSE_SEQUENCER_UNLOCK ();
if (!removal_success)
@@ -297,7 +303,7 @@ bse_sequencer_start_song (BseSong *song,
}
global_sequencer->songs = sfi_ring_append (global_sequencer->songs, song);
BSE_SEQUENCER_UNLOCK ();
- sfi_thread_wakeup (bse_sequencer_thread);
+ bse_sequencer_wakeup();
}
extern "C" void
bse_sequencer_remove_song (BseSong *song)
@@ -351,7 +357,7 @@ extern "C" gboolean
bse_sequencer_thread_lagging (guint n_blocks)
{
/* return whether the sequencer lags for n_blocks future stamps */
- const guint64 cur_stamp = gsl_tick_stamp ();
+ const guint64 cur_stamp = Bse::TickStamp::current();
guint64 next_stamp = cur_stamp + n_blocks * bse_engine_block_size();
BSE_SEQUENCER_LOCK ();
gboolean lagging = global_sequencer->stamp < next_stamp;
@@ -361,13 +367,13 @@ bse_sequencer_thread_lagging (guint n_blocks)
static void
bse_sequencer_thread_main (gpointer data)
{
- SEQTRACE ("SEQ:thrdstrt: now=%llu", gsl_tick_stamp());
- sfi_thread_set_wakeup (sequencer_wake_up, NULL, NULL);
+ SEQTRACE ("SEQ:thrdstrt: now=%llu", Bse::TickStamp::current());
+ Bse::TickStampWakeupP wakeup = Bse::TickStamp::create_wakeup (bse_sequencer_wakeup);
bse_message_setup_thread_handler();
BSE_SEQUENCER_LOCK ();
do
{
- const guint64 cur_stamp = gsl_tick_stamp ();
+ const guint64 cur_stamp = Bse::TickStamp::current();
guint64 next_stamp = cur_stamp + BSE_SEQUENCER_FUTURE_BLOCKS * bse_engine_block_size();
SfiRing *ring;
for (ring = global_sequencer->songs; ring; ring = sfi_ring_walk (ring, global_sequencer->songs))
@@ -412,11 +418,11 @@ bse_sequencer_thread_main (gpointer data)
}
}
global_sequencer->stamp = next_stamp;
- sfi_thread_awake_after (cur_stamp + bse_engine_block_size ());
+ wakeup->awake_after (cur_stamp + bse_engine_block_size ());
}
while (bse_sequencer_poll_Lm (-1));
BSE_SEQUENCER_UNLOCK ();
- SEQTRACE ("SEQ:thrdstop: now=%llu", gsl_tick_stamp());
+ SEQTRACE ("SEQ:thrdstop: now=%llu", Bse::TickStamp::current());
}
static void
bse_sequencer_process_track_SL (BseTrack *track,
@@ -506,13 +512,13 @@ bse_sequencer_process_track_SL (BseTrack *track,
if (!part && next)
{
part = bse_track_get_part_SL (track, next, &start, &next);
- SEQTRACE ("SEQ:trackjmp: tick=%u fast forward to first part part=%p now=%llu", start_tick, part,
gsl_tick_stamp());
+ SEQTRACE ("SEQ:trackjmp: tick=%u fast forward to first part part=%p now=%llu", start_tick, part,
Bse::TickStamp::current());
}
if (!part || (next == 0 && start + part->last_tick_SL < start_tick))
{
track->track_done_SL = !bse_midi_receiver_voices_pending (midi_receiver, track->midi_channel_SL);
SEQTRACE ("SEQ:trackchk: tick=%u next=%u part=%p done=%u now=%llu", // part==NULL || start + (part ?
part->last_tick_SL : 0) < start_tick
- start_tick, next, part, track->track_done_SL, gsl_tick_stamp());
+ start_tick, next, part, track->track_done_SL, Bse::TickStamp::current());
part = NULL;
}
while (part && start < bound)
@@ -563,9 +569,9 @@ bse_sequencer_process_part_SL (BsePart *part,
if (CHECKTRACE())
{
SEQTRACE ("SEQ:note-on: tick=%llu midinote=%-3d velocity=%02x freq=% 10f now=%llu",
- eon->delta_time, note->note, bse_ftoi (note->velocity * 128), freq,
gsl_tick_stamp());
+ eon->delta_time, note->note, bse_ftoi (note->velocity * 128), freq,
Bse::TickStamp::current());
SEQTRACE ("SEQ:note-off: tick=%llu midinote=%-3d velocity=%02x freq=% 10f now=%llu",
- eoff->delta_time, note->note, bse_ftoi (note->velocity * 128), freq,
gsl_tick_stamp());
+ eoff->delta_time, note->note, bse_ftoi (note->velocity * 128), freq,
Bse::TickStamp::current());
}
note++;
}
@@ -582,7 +588,7 @@ bse_sequencer_process_part_SL (BsePart *part,
BseMidiSignalType (cev->ctype), cev->value);
bse_midi_receiver_push_event (midi_receiver, event);
SEQTRACE ("SEQ:control: tick=%llu midisignal=%-3d value=%f now=%llu",
- event->delta_time, cev->ctype, cev->value, gsl_tick_stamp());
+ event->delta_time, cev->ctype, cev->value, Bse::TickStamp::current());
}
node++;
}
diff --git a/bse/bsesequencer.hh b/bse/bsesequencer.hh
index 5a4c289..b2b7ef7 100644
--- a/bse/bsesequencer.hh
+++ b/bse/bsesequencer.hh
@@ -2,12 +2,17 @@
#ifndef __BSE_SSEQUENCER_H__
#define __BSE_SSEQUENCER_H__
#include <bse/bsesong.hh>
+
G_BEGIN_DECLS
+
typedef struct {
guint64 stamp; /* sequencer time (ahead of real time) */
SfiRing *songs;
} BseSequencer;
-extern BirnetThread *bse_sequencer_thread;
+
+extern BirnetThread* bse_sequencer_thread; // FIXME
+
+void bse_sequencer_wakeup ();
void bse_sequencer_init_thread (void);
void bse_sequencer_add_io_watch (guint n_pfds,
const GPollFD *pfds,
@@ -19,5 +24,7 @@ void bse_sequencer_start_song (BseSong *song,
guint64 start_stamp);
void bse_sequencer_remove_song (BseSong *song);
gboolean bse_sequencer_thread_lagging (guint n_blocks);
+
G_END_DECLS
+
#endif /* __BSE_SSEQUENCER_H__ */
diff --git a/bse/bsesong.proc b/bse/bsesong.proc
index 16da96b..5cf9a50 100644
--- a/bse/bsesong.proc
+++ b/bse/bsesong.proc
@@ -417,7 +417,7 @@ METHOD (BseSong, synthesize-note) {
{
double semitone_factor = bse_transpose_factor (self->musical_tuning, CLAMP (note, SFI_MIN_NOTE,
SFI_MAX_NOTE) - SFI_KAMMER_NOTE);
double freq = BSE_KAMMER_FREQUENCY * semitone_factor * bse_cent_tune_fast (fine_tune);
- SfiTime tstamp = gsl_tick_stamp () + bse_engine_block_size () * 2;
+ SfiTime tstamp = Bse::TickStamp::current() + bse_engine_block_size () * 2;
BseMidiEvent *eon, *eoff;
eon = bse_midi_event_note_on (track->midi_channel_SL, tstamp, freq, velocity);
eoff = bse_midi_event_note_off (track->midi_channel_SL, tstamp + duration, freq);
diff --git a/bse/bsewaveosc.cc b/bse/bsewaveosc.cc
index d7fbf4a..4daa3af 100644
--- a/bse/bsewaveosc.cc
+++ b/bse/bsewaveosc.cc
@@ -409,7 +409,7 @@ pcm_pos_access (BseModule *module, /* EngineThread */
{
GslWaveOscData *wosc = (GslWaveOscData*) module->user_data;
PcmPos *pos = (PcmPos*) data;
- pos->stamp = GSL_TICK_STAMP;
+ pos->stamp = Bse::TickStamp::current();
pos->module_pcm_position = gsl_wave_osc_cur_pos (wosc);
if (pos->perc >= 0 && wosc->wchunk)
{
diff --git a/bse/gslcommon.cc b/bse/gslcommon.cc
index ed6b80f..d49b569 100644
--- a/bse/gslcommon.cc
+++ b/bse/gslcommon.cc
@@ -11,12 +11,48 @@
#include <sys/poll.h>
#include <sys/stat.h>
#include <sys/time.h>
-/* --- variables --- */
-volatile guint64 bse_engine_exvar_tick_stamp = 0; /* initialized to 1 upon gsl_init(), so 0==invalid */
-static guint64 tick_stamp_system_time = 0;
-static guint global_tick_stamp_leaps = 0;
-/* --- tick stamps --- */
-static BirnetMutex global_tick_stamp_mutex = { 0, };
+
+namespace Bse {
+
+// == TickStamp ==
+static Rapicorn::Mutex global_tick_stamp_mutex;
+static uint64 tick_stamp_system_time = 0;
+static uint64 tick_stamp_leaps = 0;
+Rapicorn::Atomic<uint64> TickStamp::global_tick_stamp = 0; // initialized to 1 from gsl_init(),
so 0 == invalid
+static std::list<TickStampWakeupP> tick_stamp_wakeups;
+
+void
+TickStamp::_init_forgsl()
+{
+ g_return_if_fail (global_tick_stamp == 0); // assert we're uninitialized
+ global_tick_stamp = 1;
+}
+
+void
+TickStamp::_set_leap (uint64 ticks)
+{
+ Rapicorn::ScopedLock<Rapicorn::Mutex> locker (global_tick_stamp_mutex);
+ tick_stamp_leaps = ticks;
+}
+
+void
+TickStamp::_increment ()
+{
+ g_return_if_fail (tick_stamp_leaps > 0);
+ volatile guint64 newstamp;
+ uint64 systime;
+ systime = sfi_time_system ();
+ newstamp = global_tick_stamp + tick_stamp_leaps;
+ {
+ Rapicorn::ScopedLock<Rapicorn::Mutex> locker (global_tick_stamp_mutex);
+ global_tick_stamp = newstamp;
+ tick_stamp_system_time = systime;
+ }
+ struct Internal : Wakeup { using Wakeup::_emit_wakeups; };
+ Internal::_emit_wakeups (newstamp);
+}
+
+#ifdef RAPICORN_DOXYGEN
/**
* @return GSL's execution tick stamp as unsigned 64bit integer
*
@@ -29,74 +65,109 @@ static BirnetMutex global_tick_stamp_mutex = { 0, };
* sfi_thread_awake_before(). Tick stamp updating occours at
* GSL engine block processing boundaries, so code that can
* guarantee to not run across those boundaries (for instance
- * BseProcessFunc() functions) may use the macro GSL_TICK_STAMP
+ * BseProcessFunc() functions) may use the macro Bse::TickStamp::current()
* to retrieve the current tick in a faster manner (not involving
* mutex locking). See also bse_module_tick_stamp().
* This function is MT-safe and may be called from any thread.
*/
-guint64
-gsl_tick_stamp (void)
-{
- guint64 stamp;
- GSL_SPIN_LOCK (&global_tick_stamp_mutex);
- stamp = bse_engine_exvar_tick_stamp;
- GSL_SPIN_UNLOCK (&global_tick_stamp_mutex);
- return stamp;
-}
-void
-_gsl_tick_stamp_set_leap (guint ticks)
-{
- GSL_SPIN_LOCK (&global_tick_stamp_mutex);
- global_tick_stamp_leaps = ticks;
- GSL_SPIN_UNLOCK (&global_tick_stamp_mutex);
-}
+uint64 TickStamp::current () { ... }
+#endif
+
/**
* @return Current tick stamp and system time in micro seconds
*
* Get the system time of the last GSL global tick stamp update.
* This function is MT-safe and may be called from any thread.
*/
-GslTickStampUpdate
-gsl_tick_stamp_last (void)
+TickStamp::Update
+TickStamp::get_last()
{
- GslTickStampUpdate ustamp;
- GSL_SPIN_LOCK (&global_tick_stamp_mutex);
- ustamp.tick_stamp = bse_engine_exvar_tick_stamp;
+ Update ustamp;
+ Rapicorn::ScopedLock<Rapicorn::Mutex> locker (global_tick_stamp_mutex);
+ ustamp.tick_stamp = global_tick_stamp;
ustamp.system_time = tick_stamp_system_time;
- GSL_SPIN_UNLOCK (&global_tick_stamp_mutex);
return ustamp;
}
+
+TickStamp::Wakeup::Wakeup (const std::function<void()> &wakeup) :
+ wakeup_ (wakeup), awake_stamp_ (0)
+{}
+
+TickStampWakeupP
+TickStamp::create_wakeup (const std::function<void()> &wakeup)
+{
+ struct WakeupImpl : TickStamp::Wakeup {
+ WakeupImpl (const std::function<void()> &wakeup) :
+ Wakeup (wakeup)
+ {}
+ };
+ auto wp = std::make_shared<WakeupImpl> (wakeup);
+ return wp;
+}
+
+/**
+ * @param stamp stamp to trigger wakeup
+ *
+ * Wake the current thread up at a future tick increment which exceeds @a stamp.
+ */
void
-_gsl_tick_stamp_inc (void)
+TickStamp::Wakeup::awake_after (uint64 stamp)
{
- volatile guint64 newstamp;
- guint64 systime;
- g_return_if_fail (global_tick_stamp_leaps > 0);
- systime = sfi_time_system ();
- newstamp = bse_engine_exvar_tick_stamp + global_tick_stamp_leaps;
- GSL_SPIN_LOCK (&global_tick_stamp_mutex);
- bse_engine_exvar_tick_stamp = newstamp;
- tick_stamp_system_time = systime;
- GSL_SPIN_UNLOCK (&global_tick_stamp_mutex);
- sfi_thread_emit_wakeups (newstamp);
+ Rapicorn::ScopedLock<Rapicorn::Mutex> locker (global_tick_stamp_mutex);
+ if (!awake_stamp_ && stamp)
+ {
+ tick_stamp_wakeups.push_back (shared_from_this());
+ awake_stamp_ = stamp;
+ }
+ else if (!stamp && awake_stamp_)
+ {
+ tick_stamp_wakeups.remove (shared_from_this());
+ awake_stamp_ = 0;
+ }
+ else if (awake_stamp_ && stamp)
+ awake_stamp_ = MIN (awake_stamp_, stamp);
}
+
/**
- * @param tick_stamp tick stamp update to trigger wakeup
+ * @param stamp tick stamp update to trigger wakeup
+ *
* Wakeup the currently running thread upon the last global tick stamp
- * update (see gsl_tick_stamp()) that happens prior to updating the
+ * update (see Bse::TickStamp::current()) that happens prior to updating the
* global tick stamp to @a tick_stamp.
* (If the moment of wakeup has already passed by, the thread is
* woken up at the next global tick stamp update.)
*/
void
-gsl_thread_awake_before (guint64 tick_stamp)
+TickStamp::Wakeup::awake_before (uint64 stamp)
{
- g_return_if_fail (tick_stamp > 0);
- if (tick_stamp > global_tick_stamp_leaps)
- sfi_thread_awake_after (tick_stamp - global_tick_stamp_leaps);
- else
- sfi_thread_awake_after (tick_stamp);
+ g_return_if_fail (stamp > 0);
+ if (stamp > tick_stamp_leaps)
+ stamp -= tick_stamp_leaps;
+ awake_after (stamp);
+}
+
+void
+TickStamp::Wakeup::_emit_wakeups (uint64 wakeup_stamp)
+{
+ Rapicorn::ScopedLock<Rapicorn::Mutex> locker (global_tick_stamp_mutex);
+ std::list<TickStampWakeupP> list, notifies;
+ list.swap (tick_stamp_wakeups);
+ for (auto it : list)
+ if (it->awake_stamp_ > wakeup_stamp)
+ tick_stamp_wakeups.push_back (it);
+ else // awake_stamp_ <= wakeup_stamp
+ notifies.push_back (it);
+ for (auto it : notifies)
+ if (it->wakeup_)
+ {
+ it->awake_stamp_ = 0;
+ it->wakeup_();
+ }
}
+
+} // Bse
+
+
/* --- misc --- */
const gchar*
gsl_byte_order_to_string (guint byte_order)
@@ -310,10 +381,10 @@ gsl_progress_printerr (gpointer message,
void
gsl_init (void)
{
- g_return_if_fail (bse_engine_exvar_tick_stamp == 0); /* assert single initialization */
- bse_engine_exvar_tick_stamp = 1;
+ g_return_if_fail (Bse::TickStamp::current() == 0); // assert single initialization
+ struct Internal : Bse::TickStamp { using TickStamp::_init_forgsl; };
+ Internal::_init_forgsl();
/* initialize subsystems */
- sfi_mutex_init (&global_tick_stamp_mutex);
_gsl_init_fd_pool ();
_gsl_init_data_caches ();
_gsl_init_loader_gslwave ();
diff --git a/bse/gslcommon.hh b/bse/gslcommon.hh
index 96c53c4..54093a4 100644
--- a/bse/gslcommon.hh
+++ b/bse/gslcommon.hh
@@ -6,21 +6,12 @@
G_BEGIN_DECLS
/* --- initialization --- */
void gsl_init (void);
-/* --- tick stamps --- */
-typedef struct {
- guint64 tick_stamp;
- guint64 system_time;
-} GslTickStampUpdate;
-guint64 gsl_tick_stamp (void);
-guint64 gsl_time_system (void);
-GslTickStampUpdate gsl_tick_stamp_last (void);
-#define GSL_TICK_STAMP (_GSL_TICK_STAMP_VAL ())
-#define GSL_MAX_TICK_STAMP (18446744073709551615LLU /* 2^64-1*/)
-void gsl_thread_awake_before (guint64 tick_stamp);
+
#define GSL_SPIN_LOCK sfi_mutex_lock
#define GSL_SPIN_UNLOCK sfi_mutex_unlock
#define GSL_SYNC_LOCK sfi_mutex_lock
#define GSL_SYNC_UNLOCK sfi_mutex_unlock
+
/* --- misc --- */
const gchar* gsl_byte_order_to_string (guint byte_order);
guint gsl_byte_order_from_string (const gchar *string);
@@ -39,7 +30,8 @@ typedef guint (*GslProgressFunc) (gpointer data,
GslProgressState *pstate);
struct _GslProgressState
{
- guint wipe_length, precision;
+ uint wipe_length;
+ int precision;
gfloat pval, epsilon;
gpointer pdata;
GslProgressFunc pfunc;
@@ -57,8 +49,6 @@ guint gsl_progress_printerr (gpointer message,
const gchar *detail,
GslProgressState *pstate);
/* --- implementation details --- */
-void _gsl_tick_stamp_inc (void);
-void _gsl_tick_stamp_set_leap (guint ticks);
void _gsl_init_fd_pool (void);
void _gsl_init_data_caches (void);
void _gsl_init_loader_gslwave (void);
@@ -68,7 +58,42 @@ void _gsl_init_loader_oggvorbis (void);
void _gsl_init_loader_mad (void);
void bse_init_loader_gus_patch (void);
#define GSL_N_IO_RETRIES (5)
-#define _GSL_TICK_STAMP_VAL() (bse_engine_exvar_tick_stamp + 0)
-extern volatile guint64 bse_engine_exvar_tick_stamp;
G_END_DECLS
+
+
+namespace Bse {
+
+// == TickStamp ==
+class TickStamp {
+ static Rapicorn::Atomic<uint64> global_tick_stamp;
+protected:
+ static void _init_forgsl ();
+public:
+ class Wakeup : public std::enable_shared_from_this<Wakeup> {
+ std::function<void()> wakeup_;
+ uint64 awake_stamp_;
+ protected:
+ explicit Wakeup (const std::function<void()> &wakeup);
+ static void _emit_wakeups (uint64 wakeup_stamp);
+ public:
+ void awake_after (uint64 stamp);
+ void awake_before (uint64 stamp);
+ };
+ typedef std::shared_ptr<Wakeup> WakeupP;
+ struct Update {
+ uint64 tick_stamp;
+ uint64 system_time;
+ };
+ static Update get_last ();
+ static WakeupP create_wakeup (const std::function<void()> &wakeup);
+ static inline uint64 current () { return global_tick_stamp; }
+ static inline uint64 max_stamp () { return 18446744073709551615LLU; } ///< Maximum stamp
value, 2^64-1.
+ static void _increment ();
+ static void _set_leap (uint64 ticks);
+};
+typedef TickStamp::WakeupP TickStampWakeupP;
+
+} // Bse
+
+
#endif /* __GSL_COMMON_H__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]