Search code examples
vala

How to pass GLib.Thread arguments


Typical GLib.Thread examples i found are a type of:

new Thread<void*>(null,() => { return null; };

This works well when not passing arguments to the thread.

The GLib.Thread docs show an example using a class instance to provide thread data.

// Start a thread:
MyThread my_thread = new MyThread (10);
Thread<int> thread = new Thread<int>.try ("My fst. thread", my_thread.run);

Is this the only way to pass arguments to threads? The docs also say:

The new thread starts by invoking func with the argument data. Data:
an argument to supply to the new thread.

Where is the argument data specified and how is it accessed within the thread?

For example, imagine this callback signature:

private string cbThreadSample(int id,string msg, Socket client_socket){
   //...do stuff
   return "good job";
   }

my thought for usage was something like:

new GLib.Thread<string>("my thread sample",this.cbThreadSample,id,msg, client_socket);

Obviously this does not compile. What is the correct way of creating a thread with this callback signature?


Solution

  • The data argument is part of the delegate you have passed into the thread.

    If you do:

    new GLib.Thread<string>("my thread sample",
      () => this.cbThreadSample(id,msg, client_socket));
    

    In the underlying C code, this will be translated to something like this:

    struct lambda0__data {
      WhateverClass *self;
      int id;
      gchar *msg;
      GSocket client_socket;
    };
    
    void *lambda0__func(lambda0__data *context) {
       whatever_class_cbThreadSample(context->self,
         context->id, context->msg,
         context->client_socket));
        return NULL;
    }
    
    ...
    lambda0__data *thread_data = g_new0(lambda0__data);
    thread_data->self = self;
    thread_data->id = id;
    thread_data->msg = gstrdup(msg);
    thread_data->client_socket = g_object_ref(socket);
    g_thread_try_new("my thread sample", lambda0__func, thread_data);
    

    The data parameter passed is associated with the delegate (lambda or method reference). In the case of using a subclass MyThread, the instance of MyThread will be passed as the data parameter.

    This isn't directly accessible. It's passed implicitly as either the captures of a lambda or this of an instance.

    Also, if you're actually using this for a request handler, you probably want to use a ThreadPool.