Re: [Vala] how to *not* automagically copy arrays passed to methods?



On Wed, Dec 21, 2011 at 8:54 AM, Matto Marjanovic <maddog mir com> wrote:

You're right... it is not copied in the example I gave above.  However,
it is copied if the method body produces a closure --- I didn't realize
that that detail changed the behavior (until just now).

Compiling this with "valac -C":

   void foo(uint8[] x) {
     x[0] = 7;
   }
       delegate void Callback();
       void baz(Callback callback) {
     callback();
   }
       void bar(uint8[] buffer) {
     buffer[0] = 77;
     baz(() => { buffer[0] = 23; });
   }

yields the following C code:
   ...
   void foo (guint8* x, int x_length1) {
       guint8* _tmp0_;
       gint _tmp0__length1;
       guint8 _tmp1_;
       _tmp0_ = x;
       _tmp0__length1 = x_length1;
       _tmp0_[0] = (guint8) 7;
       _tmp1_ = _tmp0_[0];
   }
   ...
   void bar (guint8* x, int x_length1) {
       Block1Data* _data1_;
       guint8* _tmp0_;
       gint _tmp0__length1;
       guint8* _tmp1_;
       gint _tmp1__length1;
       guint8* _tmp2_;
       gint _tmp2__length1;
       guint8 _tmp3_;
       _data1_ = g_slice_new0 (Block1Data);
       _data1_->_ref_count_ = 1;
       _tmp0_ = x;
       _tmp0__length1 = x_length1;
       _tmp1_ = (_tmp0_ != NULL) ? _vala_array_dup1 (_tmp0_,
_tmp0__length1) : ((gpointer) _tmp0_);
       _tmp1__length1 = _tmp0__length1;
       _data1_->x = _tmp1_;
       _data1_->x_length1 = _tmp1__length1;
       _tmp2_ = _data1_->x;
       _tmp2__length1 = _data1_->x_length1;
       _tmp2_[0] = (guint8) 7;
       _tmp3_ = _tmp2_[0];
       baz (___lambda0__callback, _data1_);
       block1_data_unref (_data1_);
       _data1_ = NULL;
   }

It looks like the presence of the closure is causing the array to get
dup'ed, and it's being dup'd even before the assignment that occurs
before the closure is constructed.


Yes, that's an unfortunate well-known issue that happens with async methods
too, and it's unfortunately hard to fix due to backward-compatibility. You
can workaround it by assigning the array to an unowned local variable
(impossible with async methods).

-- 
www.debian.org - The Universal Operating System


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