Re: [Vala] Threads and closures problem

2011-07-10 Thread Jim Peters
On Thu, January 14, 2010 21:22, JM wrote:
 Looks like closures and threads are incompatible right now.

I came across exactly the same issue when trying to pass a parameter
to a thread.  The problem is to maintain a reference to the closure
which can be released when the closure is no longer needed.  This is
the best work-around I've found so far, but it involves creating a
circular reference loop:

   private static class BoxedThreadFuncT {
  public ThreadFuncT? run;
   }

   [...]

  // 'param' is the value I want to pass to the thread
  var param = [...];
  BoxedThreadFuncvoid* btf = new BoxedThreadFuncvoid*();
  btf.run = () = {
 process(param);
 var tmp = (owned) btf; tmp.run = null;   // Cleanup
 return null;
  };
  try {
 Thread.createvoid*(btf.run, false);
  } catch (ThreadError e) {
 btf.run = null;   // Cleanup
 [...]
  }

So 'btf' keeps the reference to the closure alive, as it is itself
referenced by the closure (circular ref loop).  In theory 'btf.run =
null' should destroy both 'btf' and the closure, but in that case the
C code tries to reference through the now-destroyed closure and causes
a segfault, which is why this code goes via 'tmp' within the closure.
Hopefully I'm not breaking any rules.

Jim

-- 
 Jim Peters  (_)/=\~/_(_) j...@uazu.net
  (_)  /=\  ~/_  (_)
 Uazú  (_)/=\~/_(_)http://
 in Peru(_)  /=\  ~/_  (_)uazu.net
___
vala-list mailing list
vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-15 Thread Jan Hudec

On Thu, January 14, 2010 21:22, JM wrote:
 Hi all
 Looks like closures and threads are incompatible right now.
 This is the ccode generated from vala.

Of course. You can't just add 'owned' to a delegate parameter and think
things will work -- it changes the corresponding C signature by adding
the destroy notify callback.

Now unfortunately neither g_thread_create NOR g_thread_create_full have
destroy_notify function, so they CAN'T be bound with owned delegate.
You'll have to keep the closure around yourself.

I believe it makes sense to file a feature request against Glib to add
a variant of g_thread_create with destroy notify, but of course it will
take time before it gets to a stable release.

-- 
- Jan Hudec b...@ucw.cz

___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-15 Thread Jan Hudec

On Thu, January 14, 2010 01:12, JM wrote:
 Hi Łukas
 Thanks for your reply! This somehow does not work as soon as I add
 another thread.

 class HHH : Object {
 private ThreadFunc f;
 public void run() {
 string test = test;
 try {
 f = ()= { print(in thread : %s \n, test); };

When you call this second time, you *replace* the closure created the
first time around, causing it to be deleted. Than it's memory probably
gets reused when creating the thread (in the first post you didn't do
any allocation after the thread was created, so there was nothing to
overwrite the data), causing the first thread to fail.

You need to have one variable for each closure you create, or a collection
of them. Note, that delegates are not compatible with generics, but you can
wrap them in class instances and those are. I don't know whether explicit
boxing (append ? to the type - does the trick with double and struct types)
is supported for delegates or not.

 Thread.create(f, false);
 }
 catch(GLib.ThreadError e) {
 print(%s, e.message);
 }
 }

 public static MainLoop loop;

 public static int main() {
 loop = new MainLoop(null, false);
 var h = new HHH();
 h.run();
 h.run(); // Another thread
 loop.run();
 return 0;
 }
 }

 // valac --thread hhh.vala

 I get:

 $./hhh
 in thread : test
 in thread : (null)

 Ideas?
 Regards,
 JĂśrn

-- 
- Jan Hudec b...@ucw.cz

___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-15 Thread JM
Am Freitag, den 15.01.2010, 12:16 +0100 schrieb Jan Hudec:

 Of course. You can't just add 'owned' to a delegate parameter and think
 things will work -- it changes the corresponding C signature by adding
 the destroy notify callback.
 
Hello Jan
I didn't realize the incompatibility in the beginning. 
But then I did and sent the mail that shows that c signatures do not fit
with g_thread_create in case a owned keyword is added. I thought that
was clear.
That's why I sent that mail and gave up on closures and threads. You
just repeated what I found out.

But thanks for the idea with the feature request for glib. 
Regards Jörn


___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-14 Thread JM
Hello all
Thanks Łukasz for your reply! 
That explains the behavior. But then, shouldn't a thread also own the
thread function or will that lead to other issues?

Should the vapi binding be:
public static weak Thread create (owned ThreadFunc func, bool joinable)
throws ThreadError;

instdead of:
public static weak Thread create (ThreadFunc func, bool joinable) throws
ThreadError;

???

Then the closure handled by the thread will maybe not be freed too
early.

I really hope to clear all this because that looks like the only way to
pass some parameters to a threadfunction.
Regards, 
Jörn


Am Donnerstag, den 14.01.2010, 11:06 +0100 schrieb Łukasz Pankowski:
 JM interfl...@gmx.net writes:
 
  If I do the same thing with an Idle, the behavior is significantly
  different, as the block data is not destroyed as soon as the run()
  function is left. Why is that?
 
  Well working example:
 
  class HHH : Object {
  public void run() {
  string test = test;
  Idle.add(() = { print(in idle : %s \n, test); return 
  false;});
 
 if you look into glib-2.0.vapi Idle.add is declared as:
 
   public static uint add (owned SourceFunc function, [CCode (pos 
 = 0.1)] int priority = Priority.DEFAULT_IDLE);
 
 so the add() is declared to own the function past to it, so the closure data 
 will be kept alive
 
  }
 
  public static MainLoop loop;
 
  public static int main() {
  loop = new MainLoop(null, false);
  var h = new HHH();
  h.run();
  h.run();
  h.run();
  h.run();
  loop.run();
  return 0;
  }
  }
 
  // valac closuretest.vala


___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-14 Thread JM
Hi all
Looks like closures and threads are incompatible right now.
This is the ccode generated from vala.
VALA:
Thread.create( ()= { Thread.usleep(1000); print(in thread : %s \n,
test); }, false);

CCODE:
g_thread_create (__lambda0__gthread_func, _data1_, FALSE,
_inner_error_);

CCODE (with owned ThreadFunc in vapi):
g_thread_create (__lambda0__gthread_func, block1_data_ref (_data1_),
block1_data_unref, FALSE, _inner_error_);

As you can see, the second ccode produces one too many args for the
g_thread_create function, while for the first case the '_data1_' struct
is immediately freed as soon as the calling function is finished.

I don't really know how and if this can be fixed.
I thought this would be an easy option to hand over some parameters to a
thread function. 
Are there other good options to put parameters to threads without
accessing class variables + mutex locking?
Regards
Jörn



Am Donnerstag, den 14.01.2010, 12:40 +0100 schrieb JM:
 Hello all
 Thanks Łukasz for your reply! 
 That explains the behavior. But then, shouldn't a thread also own the
 thread function or will that lead to other issues?
 
 Should the vapi binding be:
 public static weak Thread create (owned ThreadFunc func, bool joinable)
 throws ThreadError;
 
 instdead of:
 public static weak Thread create (ThreadFunc func, bool joinable) throws
 ThreadError;
 
 ???
 
 Then the closure handled by the thread will maybe not be freed too
 early.
 
 I really hope to clear all this because that looks like the only way to
 pass some parameters to a threadfunction.
 Regards, 
 Jörn
 
 
 Am Donnerstag, den 14.01.2010, 11:06 +0100 schrieb Łukasz Pankowski:
  JM interfl...@gmx.net writes:
  
   If I do the same thing with an Idle, the behavior is significantly
   different, as the block data is not destroyed as soon as the run()
   function is left. Why is that?
  
   Well working example:
  
   class HHH : Object {
 public void run() {
 string test = test;
 Idle.add(() = { print(in idle : %s \n, test); return 
   false;});
  
  if you look into glib-2.0.vapi Idle.add is declared as:
  
  public static uint add (owned SourceFunc function, [CCode (pos 
  = 0.1)] int priority = Priority.DEFAULT_IDLE);
  
  so the add() is declared to own the function past to it, so the closure 
  data will be kept alive
  
 }
  
 public static MainLoop loop;
  
 public static int main() {
 loop = new MainLoop(null, false);
 var h = new HHH();
 h.run();
 h.run();
 h.run();
 h.run();
 loop.run();
 return 0;
 }
   }
  
   // valac closuretest.vala
 
 
 ___
 Vala-list mailing list
 Vala-list@gnome.org
 http://mail.gnome.org/mailman/listinfo/vala-list


___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


[Vala] Threads and closures problem

2010-01-13 Thread JM
Hi all
I just played around with closures as thread functions. I'm not sure if
this example is supposed to work, but at least it compiles. 


class HHH : Object {
public void run() {
string test = test;
try {
Thread.create( ()= { print(in thread : %s \n, test); 
}, false);
}
catch(GLib.ThreadError e) {
print(%s, e.message);
}
}

public static MainLoop loop;

public static int main() {
loop = new MainLoop(null, false);
var h = new HHH();
h.run();
loop.run();
return 0;
}
}

// valac --thread hhh.vala

Problem is that the value in the closure is lost somehow.
The output of this test program is:

$./hhh
in thread : (null) 

Anybody knows how this should be handled?
Regards
Jörn

___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-13 Thread Łukasz Pankowski
JM interfl...@gmx.net writes:

 Hi all
 I just played around with closures as thread functions. I'm not sure if
 this example is supposed to work, but at least it compiles.


 class HHH : Object {
   public void run() {
   string test = test;
   try {
   Thread.create( ()= { print(in thread : %s \n, test); 
 }, false);

Hi

if you look into a hhh.c generated with

valac -C --thread hhh.vala

you can see that the clause data is destroyed at the end of HHH.run
(hhh_run in C) as the closure function is no longer referenced when
exiting HHH.run, you have to assign the closure to a variable to keep
it alive, for example

class HHH : Object {
ThreadFunc f;
public void run() {
string test = test;
try {
f = ()= { Thread.usleep(1000); print(in thread : %s \n, 
test); };
Thread.create(f, false);

it gives a compilation warning but works (I needed to add usleep to observe 
your problem)

$ valac --thread --pkg posix temp.vala
hhh.vala.c: In function ‘hhh_run’:
hhh.vala.c:111: warning: assignment from incompatible pointer type


 Anybody knows how this should be handled?
 Regards
 Jörn
___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-13 Thread JM
Hi Łukas
Thanks for your reply! This somehow does not work as soon as I add
another thread. 

class HHH : Object {
private ThreadFunc f;
public void run() {
string test = test;
try {
f = ()= { print(in thread : %s \n, test); };
Thread.create(f, false);
}
catch(GLib.ThreadError e) {
print(%s, e.message);
}
}

public static MainLoop loop;

public static int main() {
loop = new MainLoop(null, false);
var h = new HHH();
h.run();
h.run(); // Another thread
loop.run();
return 0;
}
}

// valac --thread hhh.vala

I get:

$./hhh
in thread : test 
in thread : (null) 

Ideas?
Regards,
Jörn

PS: Sorry for double post, but I forgot the list

Am Donnerstag, den 14.01.2010, 00:38 +0100 schrieb Łukasz Pankowski:
 JM interfl...@gmx.net writes:
 
  Hi all
  I just played around with closures as thread functions. I'm not sure if
  this example is supposed to work, but at least it compiles.
 
 
  class HHH : Object {
  public void run() {
  string test = test;
  try {
  Thread.create( ()= { print(in thread : %s \n, test); 
  }, false);
 
 Hi
 
 if you look into a hhh.c generated with
 
 valac -C --thread hhh.vala
 
 you can see that the clause data is destroyed at the end of HHH.run
 (hhh_run in C) as the closure function is no longer referenced when
 exiting HHH.run, you have to assign the closure to a variable to keep
 it alive, for example
 
 class HHH : Object {
   ThreadFunc f;
   public void run() {
   string test = test;
   try {
   f = ()= { Thread.usleep(1000); print(in thread : %s \n, 
 test); };
   Thread.create(f, false);
 
 it gives a compilation warning but works (I needed to add usleep to observe 
 your problem)
 
 $ valac --thread --pkg posix temp.vala
 hhh.vala.c: In function ‘hhh_run’:
 hhh.vala.c:111: warning: assignment from incompatible pointer type
 
 
  Anybody knows how this should be handled?
  Regards
  Jörn


___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-13 Thread JM
The problem gets worse, as soon as I use a class variable:

class HHH : Object {
private ThreadFunc f;
public int t;
public void run() {
t = 4;
string test = test;
try {
f = ()= { Thread.usleep(1000); print(in thread : %s 
%d \n, test,
t); };
Thread.create(f, false);
}
catch(GLib.ThreadError e) {
print(%s, e.message);
}
}

public static MainLoop loop;

public static int main() {
loop = new MainLoop(null, false);
var h = new HHH();
h.run();
loop.run();
return 0;
}
}

This leads to a segmentation fault. Am I doing something wrong here?

Regards,
Jörn


Am Donnerstag, den 14.01.2010, 00:38 +0100 schrieb Łukasz Pankowski:
 JM interfl...@gmx.net writes:
 
  Hi all
  I just played around with closures as thread functions. I'm not sure if
  this example is supposed to work, but at least it compiles.
 
 
  class HHH : Object {
  public void run() {
  string test = test;
  try {
  Thread.create( ()= { print(in thread : %s \n, test); 
  }, false);
 
 Hi
 
 if you look into a hhh.c generated with
 
 valac -C --thread hhh.vala
 
 you can see that the clause data is destroyed at the end of HHH.run
 (hhh_run in C) as the closure function is no longer referenced when
 exiting HHH.run, you have to assign the closure to a variable to keep
 it alive, for example
 
 class HHH : Object {
   ThreadFunc f;
   public void run() {
   string test = test;
   try {
   f = ()= { Thread.usleep(1000); print(in thread : %s \n, 
 test); };
   Thread.create(f, false);
 
 it gives a compilation warning but works (I needed to add usleep to observe 
 your problem)
 
 $ valac --thread --pkg posix temp.vala
 hhh.vala.c: In function ‘hhh_run’:
 hhh.vala.c:111: warning: assignment from incompatible pointer type
 
 
  Anybody knows how this should be handled?
  Regards
  Jörn


___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list


Re: [Vala] Threads and closures problem

2010-01-13 Thread JM
If I do the same thing with an Idle, the behavior is significantly
different, as the block data is not destroyed as soon as the run()
function is left. Why is that? 

Well working example:

class HHH : Object {
public void run() {
string test = test;
Idle.add(() = { print(in idle : %s \n, test); return 
false;});
}

public static MainLoop loop;

public static int main() {
loop = new MainLoop(null, false);
var h = new HHH();
h.run();
h.run();
h.run();
h.run();
loop.run();
return 0;
}
}

// valac closuretest.vala

___
Vala-list mailing list
Vala-list@gnome.org
http://mail.gnome.org/mailman/listinfo/vala-list