Let's say we have a C function funA in a library, inside funA it'll call some other functions funB, funC, .etc. It's possible that funB and funC could call funA back. So the question is:
Is it possible to detect this situation just inside funA, something like:
void funA(void) {
if (...) {
// Calling back to funA
}
}
Conclusion
In a single thread environment, static/global variable would work.
In multi-thread environment, would have to depend on TLS support.
Haven't got any answer that can achieve this with just language(C) level tricks
This can be done with a static flag.
When the function is called, if the flag is not set then set it and continue, otherwise return right away. Then at the end of the function, you clear the flag so you can enter it again.
void funcA(void)
{
static int callback = 0;
if (callback) return;
callback = 1;
...
callback = 0;
}
If this needs to work in multiple thread separately you can declare the variable as _Thread_local instead of static.
If it is a single call only, you can have a global/static flag set once this function is called, and check it in the beginning. Or to remove the restriction of being single call, you can reset this flag before the function is returning.
Something like that:
void funA(void) {
static bool used = false;
if (used)
{
printf("It is used!\n");
}
used = true;
// .... Do stuff here, including possible recursion
used = false;
}
Note - this won't work with multithreading - this function is not reentrant..
maybe another approach you can identify the caller:
void func_a(void *ptr);
void func_b(void);
void func_c(void);
void func_a(void *caller)
{
if(caller == func_a)
{
printf("called from func_a\n");
return;
}
if(caller == func_b)
{
printf("called from func_b\n");
return;
}
if(caller == func_c)
{
printf("called from func_c\n");
return;
}
if(caller == NULL)
{
printf("called from somewhere elese - going to call myself\n");
func_a(func_a);
}
}
void func_b()
{
func_a(func_b);
}
void func_c()
{
func_a(func_c);
}
int main()
{
func_b();
func_c();
func_a(NULL);
return 0;
}
With a level of indirection, you can even count the number of times your function has been called:
void func( int count )
{
printf( "Count is %d\n", count );
if ( ... ) // no longer want to recurse...
{
return;
}
func( count + 1 );
}
// wrap the actual recursive call to hide the parameter
void funA()
{
func( 0 );
}
This way, it's fully thread-safe. If you don't want a wrapper function nor a parameter passed, you can use thread-specific storage.
Related
In a function that returns void and has no parameters I want to use two other functions (unfortunately I cannot modify that). The first of these functions calculates the result of an int and I want to pass that result as a parameter to the second function. How could I achieve that? thank you.
void descriptionEdit(void)
{
while(1)
{
int fieldno;
if (!pluFields())
{
break;
}
start_editor(setf, esize);
do
{
//code
} while(fieldno>=0);
saveEditor();
}
}
bool pluFields(void)
{
**edplu** = search_productcode();
if (edplu == 0)
{
return true;
}
}
void saveEditor()
{
if (save_plu(**edplu**, &plu))
{
CloseProductIniFile();
cls();
writeat(30, 6, INV2X3, "Save Confirmed");
}
}
So, I want somehow to use the edplu from pluFields function as a parameter to saveEditor function, I thought to make edplu global variable but I think this is a bad practice
You algorithm is very non-intuitive. However, to get a value of a function and pass to another function do this:
int functionName(int param1) {
// calculate values
return variable_here
}
int value = functionName(param1)
then value will go onto the parameter of your next function, like that
void function2(int value) ...
function2(value)
Let me know if I helped.
I'm beginner with c and have a simple question:
I have a function myfunction() which is called periodically every 100 ms.
Within this function I have to call an other function but only once at the first call at beginn of myfunction(), but no periodically.
void myfunction() // function is called periodically every 100 ms
{
...
mySubfunction(); // this function have to be called only once in the first call of myFunction() and than skipped each time after that.
} ...
How to realize this in c?
Use static? Something along the lines of
void myfunction() // function is called periodically every 100 ms
{
static int once = 1;
if (once) {
mySubfunction();
once = 0;
}
}
The variable once in the example will be initalized only once and retain its value between invocations because of static keyword.
Be aware of implications in multithreaded environment, see this question.
you can have something like
static int flag = 1
void myfunction() // function is called periodically every 100 ms
{
if(flag)
{
mySubfunction();
flag = 0;
}
}
...
on first look task is very simply, can be next code:
void func()
{
static LONG first = TRUE;
if (_InterlockedExchange(&first, FALSE))
{
subfunc();
}
// some code
}
this give 100% guarantee that subfunc() will be called once and only once even if several thread in concurrent call your func()
but what be if // some code depended on result of subfunc ? in this case task become already not trivial. need some synchronization. and here already depended from os or compiler. in Windows, begin from Vista understand this problem and add function InitOnceExecuteOnce - read Using One-Time Initialization
if your subfunc() have no in and out parameters code can be very simply:
BOOL CALLBACK InitOnceCallback(PINIT_ONCE /*InitOnce*/, PVOID /*Parameter*/,PVOID* /*Context*/)
{
subfunc();
return TRUE;
}
void func()
{
static INIT_ONCE once = RTL_RUN_ONCE_INIT;
if (InitOnceExecuteOnce(&once, InitOnceCallback, 0, 0))
{
// somecode
}
// error init
}
also some modern compilers can correct handle static one time initialization. say latest versions of CL. with it code can be next:
void func()
{
static char tag = (subfunc(), 0);
// some code
}
here CL internally call special functions (implemented in CRT) _Init_thread_header, _Init_thread_footer - implementation can be look in crt source code - thread_safe_statics.cpp
This may be more advanced than you're looking for, but you could use function pointers and change which function gets called.
// Function declarations
void mySubfunction(void);
void myNormalfunction(void);
// Function pointer, which can be changed at run time.
static void (*myfunction)(void) = mySubfunction;
void mySubfunction(void)
{
// Do the sub-function stuff.
// Change the function pointer to the normal function.
myfunction = myNormalfunction();
// Do the normal function stuff (if necessary on the first call).
myNormalfunction();
}
void myNormalfunction(void)
{
// Etc.
}
int main(void)
{
int x;
for(x = 0; x < 3; x++)
{
// Call myfunction as you usually would.
myfunction();
}
return 0;
}
I have a problem that i can even start to work on because i don't get it how can be done.
So we have a code
int test_handler() {
printf("Test handler called\n");
return 1;
}
// Test your implementation here
int main()
{
register_irq_handler(30, &test_handler);
do_interrupt(29); // no handler registered at this position, should return zero
do_interrupt(30); // calls handler at position 30, expected output: Test handler called
return 0;
}
I need to make those functions register_irq_handler, do_interrupt(29).
But i have no clue how to start, i am looking for a little help to send me on the right direction.
How i store 30 to point to this function when we don't have a global variable to store that "connection" or i am missing something.
You can't do it without a global variable (why would having a global variable be a problem?).
You probably need something like this:
// array of 30 function pointers (all automatically initialized to NULL upon startup)
static int(*functionpointers[30])();
void register_irq_handler(int no, int(*fp)())
{
functionpointers[no] = fp;
}
int do_interrupt(int no)
{
if (functionpointers[no] != NULL)
{
// is registered (!= NULL) call it
return (*functionpointer[no])();
}
else
{
// not registered, just return 0
return 0;
}
}
Disclaimer
This is non tested non error checking code just to give you an idea.
I have a function() which calls anotherFunction().
Inside anotherFunction(), there is an if statement which, when satisfied returns back to main() and not to function(). How do you do this?
You can't do like that in "standard" C. You can achieve it with setjmp and longjmp but it's strongly discouraged.
Why don't just return a value from anotherFuntion() and return based on that value? Something like this
int anotherFunction()
{
// ...
if (some_condition)
return 1; // return to main
else
return 0; // continue executing function()
}
void function()
{
// ...
int r = anotherFuntion();
if (r)
return;
// ...
}
You can return _Bool or return through a pointer if the function has already been used to return something else
You can't easily do that in C. Your best bet is to return a status code from anotherFunction() and deal with that appropriately in function().
(In C++ you can effectively achieve what you want using exceptions).
Most languages have exceptions which enable this sort of flow control. C doesn't, but it does have the setjmp/longjmp library functions which do this.
You can bypass the normal return sequence in C with the setjmp and longjmp functions.
They have an example at Wikipedia:
#include <stdio.h>
#include <setjmp.h>
static jmp_buf buf;
void second(void) {
printf("second\n"); // prints
longjmp(buf,1); // jumps back to where setjmp was called - making setjmp now return 1
}
void first(void) {
second();
printf("first\n"); // does not print
}
int main() {
if ( ! setjmp(buf) ) {
first(); // when executed, setjmp returns 0
} else { // when longjmp jumps back, setjmp returns 1
printf("main\n"); // prints
}
return 0;
}
I am trying to understand if getcontext/setcontext will work correctly in a specific scenario.
I can see how setcontext() can be used to unwind the stack back to a certain place in history.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
ucontext_t context;
void func(void)
{
setcontext(cp);
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
}
else
{
printf("setcontext has been called\n");
}
}
But I was wondering if after an unwind you can re-wind back to a place that was in the future? I suppose this depends on the getcontext() call captures a copy of the stack and I can't find the exact details in the documentation.
#include <stdio.h>
#include <ucontext.h>
int rollback = 0;
int backToFuture = 0;
ucontext_t context;
ucontext_t futureContext;
void func(void)
{
// Some complex calc
if (some-condition)
{
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
int main(void)
{
getcontext(&context);
if (rollback == 0)
{
printf("getcontext has been called\n");
rollback++;
func();
// eventually always return here.
}
else
{
printf("setcontext has been called\n");
// Do specialized work that needed to be done
// May involve function calls.
//
// I worry that anything the adds new stack frames
// will disrupt the saved state of futureContext
//
// But without detailed information I can not be sure
// if this is an allowed senario.
backToFuture = 1;
setcontext(&futureContext);
}
}
getcontext doesn't copy stack, it only dumps registers (including stack pointer) and a little context data like signal mask, etc.
When you jump down the stack it invalidates the top context. Even if you won't do any function calls think about the signal handler that can execute there. If you want to jump between two stacks you need to makecontext.
I added variable that demonstrates that your code is invalid:
void func(void)
{
// Some complex calc
if (1)
{
volatile int neverChange = 1;
getcontext(&futureContext); // After returning I want to come back
// here to carry on with my work.
printf("neverchange = %d\n", neverChange);
if (backToFuture == 0)
{
setcontext(&context); // rewind to get stuff-done
}
}
// Finishe work
}
On my machine it results in:
getcontext has been called
neverchange = 1
setcontext has been called
neverchange = 32767