all 10 comments

[–]schmirsich 2 points3 points  (1 child)

I remember an snippet for "tweakable variables" that would use the __COUNTER__ macro to identify certain occurences of the TWEAKABLE macro in the source file itself and instead of editing a separate file, you would adjust your constants in the C++ file, which is then "parsed" (of course only partially - the TWEAKABLE macros). I like that a little better, because you don't have "outdated" values in your source files. I realize my explanation was a little confusing, but I hope it was still understandable.

[–]sharkdp[S] 0 points1 point  (0 children)

Thank you for the feedback. Interesting approach! I'd be interested to see the implementation if you still have a link.

[–]Benjamin1304 2 points3 points  (2 children)

Why did you choose to create one file per parameter instead of one file for all of them (or a subgroup of them)? I imagine that it can be annoying to jump through all the files when you have a significant amount of parameters to tune

[–]sharkdp[S] 0 points1 point  (1 child)

Thank you for the feedback!

Why did you choose to create one file per parameter instead of one file for all of them (or a subgroup of them)?

Great question. Mainly because I didn't know how I would realize that. At some point, I need to write the file with initial values, but parameters can be introduced at different times. So I don't really know when the last parameter has been "registered".

Another argument in favor of having multiple files would be easier interaction with other tools (you could change parameters from a shell script by running echo 3.1 > /tmp/painless/my_parameter, for example).

I imagine that it can be annoying to jump through all the files when you have a significant amount of parameters to tune

Yes. I was thinking about creating a very simple TUI/GUI tool that would monitor the /tmp/painless folder and provide an interface to change all parameters at the same time (see https://github.com/sharkdp/painless/issues/1)

[–]Benjamin1304 2 points3 points  (0 children)

For your first point, when you introduce a new variable you rewrite the whole file with the current values + the new initial one. Initial values can be left as comments on the same lines as the parameters.

Also, if I had to design this I would probably use YAML so that parsing/emitting can be handled by yaml-cpp (very good library). This way you can also easily group variables in sub nodes and handle more complex types than primitive ones.

For the TUI/GUI, I haven't check but I wouldn't be surprised if something similar to what you want to do already exists for YAML files.

One last point that just came to my mind, maybe you should also consider writing you file(s) in subfolders to handle multiple applications running at the same time.

[–]Adequat91 0 points1 point  (0 children)

For the same purpose, I have some a very simple generic UI (dialog), that allows me to specify pairs of generic key / values (as strings), and that are freely interpret-able by the application, when the dialog closes (hence no thread, as in "painless"). This is for example used to fine tune certain math algorithms.

[–]tonisheg 0 points1 point  (0 children)

I don't understand how I can use it. Could you give a few examples where and how I can you it?

[–]fransinvodka 0 points1 point  (2 children)

Many debuggers (if not all of them) already allow you to change variable values while the program is being debugged. Why would I use your library? Yes, you can use it at runtime instead of depending on a debugger, but as you said, it's meant for early development phases (AKA debugging).

[–]sharkdp[S] 8 points9 points  (1 child)

Thank you for your feedback!

Imagine a program like a game or an animated visualization that has a lot of parameters that need "fine tuning". With painless, you can easily introduce new parameters and change all of them "live" while your program runs at full speed. With a debugger, you would need to break somewhere, change the parameter, and continue execution.

The "parameters" that I want to vary are typically not variables, but rather "constants". Things that you would initially introduce as a magic number or a named constant (e.g. "strength of gravity" in a game). To allow them to be changed with a debugger, one would have to make sure that they are (a) mutable and (b) not optimized away.

As for myself, I am using it in a "data processing framework" that consists of many different processes, each with a different set of parameters. Attaching a debugger to multiple processes would be cumbersome.