HackerTrans
TopNewTrendsCommentsPastAskShowJobs

mizmar

29 karmajoined geçen yıl

comments

mizmar
·dün·discuss
The seconds to calendar date conversion doesn't actually need to know about leap seconds. At the seconds representation level, the same number is repeated twice (or the smearing trategy happens).

So the times before and after leap second get converted the the same date regardless of whether you know about the leap second or not. Edge case is that once second occuring twice. You might have seen that 23:59:60 seconds timestamp somewhere.
mizmar
·dün·discuss
Yes, time() and clock_gettime(CLOCK_REALTIME) results are affected by leap seconds.

New leap second will get to your system through NTP. Sadly NTP only distributes indicator flag that leap second is going to be introduced, but not the offset itself. But the distributed time itself is already affected by leap second, so NTP client doesn't really need to know.

(In contrast the other time sync mechanisms - GPS and PTP - use time scale unaffected by leap seconds and distribute it as an additional information with UTC offset. And it's left on client to modify received time on its end. Kernel has a parameters in clock_adjtime() for leap seconds.)

So if you have a passive system that has NTP client then it's time will change for new leap second on runtime. Linux treats UTC time as the dominant one, so that's the one saved to RTC device and will survive reboot.

There is CLOCK_TAI that sounds like it should return TAI time, but it is such a second class citizen to the point that nothing on regular Linux desktop and server distros even set the offset and it returns the same time as CLOCK_REALTIME.

There is a file in /etc with list of leap seconds that is part of some package, so you need to update the system to update this file. I don't believe traditional NTP software updates this package dynamically. But not many software uses it. If some init service script parsed and set the kernel UTC offset then your system's CLOCK_TAI would be one second late from rest of the world until update. But it doesn't affect UTC time on Linux in any way I know.
mizmar
·geçen ay·discuss
Clipboard on Wayland is interesting. Clients expose the content through wl_data_source and see wl_data_offer. To receive the clipboard content, they request receive on a wl_data_offer and pass a file descriptor (usually pipe() write end) to compositor, and then read from it. File descriptor is passed to the appropriate wl_data_source origin which is expected to write the content to it.

Both reads and writes ends take some time, I played with it to see how various programs react to a writer that just hangs or takes a lot of time. If the read is handled synchronously then you can block a UI loop. Some implement timeout and some can be blocked indefinitely.

But handling in asynchronously (either on thread or in nonblocking event loop) isn't an automatic win either. For example the new gnome text editor didn't order other user inputs with clipboard; so you would press Ctrl+V, nothing happened initially, continue writing and suddenly the clipboard content was inserted.

And I don't even remember how the OpenGL hidden window inhibiting worked with wl_data_source. Since the window is stuck in eglSwapBuffers, does it get unblocked to handle the clipboard write?

Surprisingly, even though Gnome compositor doesn't have a clipboard manager, it caches the clipboard content sometimes.
mizmar
·2 ay önce·discuss
I encountered this few months back. Netcat was recv-only client connected to server that was continually sending some logs. Managed to trigger it with netcat killed with Ctrl+\ signal instead of Ctrl+C, but not consistently. My hypothesis was that it has something to do with unACKed data and/or non-empty incoming queue.
mizmar
·3 ay önce·discuss
Great reading, thanks. Describes how to handle ±0, works with difference to avoid truncation errors. First half of the paper is arriving at this correct snippet, second part of the paper is about optimizing it.

    bool DawsonCompare(float af, float bf, int maxDiff)
    {
        int ai = *reinterpret_cast<int*>(&af);
        int bi = *reinterpret_cast<int*>(&bf);
        if (ai < 0)
            ai = 0x80000000 - ai;
        if (bi < 0)
            bi = 0x80000000 - bi;
        int diff = ai - bi;
        if (abs(diff) < maxDiff)
            return true;
        return false;
    }
mizmar
·3 ay önce·discuss
the "XOR in hash functions" mentioned at the end most certainly refers to Zobrist hashing, the actually useful XOR trick.

Requires fixed-length keys. Generate random table for each byte position. Then to hash a key, for each position lookup byte in table and XOR the results. This is used in chess/go/shogi/... engines because the board/position representation is fixed-length and you can undo modes easily - XOR-out byte from previous state and XOR-in from new state.
mizmar
·3 ay önce·discuss
Another similar trick - XOR doubly linked list: XOR the prev and next pointers (storaged size of node decreases) and you can recover the values when accessing the node from prev or next side and thus already know one of the addresses.
mizmar
·3 ay önce·discuss
There is another way to compare floats for rough equality that I haven't seen much explored anywhere: bit-cast to integer, strip few least significant bits and then compare for equality. This is agnostic to magnitude, unlike epsilon which has to be tuned for range of values you expect to get a meaningful result.
mizmar
·3 ay önce·discuss
>you're assuming copy/edit don't bump mtime

Incorrect, I only assume move/rename of backup to original location doesn't change it's mtime (which it doesn't with default flags or from IDE or file manager). And I don't think this is a weird or obscure workflow, I do it all the time - have two versions of a file or make a backup before some experimental changes, and restore it later.
mizmar
·3 ay önce·discuss
ninja fails to detect that file changed from last build - all it's mtime, ctime, inode and size can change, yet it's not detected as long as mtime is not newer than target.
mizmar
·3 ay önce·discuss
Similar to make, it does mtime chronological comparison of dependencies with target to determinate if dependencies changed. This is just so flawed and simple to fool by operations on filesystem that do not change mtime (move, rename):

1) pick a source file and make a copy of it for for later 2) edit selected source file and rebuild 3) move the copy to it's original location 4) try to rebuild, nothing happens
mizmar
·4 ay önce·discuss
I wouldn't call wayland-client a callback hell. All callbacks are called at expected time when you call wl_display_dispatch() (and its variants) or during wl_display_roundtrip(). GLFW also works with callbacks and nobody complains about that.

There is no async involved so function coloring argument doesn't really apply here.

I don't share author's hate for them, but they are definitely more verbose than popping form event queue and switch statement on event type ala SDL loop. Plenty of callbacks just set parameters in some state struct and do not propagate further. And you need to fill the vtable structs, and register that as listener. This boilerplate is probably the reason why basic window examples have ~200 lines instead of 40. But in larger project this is barely a problem.
mizmar
·4 ay önce·discuss
Wayland makes it unnecessarily difficult to make simple clients. Gnome still doesn't support server-side window decoration and libdecor is an absolute nightmare and wayland-cursor doesn't even detect the system theme properly.
mizmar
·4 ay önce·discuss
>and I still don't know what's the difference between them (wl_display_roundtrip() & wl_display_dispatch()) and in what order to call them on

I've been struggling with this initially as well, it's pretty poorly explained in docs. Short explanation:

Wayland-client library implements a queues over the socket. So to get it, you have to think about when is the socket read from and written to, and when are the queues pulled from or pushed to. There is always a default queue, but for example EGL+OpenGL creates it's own queue, which further makes it more confusing.

- `wl_display_dispatch_pending()` only pulls messages from default queue to callbacks

- `wl_display_dispatch()` also tries to do blocking read on the socket if no messages are in queue

- quite recently `wl_display_dispatch_queue_timeout()` was finally added, so you can do non-blocking read from the socket. earlier you had to hack the function yourself

- `wl_display_flush()` writes enqueued messages in queue to socket

- `wl_display_roundtrip()` sends a ping message and does blocking wait for response. the purpose is that you also send all enqueued requests and receive and process all responses. for example during init you call it to create registry and enumerate the objects, and you call it for second time to enumerate further protocol objects that got registered in registry callback, such as seat

- `eglSwapBuffers()` operates on its own queue, but reading from socket also enqueues to default queue, so you should always call `wl_display_dispatch_pending()` (on default queue) afterwards

There is also a way to get around being stuck in `eglSwapBuffers()` during window inhibition: disable the blocking with `eglSwapInterval(0)` and use `wl_surface_frame()` callback, and you get notified in callback when you can redraw and swap again. But you can't do blocking reads with `wl_display_dispatch()` anymore, have to use the timeout variant. After using it this way, you can also easily manage multiple vsynced windows independently on the same thread, and even use wayland socket in epoll event loop. None of this is documented of course.

The clipboard interface is definitely compromised a bit by being shared with drag-and-drop events, but it's not that complicated. Also there is a pitfall when you copy-paste to your own application and don't use any async event loop, you can get deadlocked by being expected to write and read on the same file descriptor at the same time.
mizmar
·4 ay önce·discuss
I would mention stb_textedit.h, but I would not recommend it. It was an interesting thing to study. but the library has many shortcomings and is pain to integrate and use. It is used in ImGui, but somewhat modified. Just to illustrate the flaws - it can't be used with utf-8 bytes easily, there is a large switch on keyboard shortcuts to trigger actions so you have to fake keyboard input to script things, the default word boundary detection is pretty bad, and there is no way to nicely provide double or triple click selection.

The two notable functions are stb_text_locate_coord() and stb_textedit_find_charpos(), which connect the physical x,y coordinates with position in text buffer. They both iterate lines of text - accumulating y position; and the chars of last line - accumulating x position.

For windowing, drawing and OS integration, SDL with SDL_ttf is actually pretty good. SDL3_ttf API got an improvement and no longer requires zero-terminated strings so you don't need to relocate every chunk.
mizmar
·4 ay önce·discuss
It's not that bad. You need really large files to notice. The largest realistic file I'll ever touch - sqlite3 amalgamation with 270k lines and 9.1 kB - still takes only 6 ms to memmove it on my poor laptop. Any regular up-to 10k lines file is memmoved in order of microseconds.