[beast: 54/73] BSE: SF2: use std::shared_ptr for blob reference counting



commit f8fe2cfc4dd68eb181230c2509a862ce063edc3c
Author: Stefan Westerfeld <stefan space twc de>
Date:   Thu Dec 8 16:43:54 2016 +0100

    BSE: SF2: use std::shared_ptr for blob reference counting
    
    Signed-off-by: Stefan Westerfeld <stefan space twc de>

 bse/bsesoundfont.cc     |   57 +++++++++---------------
 bse/bsesoundfont.hh     |    5 +-
 bse/bsesoundfontrepo.cc |    3 +-
 bse/bsestorage.cc       |  109 +++++++++++++++--------------------------------
 bse/bsestorage.hh       |   31 +++++++++----
 5 files changed, 81 insertions(+), 124 deletions(-)
---
diff --git a/bse/bsesoundfont.cc b/bse/bsesoundfont.cc
index 4296787..2926173 100644
--- a/bse/bsesoundfont.cc
+++ b/bse/bsesoundfont.cc
@@ -30,7 +30,6 @@ static GQuark      quark_load_sound_font = 0;
 static void
 bse_sound_font_init (BseSoundFont *sound_font)
 {
-  sound_font->blob = NULL;
   sound_font->sfont_id = -1;
   sound_font->sfrepo = NULL;
 }
@@ -56,11 +55,12 @@ bse_sound_font_get_property (GObject    *object,
                             GParamSpec *pspec)
 {
   BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+  Bse::SoundFontImpl *sound_font_impl = sound_font->as<Bse::SoundFontImpl *>();
   switch (param_id)
     {
     case PARAM_FILE_NAME:
-      if (sound_font->blob)
-        sfi_value_set_string (value, bse_storage_blob_file_name (sound_font->blob));
+      if (sound_font_impl->blob)
+        sfi_value_set_string (value, bse_storage_blob_file_name (sound_font_impl->blob));
       else
         sfi_value_set_string (value, NULL);
       break;
@@ -90,14 +90,7 @@ bse_sound_font_finalize (GObject *object)
 {
   BseSoundFont *sound_font = BSE_SOUND_FONT (object);
 
-  /* free blob */
-  if (sound_font->blob)
-    {
-      bse_storage_blob_unref (sound_font->blob);
-      sound_font->blob = NULL;
-    }
-
-  if (sound_font->sfrepo != NULL || sound_font->blob != NULL || sound_font->sfont_id != -1)
+  if (sound_font->sfrepo != NULL || sound_font->sfont_id != -1)
     g_warning (G_STRLOC ": some resources could not be freed.");
 
   /* chain parent class' handler */
@@ -105,10 +98,12 @@ bse_sound_font_finalize (GObject *object)
 }
 
 Bse::Error
-bse_sound_font_load_blob (BseSoundFont    *self,
-                          BseStorageBlob  *blob,
-                         gboolean         init_presets)
+bse_sound_font_load_blob (BseSoundFont       *self,
+                          BseStorage::BlobP   blob,
+                         gboolean            init_presets)
 {
+  Bse::SoundFontImpl *sound_font_impl = self->as<Bse::SoundFontImpl *>();
+
   if (self->sfrepo == NULL)
     {
       self->sfrepo = BSE_SOUND_FONT_REPO (BSE_ITEM (self)->parent);
@@ -119,13 +114,6 @@ bse_sound_font_load_blob (BseSoundFont    *self,
   g_return_val_if_fail (self->sfrepo != NULL, Bse::Error::INTERNAL);
   g_return_val_if_fail (self->sfont_id == -1, Bse::Error::INTERNAL);
 
-  bse_storage_blob_ref (blob);
-  if (self->blob)
-    {
-      bse_storage_blob_unref (self->blob);
-      self->blob = NULL;
-    }
-
   std::lock_guard<Bse::Mutex> guard (bse_sound_font_repo_mutex (self->sfrepo));
   fluid_synth_t *fluid_synth = bse_sound_font_repo_fluid_synth (self->sfrepo);
   int sfont_id = fluid_synth_sfload (fluid_synth, bse_storage_blob_file_name (blob), 0);
@@ -149,12 +137,12 @@ bse_sound_font_load_blob (BseSoundFont    *self,
            }
        }
       self->sfont_id = sfont_id;
-      self->blob = blob;
+      sound_font_impl->blob = blob;
       error = Bse::Error::NONE;
     }
   else
     {
-      bse_storage_blob_unref (blob);
+      sound_font_impl->blob = nullptr;
       error = Bse::Error::WAVE_NOT_FOUND;
     }
   return error;
@@ -178,9 +166,11 @@ bse_sound_font_unload (BseSoundFont *sound_font)
 Bse::Error
 bse_sound_font_reload (BseSoundFont *sound_font)
 {
+  Bse::SoundFontImpl *sound_font_impl = sound_font->as<Bse::SoundFontImpl *>();
+
   g_return_val_if_fail (sound_font->sfont_id == -1, Bse::Error::INTERNAL);
 
-  return bse_sound_font_load_blob (sound_font, sound_font->blob, FALSE);
+  return bse_sound_font_load_blob (sound_font, sound_font_impl->blob, FALSE);
 }
 
 static void
@@ -188,19 +178,20 @@ bse_sound_font_store_private (BseObject  *object,
                              BseStorage *storage)
 {
   BseSoundFont *sound_font = BSE_SOUND_FONT (object);
+  Bse::SoundFontImpl *sound_font_impl = sound_font->as<Bse::SoundFontImpl *>();
   /* chain parent class' handler */
   BSE_OBJECT_CLASS (parent_class)->store_private (object, storage);
 
-  if (!BSE_STORAGE_SELF_CONTAINED (storage) && !bse_storage_blob_is_temp_file (sound_font->blob))
+  if (!BSE_STORAGE_SELF_CONTAINED (storage) && !bse_storage_blob_is_temp_file (sound_font_impl->blob))
     {
       bse_storage_break (storage);
-      bse_storage_printf (storage, "(load-sound-font \"%s\")", bse_storage_blob_file_name 
(sound_font->blob));
+      bse_storage_printf (storage, "(load-sound-font \"%s\")", bse_storage_blob_file_name 
(sound_font_impl->blob));
     }
   else
     {
       bse_storage_break (storage);
       bse_storage_printf (storage, "(load-sound-font ");
-      bse_storage_put_blob (storage, sound_font->blob);
+      bse_storage_put_blob (storage, sound_font_impl->blob);
       bse_storage_printf (storage, ")");
     }
 }
@@ -222,7 +213,7 @@ bse_sound_font_restore_private (BseObject  *object,
   quark = g_quark_try_string (scanner->next_value.v_identifier);
   if (quark == quark_load_sound_font)
     {
-      BseStorageBlob *blob;
+      BseStorage::BlobP blob;
       Bse::Error error;
 
       g_scanner_get_next_token (scanner); /* eat quark identifier */
@@ -233,17 +224,12 @@ bse_sound_font_restore_private (BseObject  *object,
        }
       else
        {
-          GTokenType token = bse_storage_parse_blob (storage, &blob);
+          GTokenType token = bse_storage_parse_blob (storage, blob);
          if (token != G_TOKEN_NONE)
-           {
-             if (blob)
-               bse_storage_blob_unref (blob);
-              return token;
-           }
+            return token;
        }
       if (g_scanner_peek_next_token (scanner) != ')')
        {
-         bse_storage_blob_unref (blob);
          return GTokenType (')');
        }
       parse_or_return (scanner, ')');
@@ -251,7 +237,6 @@ bse_sound_font_restore_private (BseObject  *object,
       if (error != 0)
        bse_storage_warn (storage, "failed to load sound font \"%s\": %s",
                                    bse_storage_blob_file_name (blob), bse_error_blurb (error));
-      bse_storage_blob_unref (blob);
       expected_token = G_TOKEN_NONE; /* got ')' */
     }
   else /* chain parent class' handler */
diff --git a/bse/bsesoundfont.hh b/bse/bsesoundfont.hh
index c0af024..23c34a8 100644
--- a/bse/bsesoundfont.hh
+++ b/bse/bsesoundfont.hh
@@ -14,7 +14,6 @@
 #define BSE_SOUND_FONT_GET_CLASS(object)  (G_TYPE_INSTANCE_GET_CLASS ((object), BSE_TYPE_SOUND_FONT, 
BseSoundFontClass))
 
 struct BseSoundFont : BseContainer {
-  BseStorageBlob    *blob;
   int                sfont_id;
   BseSoundFontRepo  *sfrepo;
   GList             *presets;
@@ -23,7 +22,7 @@ struct BseSoundFontClass : BseContainerClass
 {};
 
 Bse::Error      bse_sound_font_load_blob       (BseSoundFont       *sound_font,
-                                                BseStorageBlob     *blob,
+                                                BseStorage::BlobP   blob,
                                                 gboolean            init_presets);
 void           bse_sound_font_unload           (BseSoundFont       *sound_font);
 Bse::Error      bse_sound_font_reload           (BseSoundFont       *sound_font);
@@ -31,6 +30,8 @@ Bse::Error      bse_sound_font_reload           (BseSoundFont       *sound_font)
 namespace Bse {
 
 class SoundFontImpl : public ContainerImpl, public virtual SoundFontIface {
+public:
+  BseStorage::BlobP blob;
 protected:
   virtual  ~SoundFontImpl ();
 public:
diff --git a/bse/bsesoundfontrepo.cc b/bse/bsesoundfontrepo.cc
index e0e08e8..2a204e8 100644
--- a/bse/bsesoundfontrepo.cc
+++ b/bse/bsesoundfontrepo.cc
@@ -374,9 +374,8 @@ repo_load_file (BseSoundFontRepo *sfrepo, const String &file_name, BseSoundFont
   BseSoundFont *sound_font = (BseSoundFont*) bse_object_new (BSE_TYPE_SOUND_FONT, "uname", fname.c_str(), 
NULL);
   bse_container_add_item (BSE_CONTAINER (sfrepo), BSE_ITEM (sound_font));
 
-  BseStorageBlob *blob = bse_storage_blob_new_from_file (file_name.c_str(), FALSE);
+  BseStorage::BlobP blob = bse_storage_blob_new_from_file (file_name.c_str(), FALSE);
   Error error = bse_sound_font_load_blob (sound_font, blob, TRUE);
-  bse_storage_blob_unref (blob);
 
   if (error == Bse::Error::NONE)
     {
diff --git a/bse/bsestorage.cc b/bse/bsestorage.cc
index 6f1c354..b3ec778 100644
--- a/bse/bsestorage.cc
+++ b/bse/bsestorage.cc
@@ -42,14 +42,6 @@ struct _BseStorageItemLink
   BseItem              *to_item;
   gchar                *error;
 };
-struct _BseStorageBlob
-{
-  Bse::Mutex  mutex;
-  char       *file_name;
-  int        ref_count;
-  gboolean    is_temp_file;
-  gulong      id;
-};
 
 /* --- prototypes --- */
 static void       bse_storage_init                 (BseStorage       *self);
@@ -241,8 +233,6 @@ bse_storage_reset (BseStorage *self)
   self->dblocks = NULL;
   self->n_dblocks = 0;
 
-  for (auto blob : self->data.blobs)
-    bse_storage_blob_unref (blob);
   self->data.blobs.clear();
 
   g_free (self->free_me);
@@ -274,10 +264,10 @@ bse_storage_add_dblock (BseStorage    *self,
 }
 
 static gulong
-bse_storage_add_blob (BseStorage     *self,
-                      BseStorageBlob *blob)
+bse_storage_add_blob (BseStorage       *self,
+                      BseStorage::BlobP blob)
 {
-  self->data.blobs.push_back (bse_storage_blob_ref (blob));
+  self->data.blobs.push_back (blob);
   return self->data.blobs.back()->id;
 }
 
@@ -1810,24 +1800,10 @@ bse_storage_parse_data_handle_rest (BseStorage     *self,
 
 // == blobs ==
 
-BseStorageBlob *
-bse_storage_blob_ref (BseStorageBlob *blob)
-{
-  g_return_val_if_fail (blob != NULL, NULL);
-  g_return_val_if_fail (blob->ref_count > 0, NULL);
-
-  blob->mutex.lock();
-  blob->ref_count++;
-  blob->mutex.unlock();
-
-  return blob;
-}
-
 const gchar *
-bse_storage_blob_file_name (BseStorageBlob *blob)
+bse_storage_blob_file_name (BseStorage::BlobP blob)
 {
   g_return_val_if_fail (blob != NULL, NULL);
-  g_return_val_if_fail (blob->ref_count > 0, NULL);
 
   blob->mutex.lock();
   const gchar *file_name = blob->file_name;
@@ -1836,29 +1812,16 @@ bse_storage_blob_file_name (BseStorageBlob *blob)
   return file_name;
 }
 
-void
-bse_storage_blob_unref (BseStorageBlob *blob)
+BseStorage::Blob::~Blob()
 {
-  g_return_if_fail (blob != NULL);
-  g_return_if_fail (blob->ref_count > 0);
-
-  blob->mutex.lock();
-  blob->ref_count--;
-  gboolean destroy = blob->ref_count == 0;
-  blob->mutex.unlock();
-  if (destroy)
+  if (is_temp_file)
     {
-      if (blob->is_temp_file)
-       {
-         unlink (blob->file_name);
-         /* FIXME: check error code and do what? */
-       }
-      g_free (blob->file_name);
-      blob->file_name = NULL;
-      bse_id_free (blob->id);
-      blob->mutex.~Mutex();
-      g_free (blob);
+      unlink (file_name);
+      /* FIXME: check error code and do what? */
     }
+  g_free (file_name);
+  file_name = NULL;
+  bse_id_free (id);
 }
 
 /* search in /tmp for files called "bse-<user>-<pid>*"
@@ -1893,24 +1856,21 @@ bse_storage_blob_clean_files()
     }
 }
 
-BseStorageBlob *
+BseStorage::BlobP
 bse_storage_blob_new_from_file (const char *file_name,
                                 gboolean    is_temp_file)
 {
-  BseStorageBlob *blob = g_new0 (BseStorageBlob, 1);
-  new (&blob->mutex) Bse::Mutex();
+  BseStorage::BlobP blob = std::make_shared<BseStorage::Blob>(); // FIXME: constructor
   blob->file_name = g_strdup (file_name);
-  blob->ref_count = 1;
   blob->is_temp_file = is_temp_file;
   blob->id = bse_id_alloc();
   return blob;
 }
 
 gboolean
-bse_storage_blob_is_temp_file (BseStorageBlob *blob)
+bse_storage_blob_is_temp_file (BseStorage::BlobP blob)
 {
   g_return_val_if_fail (blob != NULL, FALSE);
-  g_return_val_if_fail (blob->ref_count > 0, FALSE);
 
   blob->mutex.lock();
   gboolean is_temp_file = blob->is_temp_file;
@@ -1919,19 +1879,19 @@ bse_storage_blob_is_temp_file (BseStorageBlob *blob)
   return is_temp_file;
 }
 
-typedef struct
+struct WStoreBlob
 {
-  BseStorageBlob *blob;
-  BseStorage     *storage;
-  int             fd;
-} WStoreBlob;
+  BseStorage::BlobP blob;
+  BseStorage       *storage;
+  int               fd;
+};
 
 static WStoreBlob *
-wstore_blob_new (BseStorage *storage,
-                 BseStorageBlob *blob)
+wstore_blob_new (BseStorage        *storage,
+                 BseStorage::BlobP  blob)
 {
-  WStoreBlob *wsb = (WStoreBlob *) g_new0 (WStoreBlob, 1);
-  wsb->blob = bse_storage_blob_ref (blob);
+  WStoreBlob *wsb = new WStoreBlob();
+  wsb->blob = blob;
   wsb->storage = storage;
   wsb->fd = -1;
   return wsb;
@@ -1970,12 +1930,12 @@ wstore_blob_destroy (gpointer data)
   WStoreBlob *wblob = (WStoreBlob *) data;
   if (wblob->fd >= 0)
     close (wblob->fd);
-  bse_storage_blob_unref (wblob->blob);
+  delete wblob;
 }
 
 void
-bse_storage_put_blob (BseStorage      *self,
-                      BseStorageBlob  *blob)
+bse_storage_put_blob (BseStorage         *self,
+                      BseStorage::BlobP   blob)
 {
   if (BSE_STORAGE_DBLOCK_CONTAINED (self))
     {
@@ -1997,14 +1957,14 @@ bse_storage_put_blob (BseStorage      *self,
 
 GTokenType
 bse_storage_parse_blob (BseStorage             *self,
-                        BseStorageBlob        **blob)
+                        BseStorage::BlobP      &blob_out)
 {
   GScanner *scanner = bse_storage_get_scanner (self);
   int bse_fd = -1;
   int tmp_fd = -1;
   char *file_name = g_strdup_format ("%s/bse-%s-%u-%08x", g_get_tmp_dir(), g_get_user_name(), getpid(), 
g_random_int());
 
-  *blob = NULL; /* on error, the resulting blob should be NULL */
+  blob_out = nullptr; /* on error, the resulting blob should be NULL */
 
   parse_or_return (scanner, '(');
   parse_or_return (scanner, G_TOKEN_IDENTIFIER);
@@ -2072,7 +2032,7 @@ bse_storage_parse_blob (BseStorage             *self,
        }
       close (bse_fd);
       close (tmp_fd);
-      *blob = bse_storage_blob_new_from_file (file_name, TRUE);
+      blob_out = bse_storage_blob_new_from_file (file_name, TRUE);
       g_free (file_name);
     }
   else if (g_quark_try_string (scanner->value.v_identifier) == quark_blob_id)
@@ -2080,13 +2040,14 @@ bse_storage_parse_blob (BseStorage             *self,
       gulong id;
       parse_or_return (scanner, G_TOKEN_INT);
       id = scanner->value.v_int64;
-      *blob = NULL;
-      for (auto b : self->data.blobs)
+      blob_out = NULL;
+      for (auto blob : self->data.blobs)
        {
-         if (b->id == id)
-           *blob = bse_storage_blob_ref (b);
+         if (blob->id == id)
+           blob_out = blob;
+;
        }
-      if (!*blob)
+      if (!blob_out)
        {
          g_warning ("failed to lookup storage blob with id=%ld\n", id);
          goto return_with_error;
diff --git a/bse/bsestorage.hh b/bse/bsestorage.hh
index 22aeee4..db7ace5 100644
--- a/bse/bsestorage.hh
+++ b/bse/bsestorage.hh
@@ -37,7 +37,6 @@ typedef enum    /*< skip >*/
 /* --- BseStorage --- */
 typedef struct _BseStorageDBlock   BseStorageDBlock;
 typedef struct _BseStorageItemLink BseStorageItemLink;
-typedef struct _BseStorageBlob     BseStorageBlob;
 typedef void (*BseStorageRestoreLink)   (gpointer        data,
                                          BseStorage     *storage,
                                          BseItem        *from_item,
@@ -65,14 +64,28 @@ struct BseStorage : BseObject {
   gfloat                 osc_freq;
   guint                  n_channels;
 
+  /* storage blob */
+  struct Blob {
+    Bse::Mutex  mutex;
+    char       *file_name;
+    gboolean    is_temp_file;
+    gulong      id;
+
+    ~Blob();
+  };
+
+  typedef std::shared_ptr<Blob> BlobP;
+
   /* C++ allocated data */
   struct Data {
-    std::vector<BseStorageBlob *> blobs;
+    std::vector<BlobP> blobs;
   } data;
 };
 struct BseStorageClass : BseObjectClass
 {};
 
+typedef struct BseStorage::Blob BseStorageBlob;
+
 /* --- compatibility file parsing --- */
 void         bse_storage_compat_dhreset         (BseStorage             *self);
 void         bse_storage_compat_dhmixf          (BseStorage             *self,
@@ -121,7 +134,7 @@ void         bse_storage_put_data_handle        (BseStorage             *self,
                                                  guint                   significant_bits,
                                                  GslDataHandle          *dhandle);
 void         bse_storage_put_blob               (BseStorage             *self,
-                                                 BseStorageBlob         *blob);
+                                                 BseStorage::BlobP       blob);
 void         bse_storage_put_xinfos             (BseStorage             *self,
                                                  gchar                 **xinfos);
 Bse::Error bse_storage_flush_fd               (BseStorage             *self,
@@ -164,18 +177,16 @@ GTokenType   bse_storage_parse_rest             (BseStorage             *self,
                                                  BseTryStatement         try_statement,
                                                  gpointer                user_data);
 GTokenType   bse_storage_parse_blob             (BseStorage             *self,
-                                                 BseStorageBlob        **blob);
+                                                 BseStorage::BlobP      &blob);
 gboolean     bse_storage_check_parse_negate     (BseStorage             *self);
 
 /* --- bse storage blob --- */
 
-BseStorageBlob  *bse_storage_blob_ref               (BseStorageBlob         *self);
-const gchar     *bse_storage_blob_file_name         (BseStorageBlob         *self);
-gboolean         bse_storage_blob_is_temp_file      (BseStorageBlob         *self);
-void             bse_storage_blob_unref             (BseStorageBlob         *self);
-BseStorageBlob  *bse_storage_blob_new_from_file     (const gchar            *file_name,
+const gchar      *bse_storage_blob_file_name         (BseStorage::BlobP      self);
+gboolean          bse_storage_blob_is_temp_file      (BseStorage::BlobP      self);
+BseStorage::BlobP bse_storage_blob_new_from_file     (const gchar           *file_name,
                                                      gboolean                is_temp_file);
-void             bse_storage_blob_clean_files       (void);
+void              bse_storage_blob_clean_files       (void);
 
 /* --- short-hands --- */
 #define bse_storage_get_scanner(s)      ((s)->rstore->scanner)


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]