Emit detailed signal in Vala - vala

I have the following original C code:
static guint event_signal_id;
struct _MatrixClientIface {
void (*event)(MatrixClient *client, const gchar *room_id, const JsonNode *raw_event, MatrixEvent *event);
}
static void
matrix_client_default_init(MatrixClientIface *iface)
{
event_signal_id = g_signal_new("event",
MATRIX_TYPE_CLIENT,
G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED,
G_STRUCT_OFFSET(MatrixClientIface, event),
NULL, NULL, _matrix_marshal_VOID__STRING_BOXED_OBJECT,
G_TYPE_NONE, 3,
G_TYPE_STRING,
JSON_TYPE_NODE,
MATRIX_TYPE_EVENT);
}
void
matrix_client_incoming_event(MatrixClient *client,
const gchar *room_id,
const JsonNode *raw_event,
MatrixEvent *event)
{
GQuark equark;
equark = g_type_qname(G_TYPE_FROM_INSTANCE(event));
g_signal_emit(client,
event_signal_id, equark,
room_id, raw_event, event);
}
Now I want to transform this to Vala; however, I cannot find a tutorial about emitting signals (defining them appears in tutorials many times). I found GLib.Signal.emit() in the docs, but there is no example there on how to get a GLib.Signal object.
My current interface looks like this:
namespace Matrix {
public interface Client : GLib.Object {
public virtual signal void
#event(string? room_id, Json.Node raw_event, Matrix.Event matrix_event)
{
Quark equark = #event.get_type().qname();
#event.emit(room_id, raw_event, matrix_event);
}
}
This obviously doesn’t work. The questions are:
Am I defining the emitter as I should, at all?
If so, how do I actually emit the event signal with equark as a detail?

I cannot find a tutorial about emitting signals (defining them appears in tutorials many times).
I suspect that you actually have, but missed the significance because emitting signals is so easy. For example, see the Signals section of the Vala Tutorial; emitting is shown (t1.sig_1(5);).
I found GLib.Signal.emit() in the docs, but there is no example there on how to get a GLib.Signal object.
GLib.Signal.emit is the low-level way of emitting signals, and there is basically no reason to ever use it from Vala.
Note that the first argument to emit is a pointer. There are few exceptions (most notably libxml), but for the most part if you ever encounter a pointer in Vala, you're doing something wrong. For the most part that also holds true for quarks; virtually everything you would use quarks for has syntax support in Vala.
Am I defining the emitter as I should, at all?
Nope. For starters, get rid of the method body and the "virtual".
If so, how do I actually emit the event signal with equark as a detail?
All you need is something like this:
namespace Matrix {
public class Client : GLib.Object {
[Signal (detailed = true)]
public signal void #event (string? room_id, Json.Node raw_event, Matrix.Event evt);
}
To emit it, you can do something like:
client.#event[evt.get_type().name()](room_id, raw_event, evt);
To connect:
client.#event[evt.get_type().name()].connect((room_id, raw_event, evt) => {
// Signal with a matching detail received
});
client.#event.connect((room_id, raw_event, evt) => {
// Signal received with *any* value for the detail
});

Related

How to write some arbitrary initialization code in a Dart mixin?

Say I have a package that exposes a mixin that provides some extensibility through an API:
mixin ListenerModifier<T> {
T get value;
void addListener(Callback callback);
void removeListener(Callback callback);
}
Say I want to make a "plugin" based on this mixin:
mixin PreviousValue<T> on ListenerModifier<T> {
late T previous;
const PreviousValue() {
addListener(() => previous = value);
}
}
(You could also have plugins defined in other packages as well, perhaps to expose a Stream<T> getter.)
Then, a user could use any plugins at will, like this:
abstract class MyListener<T> with ListenerModifier<T>, PreviousValue<T> {}
The issue is, mixins can't have constructors like the above PreviousValue assumes. Is there some OOP/architectural way to get around this problem? I initially thought of just forcing users of PreviousValue (for example) to call a registerPreviousValue() method in their MyListener constructor as a workaround, but that is highly error prone.
Related:
How to group mixins in Dart?
How can I initialize a mixin's immutable data in Dart?
Just realized for the particular example I gave, I can use a different sort of plugin system without mixins:
mixin ListenerModifierPluginAPI {
T get value;
void addListener(Callback callback);
void removeListener(Callback callback);
}
abstract class ListenerModifier with ListenerModifierPluginAPI {
T registerPlugin<T>(T Function(ListenerModifierPluginAPI) plugin) => plugin(this);
}
class MyListenerModifier extends ListenerModifier {
late final PreviousValueState previousValueState;
const MyListenerModifier() {
previousValueState = registerPlugin(previousValuePlugin);
}
// ...
}
This may not work for all people though. If someone has a different solution, I am all ears.

Apache Beam Stateful DoFn Periodically Output All K/V Pairs

I'm trying to aggregate (per key) a streaming data source in Apache Beam (via Scio) using a stateful DoFn (using #ProcessElement with #StateId ValueState elements). I thought this would be most appropriate for the problem I'm trying to solve. The requirements are:
for a given key, records are aggregated (essentially summed) across all time - I don't care about previously computed aggregates, just the most recent
keys may be evicted from the state (state.clear()) based on certain conditions that I control
Every 5 minutes, regardless if any new keys were seen, all keys that haven't been evicted from the state should be outputted
Given that this is a streaming pipeline and will be running indefinitely, using a combinePerKey over a global window with accumulating fired panes seems like it will continue to increase its memory footprint and the amount of data it needs to run over time, so I'd like to avoid it. Additionally, when testing this out, (maybe as expected) it simply appends the newly computed aggregates to the output along with the historical input, rather than using the latest value for each key.
My thought was that using a StatefulDoFn would simply allow me to output all of the global state up until now(), but it seems this isn't a trivial solution. I've seen hintings at using timers to artificially execute callbacks for this, as well as potentially using a slowly growing side input map (How to solve Duplicate values exception when I create PCollectionView<Map<String,String>>) and somehow flushing this, but this would essentially require iterating over all values in the map rather than joining on it.
I feel like I might be overlooking something simple to get this working. I'm relatively new to many concepts of windowing and timers in Beam, looking for any advice on how to solve this. Thanks!
You are right that Stateful DoFn should help you here. This is a basic sketch of what you can do. Note that this only outputs the sum without the key. It may not be exactly what you want, but it should help you move forward.
class CombiningEmittingFn extends DoFn<KV<Integer, Integer>, Integer> {
#TimerId("emitter")
private final TimerSpec emitterSpec = TimerSpecs.timer(TimeDomain.PROCESSING_TIME);
#StateId("done")
private final StateSpec<ValueState<Boolean>> doneState = StateSpecs.value();
#StateId("agg")
private final StateSpec<CombiningState<Integer, int[], Integer>>
aggSpec = StateSpecs.combining(
Sum.ofIntegers().getAccumulatorCoder(null, VarIntCoder.of()), Sum.ofIntegers());
#ProcessElement
public void processElement(ProcessContext c,
#StateId("agg") CombiningState<Integer, int[], Integer> aggState,
#StateId("done") ValueState<Boolean> doneState,
#TimerId("emitter") Timer emitterTimer) throws Exception {
if (SOME CONDITION) {
countValueState.clear();
doneState.write(true);
} else {
countValueState.addAccum(c.element().getValue());
emitterTimer.align(Duration.standardMinutes(5)).setRelative();
}
}
}
#OnTimer("emitter")
public void onEmit(
OnTimerContext context,
#StateId("agg") CombiningState<Integer, int[], Integer> aggState,
#StateId("done") ValueState<Boolean> doneState,
#TimerId("emitter") Timer emitterTimer) {
Boolean isDone = doneState.read();
if (isDone != null && isDone) {
return;
} else {
context.output(aggState.getAccum());
// Set the timer to emit again
emitterTimer.align(Duration.standardMinutes(5)).setRelative();
}
}
}
}
Happy to iterate with you on something that'll work.
#Pablo was indeed correct that a StatefulDoFn and timers are useful in this scenario. Here is the with code I was able to get working.
Stateful Do Fn
// DomainState is a custom case class I'm using
type DoFnT = DoFn[KV[String, DomainState], KV[String, DomainState]]
class StatefulDoFn extends DoFnT {
#StateId("key")
private val keySpec = StateSpecs.value[String]()
#StateId("domainState")
private val domainStateSpec = StateSpecs.value[DomainState]()
#TimerId("loopingTimer")
private val loopingTimer: TimerSpec = TimerSpecs.timer(TimeDomain.EVENT_TIME)
#ProcessElement
def process(
context: DoFnT#ProcessContext,
#StateId("key") stateKey: ValueState[String],
#StateId("domainState") stateValue: ValueState[DomainState],
#TimerId("loopingTimer") loopingTimer: Timer): Unit = {
... logic to create key/value from potentially null values
if (keepState(value)) {
loopingTimer.align(Duration.standardMinutes(5)).setRelative()
stateKey.write(key)
stateValue.write(value)
if (flushState(value)) {
context.output(KV.of(key, value))
}
} else {
stateValue.clear()
}
}
#OnTimer("loopingTimer")
def onLoopingTimer(
context: DoFnT#OnTimerContext,
#StateId("key") stateKey: ValueState[String],
#StateId("domainState") stateValue: ValueState[DomainState],
#TimerId("loopingTimer") loopingTimer: Timer): Unit = {
... logic to create key/value checking for nulls
if (keepState(value)) {
loopingTimer.align(Duration.standardMinutes(5)).setRelative()
if (flushState(value)) {
context.output(KV.of(key, value))
}
}
}
}
With pipeline
sc
.pubsubSubscription(...)
.keyBy(...)
.withGlobalWindow()
.applyPerKeyDoFn(new StatefulDoFn())
.withFixedWindows(
duration = Duration.standardMinutes(5),
options = WindowOptions(
accumulationMode = DISCARDING_FIRED_PANES,
trigger = AfterWatermark.pastEndOfWindow(),
allowedLateness = Duration.ZERO,
// Only take the latest per key during a window
timestampCombiner = TimestampCombiner.END_OF_WINDOW
))
.reduceByKey(mostRecentEvent())
.saveAsCustomOutput(TextIO.write()...)

env->ExceptionCheck() in JNA

I am using JNA in my project and my Java JNA Callbacks throw exception in some cases. I want to know from C/C++ code an exception was thrown by last calbback method call. In JNI, one can do it using env->ExceptionCheck() but could not find any equivalent in JNA.
Is there any possibility to achieve this?
The native code calling your callback certainly has no expectation that a Java exception will be raised. There is no guarantee that a JNA callback will be invoked from a containing JVM context. Even if it were, you'd have to establish an out of band channel to pass the exception from the callback to the JVM further up the stack, since you have no guarantees about the calling C code.
Assuming you have Java code -> C code -> callback, I'd recommend you catch all your callback's exceptions, then put them somewhere for the calling Java code to examine after the call.
You could make this happen under the covers with an InvocationMapper, which basically lets you capture and/or modify the results of an interface-mapped call, but it's probably easier just to be explicit about it and wrap the whole thing in a utility function.
For example:
public interface MyLibrary extends Library {
MyLibrary INSTANCE = (MyLibrary)Native.loadLibrary();
interface MyCallback extends Callback {
void invoke();
}
void myFunction(MyCallback callback);
}
Then you provide a utility wrapper:
public void myFunction(final MyCallback callback) {
final List<Exception> exceptions = new List<Exception>();
MyLibrary.INSTANCE.myFunction(new MyCallback() {
public void invoke() {
try {
callback.invoke();
} catch(Exception e) {
exceptions.add(e);
}
}
});
if (exceptions.size() > 0) {
// ...
}
}

Is there a way to pass a primitive parameter by reference in Dart?

I would like to pass a primitive (int, bool, ...) by reference. I found a discussion about it (paragraph "Passing value types by reference") here: value types in Dart, but I still wonder if there is a way to do it in Dart (except using an object wrapper) ? Any development ?
The Dart language does not support this and I doubt it ever will, but the future will tell.
Primitives will be passed by value, and as already mentioned here, the only way to 'pass primitives by reference' is by wrapping them like:
class PrimitiveWrapper {
var value;
PrimitiveWrapper(this.value);
}
void alter(PrimitiveWrapper data) {
data.value++;
}
main() {
var data = new PrimitiveWrapper(5);
print(data.value); // 5
alter(data);
print(data.value); // 6
}
If you don't want to do that, then you need to find another way around your problem.
One case where I see people needing to pass by reference is that they have some sort of value they want to pass to functions in a class:
class Foo {
void doFoo() {
var i = 0;
...
doBar(i); // We want to alter i in doBar().
...
i++;
}
void doBar(i) {
i++;
}
}
In this case you could just make i a class member instead.
No, wrappers are the only way.
They are passed by reference. It just doesn't matter because the "primitive" types don't have methods to change their internal value.
Correct me if I'm wrong, but maybe you are misunderstanding what "passing by reference" means? I'm assuming you want to do something like param1 = 10 and want this value to still be 10 when you return from your method. But references aren't pointers. When you assign the parameter a new value (with = operator), this change won't be reflected in the calling method. This is still true with non-primitive types (classes).
Example:
class Test {
int val;
Test(this.val);
}
void main() {
Test t = new Test(1);
fn1(t);
print(t.val); // 2
fn2(t);
print(t.val); // still 2, because "t" has been assigned a new instance in fn2()
}
void fn1(Test t) {
print(t.val); // 1
t.val = 2;
}
void fn2(Test t) {
t = new Test(10);
print(t.val); // 10
}
EDIT
I tried to make my answer more clear, based on the comments, but somehow I can't seem to phrase it right without causing more confusion. Basically, when someone coming from Java says "parameters are passed by reference", they mean what a C/C++ developer would mean by saying "parameters are passed as pointers".
As dart is compiled into JavaScript, I tried something that works for JS, and guess what!? It worked for dart!
Basically, what you can do is put your value inside an object, and then any changes made on that field value inside that function will change the value outside that function as well.
Code (You can run this on dartpad.dev)
main() {
var a = {"b": false};
print("Before passing: " + a["b"].toString());
trial(a);
print("After passing: " + a["b"].toString());
}
trial(param) {
param["b"] = true;
}
Output
Before passing: false
After passing: true
One of the way to pass the variables by reference by using the values in List. As arrays or lists are Pass by reference by default.
void main() {
List<String> name=['ali' ,'fana'];
updatename(name);
print(name);
}
updatename(List<String> name){
name[0]='gufran';
}
Try this one, This one of the simplest way to pass by reference.
You can use ValueNotifier
And, you can pass it as ValueListenable to classes or methods that needs to know up-to-date value, but should not edit it:
class Owner {
final theValue = ValueNotifier(true);
final user = User(theValue);
...
}
class User {
final ValueListeneble<bool> theValue;
User(this.theValue);
...
}
It provides more functionality than actually needed, but solves the problem.
If ValueNotifier + ValueListenable do not work for you (you want to make sure the client does not listen to every change of the value, or your package is pure Dart package and thus cannot reference Flutter libraries), use a function:
class Owner {
int _value = 0;
int getValue() => _value;
void increase() => _value++;
}
void main() {
final owner = Owner();
int Function() obtainer = owner.getValue;
print(obtainer());
owner.increase();
print(obtainer());
}
Output will be:
0
1
This approach has memory usage related downside: the obtainer will hold the reference to the owner, and this, even if owner is already not referenced, but obtainer is still reachable, owner will be also reachable
and thus will not be garbage collected.
If you do not want the downside, pass the smaller container than the entire owner:
import 'package:flutter/foundation.dart';
class ListenableAsObtainer<T> implements ValueObtainer<T> {
ListenableAsObtainer(this._listenable);
final ValueListenable<T> _listenable;
#override
T get value => _listenable.value;
}
class FunctionAsObtainer<T> implements ValueObtainer<T> {
FunctionAsObtainer(this._function);
final T Function() _function;
#override
T get value => _function();
}
class ValueAsObtainer<T> implements ValueObtainer<T> {
ValueAsObtainer(this.value);
#override
T value;
}
/// Use this interface when the client needs
/// access to the current value, but does not need the value to be listenable,
/// i.e. [ValueListenable] would be too strong requirement.
abstract class ValueObtainer<T> {
T get value;
}
The usage of FunctionAsObtainer will still result in holding the owner from garbage collection, but two other options will not.
Just to make it clear:
void main() {
var list1 = [0,1,2];
var modifiedList1 = addMutable(list1, 3);
var list2 = [0,1,2];
var modifiedList2 = addImmutable(list2, 3);
print(list1);
print(modifiedList1);
print(list2);
print(modifiedList2);
}
List<int> addMutable(List<int> list, int element){
return list..add(element);
}
List<int> addImmutable(List<int> list, int element){
return [...list, element];
}
Output:
[0, 1, 2, 3]
[0, 1, 2, 3]
[0, 1, 2]
[0, 1, 2, 3]
All variables are passed by value. If a variable contains a primitive (int, bool, etc.), that's it. You got its value. You can do with it whatever you want, it won't affect the source value. If a variable contains an object, what it really contains is a reference to that object.
The reference itself is also passed by value, but the object it references is not passed at all. It just stayed where it was. This means that you can actually make changes to this very object.
Therefore, if you pass a List and if you .add() something to it, you have internally changed it, like it is passed by reference. But if you use the spread operator [...list], you are creating a fresh new copy of it. In most cases that is what you really want to do.
Sounds complicated. Isn't really. Dart is cool.

When to use Future.handleexception in Dart and when to try-catch

I'm trying to really get Futures in Dart and I've noticed that just about every example I come across uses handleException to deal with exceptions that complete the Future. Yet the API documentation states "In most cases it should not be necessary to call handleException, because the exception associated with this Future will propagate naturally if the future's value is being consumed. Only call handleException if you need to do some special local exception handling related to this particular Future's value."
So when would I need "special local exception handling"? Could someone explain that in a bit more detail? Is there some code that I honestly can't run easily by letting the exception propagate?
Mads Ager gave me this answer:
Basically, this is the equivalent of having a try-catch in straight-line code:
int doSomethingElse() {
try {
return thisMightFail();
} catch(e) {
return -1;
}
}
void doSomething() {
int value = doSomethingElse();
// operate on value
}
With Futures it is something like this (not tested):
Future<int> doSomethingElse() {
return thisMightFail().transformException((e) => -1);
}
void doSomething() {
doSomethingElse().then((value) {
// operate on value
});
}
So this is for local exception handling instead of global exception handling. If you never use handleException or transformException that would correspond to always dealing with exceptions at the top level in non-async code.

Resources