[beast: 3/6] BSE: make bse_engine_const_values thread safe and simplify implementation
- From: Tim Janik <timj src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [beast: 3/6] BSE: make bse_engine_const_values thread safe and simplify implementation
- Date: Sun, 6 Nov 2016 22:32:42 +0000 (UTC)
commit d880d2ac3c778260c0c39ef03cd992a78cd0ad58
Author: Tim Janik <timj gnu org>
Date: Sun Nov 6 21:31:43 2016 +0100
BSE: make bse_engine_const_values thread safe and simplify implementation
Signed-off-by: Tim Janik <timj gnu org>
bse/bseengine.hh | 4 +-
bse/bseengineutils.cc | 169 ++++++++-----------------------------------------
bse/bseengineutils.hh | 3 +-
3 files changed, 30 insertions(+), 146 deletions(-)
---
diff --git a/bse/bseengine.hh b/bse/bseengine.hh
index e141f8f..cd4153e 100644
--- a/bse/bseengine.hh
+++ b/bse/bseengine.hh
@@ -171,7 +171,7 @@ void bse_transact (BseJob *job,
...) G_GNUC_NULL_TERMINATED;
/* --- module utilities (EngineThread functions) --- */
-gfloat* bse_engine_const_values (gfloat value);
+float* bse_engine_const_values (float value);
/* --- initialization & main loop --- */
void bse_engine_constrain (guint latency_ms,
@@ -185,7 +185,7 @@ gboolean bse_engine_configure (guint latency_ms,
guint control_freq);
/* --- miscellaneous --- */
-gfloat* bse_engine_const_zeros (guint smaller_than_BSE_STREAM_MAX_VALUES);
+float* bse_engine_const_zeros (uint smaller_than_BSE_STREAM_MAX_VALUES);
gboolean bse_engine_has_garbage (void);
void bse_engine_user_thread_collect (void);
void bse_engine_free_ostreams (guint n_ostreams,
diff --git a/bse/bseengineutils.cc b/bse/bseengineutils.cc
index ec70f1f..686ae7f 100644
--- a/bse/bseengineutils.cc
+++ b/bse/bseengineutils.cc
@@ -5,6 +5,7 @@
#include "bseenginenode.hh"
#include "bseengineschedule.hh"
#include "bsemathsignal.hh"
+#include <unordered_map>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
@@ -642,157 +643,41 @@ _engine_mnl_node_changed (EngineNode *node)
/* --- const value blocks --- */
-float*
-bse_engine_const_zeros (guint smaller_than_BSE_STREAM_MAX_VALUES)
-{
- static const float engine_const_zero_block[BSE_STREAM_MAX_VALUES + 16 /* SIMD alignment */] = { 0, };
- /* this function is callable from any thread */
- assert (smaller_than_BSE_STREAM_MAX_VALUES <= BSE_STREAM_MAX_VALUES);
- return (float*) engine_const_zero_block;
-}
-
-typedef struct
-{
- guint n_nodes;
- gfloat **nodes;
- guint8 *nodes_used;
-} ConstValuesArray;
-
-static const guint8 CONST_VALUES_EXPIRE = 16; /* expire value after being unused for 16 times */
+typedef std::unordered_map<float, const float*> FloatBlockMap;
+static std::mutex engine_const_value_mutex;
+static FloatBlockMap engine_const_value_map;
+static const float engine_const_values_0[BSE_STREAM_MAX_VALUES + 16] = { 0 }; // 0.0...
-static inline gfloat**
-const_values_lookup_nextmost (ConstValuesArray *array,
- gfloat key_value)
+float*
+bse_engine_const_values (float value)
{
- guint n_nodes = array->n_nodes;
-
- if (n_nodes > 0)
+ if (value == 0.0)
+ return const_cast<float*> (engine_const_values_0);
+ std::lock_guard<std::mutex> guard (engine_const_value_mutex);
+ const float *&block = engine_const_value_map[value];
+ if (block == NULL)
{
- gfloat **nodes = array->nodes;
- gfloat **check;
-
- nodes -= 1;
- do
- {
- guint i;
- register gfloat cmp;
-
- i = (n_nodes + 1) >> 1;
- check = nodes + i;
- cmp = key_value - **check;
- if (cmp > BSE_SIGNAL_EPSILON)
- {
- n_nodes -= i;
- nodes = check;
- }
- else if (cmp < -BSE_SIGNAL_EPSILON)
- n_nodes = i - 1;
- else /* cmp ~==~ 0.0 */
- return check; /* matched */
- }
- while (n_nodes);
-
- return check; /* nextmost */
+ float *value_block = new float[BSE_STREAM_MAX_VALUES + 16];
+ bse_block_fill_float (BSE_STREAM_MAX_VALUES + 16, value_block, value);
+ block = value_block;
}
-
- return NULL;
-}
-
-static inline guint
-upper_power2 (guint number)
-{
- return sfi_alloc_upper_power2 (MAX (number, 8));
+ return const_cast<float*> (block);
}
-static inline void
-const_values_insert (ConstValuesArray *array,
- guint index,
- gfloat *value_block)
-{
- if (array->n_nodes == 0)
- {
- uint new_size = upper_power2 (sizeof (float*));
- array->nodes = (float**) g_realloc (array->nodes, new_size);
- array->nodes_used = (guint8*) g_realloc (array->nodes_used, new_size / sizeof (gfloat*));
- array->n_nodes = 1;
- assert (index == 0);
- }
- else
- {
- uint n_nodes = array->n_nodes++;
- if (*array->nodes[index] < *value_block)
- index++;
- if (1)
- {
- uint new_size = upper_power2 (array->n_nodes * sizeof (gfloat*));
- uint old_size = upper_power2 (n_nodes * sizeof (gfloat*));
- if (new_size != old_size)
- {
- array->nodes = (float**) g_realloc (array->nodes, new_size);
- array->nodes_used = (guint8*) g_realloc (array->nodes_used, new_size / sizeof (float*));
- }
- }
- memmove (array->nodes + index + 1, array->nodes + index, (n_nodes - index) * sizeof (array->nodes[0]));
- memmove (array->nodes_used + index + 1, array->nodes_used + index, (n_nodes - index) * sizeof
(array->nodes_used[0]));
- }
- array->nodes[index] = value_block;
- array->nodes_used[index] = CONST_VALUES_EXPIRE;
-}
-
-static ConstValuesArray cvalue_array = { 0, NULL, NULL };
-
float*
-bse_engine_const_values (gfloat value)
+bse_engine_const_zeros (uint smaller_than_BSE_STREAM_MAX_VALUES)
{
- if (fabs (value) < BSE_SIGNAL_EPSILON)
- return bse_engine_const_zeros (BSE_STREAM_MAX_VALUES);
-
- float **block = const_values_lookup_nextmost (&cvalue_array, value);
- /* found correct match? */
- if (block && fabs (**block - value) < BSE_SIGNAL_EPSILON)
- {
- cvalue_array.nodes_used[block - cvalue_array.nodes] = CONST_VALUES_EXPIRE;
- return *block;
- }
- else
- {
- /* create new value block */
- gfloat *values = g_new (gfloat, bse_engine_block_size ());
- bse_block_fill_float (bse_engine_block_size(), values, value);
- if (block)
- const_values_insert (&cvalue_array, block - cvalue_array.nodes, values);
- else
- const_values_insert (&cvalue_array, 0, values);
-
- return values;
- }
+ assert_return (smaller_than_BSE_STREAM_MAX_VALUES <= BSE_STREAM_MAX_VALUES, NULL);
+ return const_cast<float*> (engine_const_values_0);
}
void
-_engine_recycle_const_values (gboolean nuke_all)
-{
- gfloat **nodes = cvalue_array.nodes;
- guint8 *used = cvalue_array.nodes_used;
- guint count = cvalue_array.n_nodes, e = 0, i;
-
- for (i = 0; i < count; i++)
- {
- if (nuke_all)
- used[i] = 0;
- else
- used[i]--; /* invariant: use counts are never 0 */
-
- if (used[i] == 0)
- g_free (nodes[i]);
- else /* preserve node */
- {
- if (e < i)
- {
- nodes[e] = nodes[i];
- used[e] = used[i];
- }
- e++;
- }
- }
- cvalue_array.n_nodes = e;
+_engine_recycle_const_values (bool remove_all)
+{
+ if (!remove_all)
+ return;
+ std::lock_guard<std::mutex> guard (engine_const_value_mutex);
+ for (const auto &it : engine_const_value_map)
+ delete[] it.second;
+ engine_const_value_map.clear();
}
diff --git a/bse/bseengineutils.hh b/bse/bseengineutils.hh
index 45ca043..ed97186 100644
--- a/bse/bseengineutils.hh
+++ b/bse/bseengineutils.hh
@@ -9,12 +9,11 @@ void _engine_free_trans (BseTrans *trans);
BseOStream* _engine_alloc_ostreams (guint n);
#if 0 /* bseengine.hh: */
void bse_engine_user_thread_collect (void);
-gfloat* bse_engine_const_values (gfloat value);
#endif
/* --- MasterThread --- */
-void _engine_recycle_const_values (gboolean nuke_all);
+void _engine_recycle_const_values (bool remove_all);
void _engine_node_collect_jobs (EngineNode *node);
/* master node list */
void _engine_mnl_remove (EngineNode *node);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]