Hah! My debugging didn't fool me. It's more than useful to have something that automatic if you're doing it more than often. And I can exclude debug output for modules directly in the code, something really useful. Anyway, those segfaults and endless loops were simply related to a false cast I didn't end before, so it wasn't a fundamental algorithmic problem at all. But I noticed how incredibly mixed the log time is. Things get printed before they'd occur and so on, something I can only really react on with a qmutex. I guess his time I'll definitely need to wrap a qmutex around it. Can't decipher those rather massively long logs with unknown order and or detailed time stamp.

Edit: I think I found a good solution only requiring a single single debug initialisation by using a qmutex pool I'm occupying dynamically on each debug operation. Therefore, a debug output would be like three function calls with the lock/unlock around. That's totally ok if I can get my output ordered. Furthermore, since the modules will be compiled individually, I can put different debug flags in the header and have their output formatted differently. And that means I can also cut out the synchronization to have a more lightweight functionality. Still, I'd need to use a temporary variable for storing the qmutex adress. I've come across an interesting abuse of parameter evaluation for this. It depends on the parameter evaluation order, so I won't use it in the real code, it's just something I found very interesting. Imagine you're calling the qmutex giving function that'll also lock it, passing it to the qmutex release function as parameter which will then unloc it. To do something with it before it'll be released, you can call your printf function and use it's return value as a generally ignored parameter to the releasing function. There's also a bit of unlock wrapping involved. Let's assume this:

create() as the creator function,
release(qmutex) as the releaser function,
lock(qmutex) for locking,
unlock(qmutex) for unlocking,

to create this:

unlock_and_release(qmutex,integer) { unlock(qmutex); release(qmutex); }
as a wrapper for release with additional int parameter,

create_and_lock() { qmutex = create(); lock(qmutex); return qmutex; }
as the create/lock function to be called first.

So when we have these two, we can pass the printf after the lock occurs if parameters will be evaluated from left to right:

unlock_and_release(create_and_lock(), printf(...))

In case of such an evaluation order, we'd at first create the qmutex, lock it, store it for later, call printf and then passing the printf result together with the qmutex adress. Too bad it won't work this way cause evaluation is not defined in the C standard. Still, wouldn't it be lovely to control some temporary this way? Anway, it wouldn't be as performant as a simple temporary variable. And without initialization, I'd need some sort of ifndef shit with variable definition out of place or a global, mutex-guarded stack for getting local variables. Well, my qmutex pool has a mutex, so I could theoretically abuse this but it's no good solution. It's not worth it, rather use some initialization or so.

No comments: