Create a dynamic rescheduling GSource in JavaScrip

2019-07-27 04:11发布

GLib's main loop supports scheduling callback functions for periodic intervals, using g_timemout_source_new and related functions. The callback will repeatedly be called after the scheduled interval, until it returns false.

I now want to modify this process with a dynamic interval. Instead of just true or false, the callback should be able to return a time value that should pass until its next invocation.

Doing this in C is quite straightforward: A new GSource Type can be created, that only differs from the timeout source in its dispatch function, which then takes into account the return value when setting the next expiration.

Unfortunately, I am programming an extension for the GNOME Shell, so I'm stuck to JavaScript. The main critical point to porting the above strategy to JavaScript seems to be the equivalent of the g_source_new function, new GLib.Source. First, it requires the length of the struct type to initialize, which would be computed by the sizeof operator in C. I do not know how to get this value in JavaScript. In addition, it is an error to attempt the creation of a GSourceFuncs Struct, the second argument to this constructor, which is needed to hold the dispatch function.

gjs> new imports.gi.GLib.SourceFuncs()
Error: Unable to construct struct type SourceFuncs since it has no default constructor and cannot be allocated directly

How can I create a new GSource in JavaScript?

1条回答
爷的心禁止访问
2楼-- · 2019-07-27 04:38

g_source_new() was not really designed for language bindings and should probably be marked to be skipped when generating bindings for JS or Python.

Including your own private C library, accessed via GObject introspection, as you suggest in your other question, is what I would usually do in an app. However, I have no idea if you can do it for a shell extension.

You should quite easily be able to implement what you want in JS, though. Here's a simple example I wrote from memory that seems like it might do what you want:

const Scheduler = new Lang.Class({
    Name: 'Scheduler',
    schedule: function (timeMs, callback, priority=GLib.PRIORITY_DEFAULT) {
        this._callback = callback;
        this._priority = priority;
        GLib.timeout_add(priority, timeMs, this._onTimeout.bind(this));
    },
    _onTimeout: function (
        let nextTimeoutMs = this._callback();
        this.schedule(nextTimeoutMs, this._callback, this._priority);
        return GLib.SOURCE_REMOVE;
    },
});
查看更多
登录 后发表回答