GLib - invoke callback for all instances of a class - callback

I started to look into Glib signals. In my scenario I want to connect several instances of a class to a signal and if one of those instances calls g_signal_emit(...), the provided callback function should be called for all instances of that class. Let me try to explain this with an example.
What I tried is to create two instance of a class A (A0 and A1).
Class A registers a very simple signal in its _class_init function.
file_signals[0] = g_signal_newv("a_signal",
G_TYPE_FROM_CLASS(ACLASS),
G_SIGNAL_ACTION,
NULL /* closure */,
NULL /* accumulator */,
NULL /* accumulator data */,
NULL /* C marshaller */,
G_TYPE_NONE /* return_type */,
0 /* n_params */,
NULL); /* argument types*/
Then I connect a simple callback function (cb_a) for both instances A0 and A1 to the signal "a_signal". (For example in the _instance_init function)
g_signal_connect(A0, "a_signal", (GCallback)cb_a, NULL);
g_signal_connect(A1, "a_signal", (GCallback)cb_a, NULL); ,
where cb_a is a function defined in A.c:
static void cb_a(void)
{
printf("cb_a called!\");
}
What happens now is that if I invoke
g_signal_emit(A0, file_signals[0], 0);
is that only the callback associated to A0 is invoked. I couldn´t figure out how to call the function for each instance of A with e.g. a single call to g_signal_emit(...)?
Any help is appreciated. Thanks.

That’s not how GObject signals work. A signal is a one-to-many notification from a single class instance to all the connected callbacks for that class instance. If you want to emit the A::a_signal signal from several instances of the class, you need to call g_signal_emit() for each of those instances.
Note that g_signal_emit() is only meant to be called from within the implementation of a class, not from code outside that class.
One approach to your problem is to have a separate class (let’s call it Signaller) with a signal on it, to store a reference to a single instance of Signaller within A0 and A1, and to connect a_cb to that instance within each of A0 and A1. To notify all instances of the A class, emit Signaller::a_signal on the single Signaller instance.
However, without more concrete information about the particular problem you’re trying to solve, it’s hard to say what the right architecture is. My suggestion above may not be the most appropriate solution.

Related

Matlab: how to access object values inside an eventhandler?

I am trying to raise an event in Matlab. It is working, but not as i expected. What is going on is that the source object is passed as parameter do the event handler and i can't access my object properties inside the event handler.
Here is my class:
classdef MyClass < handle
properties
Name = 'a';
end
events
Changed
end
methods
function obj = MyClass(current)
if exist('current','var')
addlistener(current,'Changed',#ChangedHandle);
end
end
function obj = Change(obj,value)
notify(obj,'Changed');
end
function obj = ChangedHandle(obj,value)
disp(obj.Name);
end
end
end
These are the command lines to reproduce whats going on:
a = MyClass();
b = MyClass(a);
b.Name = 'b';
a.Change(3);
This is returning "a" and i want it to return "b".
Regards
The listener callback you specify receives details of the object raising the event. The fact that the listener has been created during the creation of a different object is not an intrinsic property of the listener – unless you effectively embed this in the design of your callback.
In your example, #ChangedHandle only works as a callback because it happens to be a method of the class current belongs to. If a and b belonged to different classes the problem would be more obvious: if ChangedHandle was a method only of a, it wouldn't know anything about the Name property of b. And if only a method of b, the listener bound to a would have only the function handle without any reference to the instance b of the class to which ChangeHandle belongs.
As described in the listener callback documentation you can use a method of the specific object instance current as an event listener using the syntax #current.ChangedHandle.
This method then receives callback arguments in the format callbackMethod(obj,src,evnt), so you need to add an argument to the definition of ChangedHandle. The first argument obj will be the instance referenced by current when the listener is created, so the line disp(obj.Name) will then produce the intended result without modification.
The reference to a received by the callback in the example will still be passed to the new callback – this is a fundamental behaviour of listener callbacks – but it will now be accessible from the second argument src.
In your addlistener code you are not telling the listener which object you want to call the method on, so what Matlab does it will apply the listener to the current object since thats all that was passed into the function, you can check this by changing the code to:
addlistener(current,'Changed',#(h,evt)current.ChangedHandle);
if you want it to run the code for the other class b (obj), then you use:
addlistener(current,'Changed',#(h,evt)obj.ChangedHandle);

UVM- run test() in top block and Macros

I'm reading the following guide:
https://colorlesscube.com/uvm-guide-for-beginners/chapter-3-top-block/
In Code 3.2 line 24- run_test();
I realized that it supposed to execute the test, but how it know which test, and how, and why should I write it in the top block.
In Code 4.1 lines 11-14 (https://colorlesscube.com/uvm-guide-for-beginners/chapter-4-transactions-sequences-and-sequencers/):
`uvm_object_utils_begin(simpleadder_transaction)
`uvm_field_int(ina, UVM_ALL_ON)
`uvm_field_int(inb, UVM_ALL_ON)
`uvm_field_int(out, UVM_ALL_ON)
`uvm_object_utils_end
Why should I add the "uvm_field_int" , what would happend if i didn't add them, and what is "UVM_ALL_ON"?
run_test is a helper global function , it calls the run_test function of the uvm_root class to run the test case. There are two ways by which you can pass the test name to the function.The first is via the function argument and the second is via a command line argument. The command line argument takes precedence over the test name passed via the function argument.
+UVM_TESTNAME=YOUR_TEST_NAME
run_test("YOUR_TEST_NAME");
run_test function in the uvm_root uses the factory mechanism to create the appropriate instance of the umm_test class and so the test case must register itself with the factory using the macro `uvm_component_utils for the factory mechanism (create_component_by_name) to function.
class YOUR_TEST_NAME extends umm_test ;
// register the class with the factory
// so that run_test can find this class when the
// string test_name is passed to it.
`uvm_component_utils(YOUR_TEST_NAME)
.....
endclass
The run_test function then kicks of the uvm_phases (..,build_phase,connect_phase,...) starting the uvm portion of the simulation. There should be no time ticks consumed before the run_phase starts , so it is essential that run_test case is called in the initial block itself. Also we want the uvm and test bench to be ready to drive and receive data as soon as the RTL is ready for which it is essential that we start the run_test at the earliest. Any delay in doing so will generate an error.
`uvm_field_int/uvm_field_object/.. are called field automation macros. They are not mandatory in the class definition and are provided as a helper macros to ease the use of many common/routine functions of the uvm_object. Examples of thse functions in uvm_object are - copy,compare,pack,unpack,print, etc and these macros generate code to automatically use these functions.
If you are not using the uvm_object common functions leaving out these macros from the class definition will not produce any errors.
In case you implement you own version of the common operations you can also leave out these macros from the class.
UVM_ALL_ON - enables all functions like compare/copy/... to be implemented for the particular field.
link with examples -
http://www.testbench.in/UT_04_UVM_TRANSACTION.html
For example the uvm_object has a compare function which compare two instances of the same class and return true if all the variables in the class are equal.
virtual function bit do_compare( uvm_object rhs, uvm_comparer comparer );
.....
// return 1 if all the variables match
return ( super.do_compare( rhs, comparer ) &&
this.var_1 == rhs.var_1 &&
this.var_2 == rhs.var_2 &&
......
this.var_n == rhs.var_n );
endfunction: do_compare
// use in main code
if ( new_class.compare(old_classs) )
...
//instead of
if ( new_class.var1 == old_class.var1 && new_class.var2 == old_class.var2 && ... new_class.varn == old_class.varn )
...
The above compare has to be written for each class and updated and maintained for every new variable that is added to the class. This could become error prone as newer variables are added. A similar process has to be followed for all the standard functions uvm_object provides.
The field automation macro generates function to address all these functionality automatically. So doing a do_print for a class with the macros will print out all the fields without explicitly writing any code for it.
// compare/print/.. functions for class simpleadder_transaction are provided by using `uvm_field_int macro.
`uvm_object_utils_begin(simpleadder_transaction)
`uvm_field_int(ina, UVM_ALL_ON)
`uvm_object_utils_end
BUT a word of caution , the use of these macros are discouraged as they add a significant amount of code into the class.. Most of these functions may not be needed by the class yet they get generated by default.
run_test is defined in the documentation (link) as:
virtual task run_test (
string test_name = ""
)
So, in principle, you can state there the test name as a string. But what's usually done is to pass it in the command line of your simulator using the argument: +UVM_TESTNAME=TEST_NAME
The uvm_object macros are a bit more complicated. They generate several methods and more importantly they register the object in the UVM factory, which is what makes them necessary (at least if you are using, as you should, the factory to create them). Citing from the UVM Class Reference documentation (Section 20.2 Component and Object Macros):
Simple (non-parameterized) objects use the uvm_object_utils* versions,
which do the following:
Implements get_type_name, which returns TYPE as a string
Implements create, which allocates an object of type TYPE by calling its constructor with no arguments. TYPE’s constructor, if
defined, must have default values on all it arguments.
Registers the TYPE with the factory, using the string TYPE as the factory lookup string for the type.
Implements the static get_type() method which returns a factory proxy object for the type.
Implements the virtual get_object_type() method which works just like the static get_type() method, but operates on an already
allocated object.

How to append request contexts while they have different receiver implementation

In google io 2011, David Chandler mentioned that you can chain different request context by using append() method,but in practice, I don't know how to chain them up while they have different receiver,using to() and then fire()?
Please help.
There are two kinds of receivers: the ones bound to each method invocation (that you pass to the Request's to() method), and the context-level one (that you pass to the RequestContext's fire() method). The Request's fire(Receiver) method is a short-hand for to(receiver).fire(), i.e. it binds the Receiver to the method.
The method-level receivers depend on the method only, their generic parameterization depends on the method's return value (the generic parameterization of the Request or InstanceRequest), so whether you append() several RequestContexts together changes absolutely nothing.
The context-level receiver is always parameterized with Void. When you append() contexts together, they actually form a single context with several interfaces, so you only call fire() once, on any one of the appended contexts.
Now let's go back to the basics: without using append(), you can only batch together calls for methods that are declared on the context interface. If you have two distinct context interfaces you want to use, you have to make two fire(), i.e. two HTTP requests. The introduction of append() allows you to batch together calls for methods declared on any context interface: simply append a context to another one and the calls on both contexts will be batched together in the same HTTP request, triggered by a unique fire() on any one of the context being appended.
Now into the technical details: internally, a context is nothing more than a thin wrapper around a state object. When you edit() or create() a proxy, you add it to the internal state, and when you call a service method, the method name (actually, its obfuscated token) and the arguments are captured and pushed to the state as well. When you append() a context, you're only making it share its internal state with the one of the context you append it to. That way, when you call a service method on the appended context, its pushed on the exact same state as the one of the other context, and when you fire() any one of them, the state is serialized into a single HTTP request.
Note that, to append a context, its own internal state has to be empty, otherwise an exception will be raised, as the state would be thrown away to be replaced by the one of the other context.
In brief, and in practice:
FirstContext first = rf.first();
SomeProxy proxy = first.create(SomeProxy.class);
...
SecondContext second = first.append(rf.second());
OtherProxy other = second.create(OtherProxy.class);
other.setSome(proxy);
...
second.saveAndReturnSelf(other).to(new Receiver<OtherProxy>() {
...
});
...
first.fire();
Note that the line that creates and appends the second context could equally be written:
SecondContext second = rf.second();
first.append(second);
The append method returns its argument as a convenience, but it's really the same value you passed as the argument. This is only to allow writing the one-liner above, instead of being forced to use the two-liner.

Execute class method or function(static method) on main thread from another thread C/C++

Is it possible to create some of equivalent in iOS objective-c "performSelectorOnMainThread" functionality on C/C++ for Windows and UNIX, not iOS.
Many thanks.
No, you'll have to roll your own. One way to do this would be to keep a global function pointer that your main thread checks each iteration of the main loop. For example:
// Global variables
pthread_mutex_t gMutex = PTHREAD_MUTEX_INITIALIZER;
void (*gFuncPtr)(void*);
void *gFuncArg;
// Your program's main loop in the main thread
while(programIsRunning())
{
// If we have a function to call this frame, call it, then do the rest of
// our main loop processing
void (*funcPtr)(void*);
void *funcArg;
pthread_mutex_lock(&gMutex);
funcPtr = gFuncPtr;
funcArg = gFuncArg;
gFuncPtr = NULL;
pthread_mutex_unlock(&gMutex);
if(funcPtr != NULL)
(*funcPtr)(funcArg);
// Rest of main loop
...
}
// Call this function from another thread to have the given function called on
// the main thread. Note that this only lets you call ONE function per main
// loop iteration; it is left as an exercise to the reader to let you call as
// many functions as you want. Hint: use a linked list instead of a single
// (function, argument) pair.
void CallFunctionOnMainThread(void (*funcPtr)(void*), void *funcArg)
{
pthread_mutex_lock(&gMutex);
gFuncPtr = funcPtr;
gFuncArg = funcArg;
pthread_mutex_unlock(&gMutex);
}
For Windows instead of POSIX, use CRITICAL_SECTION, EnterCriticalSection, and LeaveCriticalSection instead of pthread_mutex_t, pthread_mutex_lock, and pthread_mutex_unlock respectively, and don't forget to initialize and deinitialize the critical section appropriately.
If it's all on the iPhone, you can either use CFRunLoopAddSource(), or provide a C++-friendly wrapper over performSelectorOnMainThread by having an Objective C++ file (extension .mm). I recommend the second way.
If it's on a different platform - please specify the platform. Windows has such means (APC and messages).
No platform-indepenent way, since there's no such thing as platform-independent threads.
If the thing has to run on both unix and windows (and you are using c++), use boost for threads & mutexes

c and objective-c variables

Let me see if I can articulate what I'm trying to do... I'll distill it to the core issue.
I have an objective-c program and a c callback function. The context is I am using cocos2d and chipmunk physics with the iphone sdk. What I am trying to do is update "score" upon a collision between a bullet and a monster. Everything works fine except for updating the score.
the game logic is in obj-c but the actual collision logic is done in a c function that gets called when things collide. For example, it is there that I render the flames/explosion of the collision. It is also there that I want to update the score.
Here's the problem:
But score is an instance variable of the "GAME" object and I do not have visibility into that instance variable. I suppose I can pass into the c function another parameter by reference called &addscore or something, but was wondering if there is a more obvious way to do it since there might be a bunch of other variables beyond 'score' that must be updated upon the collission.
the net is I need variables in the object to be seen by the c function, and vice versa: those variables set in the function to be seen in the object.
thanks in advance.
Your knowledge and thoughts about gaining access to Obj-C instance variables within C code by passing them by reference seems correct.
If you need to pass a number of variables I assume they collectively make up some kind of "game state" description. Perhaps these could be grouped into a seperate object or structure and passed into the C function via a single parameter?
As an example, the following class:
typedef struct GameState {
int score;
int numberOfBulletsLeft;
} GameState;
#interface GAME : NSObject {
GameState state;
}
...
#end
Would work well with a C function such as the following
void myCFunctionThatDoesCollisiondetectionEtc(GameState * state) {
NSLog(#"You have %d bullets left", state->numberOfBulletsLeft);
}
If your existing GAME object has suitable properties or messages, you may even be able to do something like the following, where you simply pass your entire Objective-C object:
void myCFunctionThatDoesCollisionDetectionEtc(GAME * myGame) {
if (...)
[myGame increaseScore:50];
else
[myGame decreaseScore:50];
}
A third alternative would be to change the return value of your C function to indicate if a collision has been detected and then leave it up to the Objective-C code within the GAME class to update the score and any other actions which may need to occur.
To improve on that last answer a bit more, you can do the following:
cpSpaceAddCollisionPairFunc( space, 1, 2, (cpCollFunc)functionName, game);
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, GameClass *game) {
[game doSomethingToScoreSomething];
}
No need to cast the pointer inside of the function, you can cast the function pointer instead. That's what I've done internally with the Chipmunk source and it's a lot cleaner.
No, you do not need variables in your object to be visible by the function. That breaks encapsulation, and it's a bad idea. When you want an object to do something (like changing some internal value such as the score) you should provide a method to accomplish that effect.
If you allow code outside your class to alter your instance variables, then you're throwing away a key advantage of object-oriented programming.
If the game object is a singleton you can access it from any scope (which includes your C callback). You would make a singleton if you only ever want one instance of some object to exist. A singleton can always be reached from anywhere by sending a message to the class to retrieve the singleton instance:
[Game sharedGameInstance];
Alternatively, chipmunk allows for you to pass a void * data to the callback. This is to accommodate the programmer to send information he needs to the callback.
You can send a pointer to your game object instance in that void * to the callback, like so:
cpSpaceAddCollisionPairFunc( space, 1, 2, &functionName, (void *)game );
void functionName( cpShape *a, cpShape *b, cpContact *contacts, int numContacts, cpFloat normal_coef, void *data ) {
GameClass * game = (GameClass *)data;
// do whatever you need here. You can call messages on game as per usual.
}