Some Ramblings for November 24th, 2019
November 24, 2019Welcome back to another week of my ramblings.
Autumn here is quite thoroughly over, with Boston having gotten a couple of light freezes and a lot of dreary, watery weather. This picture is from more than a month ago, right around the time I was starting to get sick. Chances are, going on a hike and “taking the fresh mountain air” did not actually help my health at all, seeing as I then spent two weeks sick and several additional weeks with the dregs of illness.
Mental Health
This has been a struggle of a week. My mental health has cratered severly, and I have gotten into the range of not leaving the house because of the risk that I might have to interact with strangers.
Almost all of my trouble is work-related. I despair of ever getting to do work that I like, while I’m simultaneously having to maintain professionalism while dealing with complete disasters, and undisciplined men who are not actually interested in my experience (where by experience, I mean “hey, I’ve done that before and everything I touched exploded into flame”).
It is hard for me to take a mental health day primarily because I know that I will have to return to work to face whatever problems I was unable to solve before. This would not be a huge problem if I actually worked on interesting problems, but instead the problems I face are things like “the state model of this application is uncontrolled and getting worse” or “javascript is flagging errors in places where there cannot possibly errors”.
Let’s get something really clear: My career advanced as far as it did because I was viewed as a man until I reached the 32 years of age. My career has been backsliding ever since, with my options gradually shrinking, even though I have relentlessly expanded my technical skills and my project management skills.
Mental health, and the attendant suicidality that I manage, all revolve around hope. I basically don’t have any.
Obviously, this is not a healthy way to live. Where my co-workers and my clients see how I bring intense passion and skill to my work, the reality is that I actually just cannot disconnect from my work. I have never learned the trick of shutting work out of my mind when I am not working, and so problems at work always spill out into the rest of my life.
Rust, GUIs, and notifications
On my mental health day, I took the time to start getting familiar with building applicatinos in GTK again. I follow a development philosophy in which I have an “application” which is basically a headless object on which all operations can be performed, and the visible GUI is just a thin skin over that.
It turns out, React + Redux applications follow this model almost precisely. We all know that we can store our application state in Redux, using our actions and reducers to update the state, and using React to display the state.
So, on Thursday I took up the challenge of figuring out some version of that with GTK in Rust, and with some help I succeeded.
GTK inherently follows a “push” model of state updates, where React + Redux is made to feel like a pull update. React components exist and will pull any new updates whenever a state update occurs. With GTK, though, I have to build some of that infrastructure myself. I opted to use a listener model, in which I will register an update function for every component that I want to update in response to a state change. That update function receives the updated information and manually updates the component. The state manager (AppContext
in the link above) calls all listeners (which really means just executing the registered functions) whenever a state update occurs. Functions that update the state are responsible for ensuring that this dispatch actually happens.
While this is conceptually straightforward, Rust’s very strict memory checking made this rather challenging to figure out.
Pay close attention to the closures on line 73 and 77. connect_clicked
requires an Fn
, not an FnOnce
, implying that the closures will be executed more than once. Less obvious, though, the closures must outlast the closure passed to connect_activate
on line 57, because the connect_activate
call is specifically for setting up widgets. These widgets will inherently outlast the function call. So, dec_ctx
and inc_ctx
must both be cloned off of ctx
, and ownership of them moved into the closures that get registered as callback functions.
It is not clear to me, however, why dec_ctx
and inc_ctx
, once moved, outlast an individual invocation of the enclosed functions. I can only assume that both variables (and, technically, ctx
in the larger function) and the code fo the closure are bound together into a context that persists much longer than any particular invocation.
In writing this, I also look ta line 67 and wonder about the lifetime of the label, the label clone, and the update listener. In particular, I wonder what happens if the box containing the original counter_label
gets destroyed. I suspect that while counter_label
itself gets dropped, label_clone
and the listener function continue to work as expected, but with no visual effects because no widget actually contians the label_clone
.
For my next challenge, I will be converting the AppContext
into something that keeps the handle to the underlying trax database, and which observes changes to the currently selecting range of data to show.
Immediate plans include full editing and record creation, plus better formatting. But I still want to get timezone, display units, and translations into the application as quickly as I can.
Games
In the midst of the depression, I have done a lot of self-distraction. First, I bought and played through Sayonara Wild Hearts on the Switch. This is more of a music game, racing through lots of neon scenes at breakneck speeds, and putting together an impression of a story of a broken heart attached to astral highways. But, the game is intensely positive, the protagonist is hella trans, and there are furries, androgynes, and lesbians scattered around as shattered fragments that the protagonist has to reclaim.
Second, today I got Steam working correctly on my NixOS machine and then fired up “Torment: Tides of Numenera”. I bought the game while I was sick last December, but I was unable to play it because so many of the scenes broke on my Macbook’s graphics hardware. I find it horribly ironic that a Linux machine runs games better than a Macbook pro, but that is the world we live in.
As a sidenote, this is what it takes to get Steam working on a NixOS machine. Install these packages:
unstable.libva
unstable.steam
Next, enable this in your system’s configuration.nix
:
hardware.opengl.driSupport32Bit = true;
That’s it for this week.
The upcoming week will involve me dedicating most of my spare time to baking until Thanksgiving arrives, and then I will re-approach fitnesstrax late Thursday and for most of the day on Friday.
With any luck, things at work will go well enough that I can stop stressing.