[–] 5 points 9 months ago* (last edited 9 months ago) (2 children)

Well, as long as you're doing single machine instructions. I think. But you might be doing something that's done in multiple instructions. And you don't really know what the compiler does, and what machine instructions your code translates to... And there will be other issues. If you allow your code to access stuff in random sequence, you might end up reading before a write, or read after the write. So your variable might be set, or undefined... Depending on the programming language and type, and if it's in the heap or stack, it could be zero, or whatever happened to be in memory before... I don't have a clue about Rust. Just think the half-set with primitive types isn't really how it works. If it's that short, it will be one of the two. You might be able to do something like it with longer data structures, though. Like do a loop to set a very long string / array. And do something while the other thread is in the middle of writing. That'd be possible.

  • source
  • parent
  • context
  • [–] [S] 2 points 9 months ago (1 child)

    Hm. Good to know. As far as i know. rusts unsafe is kind of like sudo where more tools are granted to you with less checks and balances. Those checks being the borrow checker. So I think unsafe is more like saying "I don't want the extra protection against bad memory use." (Like say using memory you already freed). Now im not familiar with what makes a variable atomic or not. But assuming if a variable can be read or written with a single instruction. I'm interpereting that as making it safe?

  • source
  • parent
  • context
  • [–] [S] 3 points 9 months ago (3 children)

    Thank you for replying so quickly. Very interesting that it writes 64 bits at a time. (at least on the x86_64 platform i am on) So theres no tangible risk of a cpu processing a read and write instruction in parallel messing up the data that was read?

  • source
  • parent
  • context
  • [–] 7 points 9 months ago (2 children)

    In general, yes, it's possible to end up with half-written variables -- mutexes (and/or other synchronization primitives) are used to avoid that kind of problem.

    Whether you can encounter it in practice depends on the specific programming language, CPU, compiler, and actual instructions involved. Some operations that seem like they should be atomic from the perspective of a high level language are actually implemented as multiple machine code instructions and the thread could be interrupted between them, causing problems, unless steps are deliberately taken to avoid issues with concurrency.

    I have minimal experience with Rust, so I'm not sure how bad the footguns you can run into with unsafe are there specifically, but you can definitely blow your leg off in C/C++...

  • source
  • [–] 5 points 9 months ago* (last edited 9 months ago) (4 children)

    You're probably doing this on a 32bit or 64bit processor. It writes 32bit (or 64) at a time, using one instruction. There is no time in between, where only specific bits are set.

  • source
  • [–] 4 points 10 months ago*

    Check that you're on a new enough version where main is actually the default, not master.

    Also, there's no reason why you can't just switch branches? Just create a main branch from whereever (either right at the start after init or at some later point) and push it, then delete master.

    Also literally thr first result when googling how to set the default branch name: https://superuser.com/questions/1419613/change-git-init-default-branch-name set it to main manually if it won't do it automatically

    E: regarding the errors when pushing to main, I assume you tried git push origin main while on the master branch. That doesn't work because git only wants to push to same-name branches. However, you can do git push origin master:main, which means "push this branch master to the remote origin and rename it to main".

  • source
  • [–] 3 points 10 months ago

    I don't know the incantation offhand, but certainly there is a way to tell your git to treat 'main' as the default.

    However, 'master' actually was the historical default; 'main' is a newer name (search online if you are interested in why some repos and git hosting providers switched to use 'main' ... warning, opinions differ on whether said reasons were considered sensible or not).

  • source
  • [–] [S] 2 points 11 months ago (1 child)

    The separate thread did the trick for the most part, now I'm having a different issue, where I'll likely need a debugger. Let's hope Seer works for me and I don't have to spend a month to learn GDB, just so I don't spend 30 mins every time I need to search for a feature I don't know.

  • source
  • parent
  • context
  • [–] 2 points 11 months ago (2 children)

    Their sample code:

    struct libevdev *dev = NULL;
     int fd;
     int rc = 1;
    
     fd = open("/dev/input/event0", O_RDONLY|O_NONBLOCK);
     rc = libevdev_new_from_fd(fd, &dev);
     if (rc < 0) {
             fprintf(stderr, "Failed to init libevdev (%s)\n", strerror(-rc));
             exit(1);
     }
     printf("Input device name: \"%s\"\n", libevdev_get_name(dev));
     printf("Input device ID: bus %#x vendor %#x product %#x\n",
            libevdev_get_id_bustype(dev),
            libevdev_get_id_vendor(dev),
            libevdev_get_id_product(dev));
     if (!libevdev_has_event_type(dev, EV_REL) ||
         !libevdev_has_event_code(dev, EV_KEY, BTN_LEFT)) {
             printf("This device does not look like a mouse\n");
             exit(1);
     }
    
     do {
             struct input_event ev;
             rc = libevdev_next_event(dev, LIBEVDEV_READ_FLAG_NORMAL, &ev);
             if (rc == 0)
                     printf("Event: %s %s %d\n",
                            libevdev_event_type_get_name(ev.type),
                            libevdev_event_code_get_name(ev.type, ev.code),
                            ev.value);
     } while (rc == 1 || rc == 0 || rc == -EAGAIN);
    

    Is definitely doing the polling in a blocking way. I think this is intended to be run on a separate thread, and you pass the inputs to your main application thread via some other mechanism.

    If your using the polling function, you should be able to do it in a single thread, but then you have to periodically check in between doing other work.

  • source
  • parent
  • context
  • [–] 1 point 1 year ago

    Well it's off to a great start in that a very casual review has already found a significant soundness issue. This transpiler adds a nullable type and implicitly makes all other types non-nullable. That's great but it also adds boilerplate generators for data classes and one of the options for that is to generate a no-arg constructor. I was curious how it handles the combination of those two features. The answer is that it doesn't. You can declare a class with non-nullable properties, and then auto-generate a no-arg constructor that sets those properties to null.

    You can already do better than this with plain Java plus the Immutables builder library and the findbugs static analysis tools nonnull check. Intellij even has built in support to recognize the nonnull annotation and will do the analysis automatically.

  • source
  • [–] 2 points 1 year ago

    You could use Lazarus, which is based on Pascal, cross-compilable, and allows you to create the UI by dragging and dropping.

    Another alternative is B4J, which allows you to write the code in a dialect of BASIC, but compiles it to Java bytecode.

  • source
  • view more: ‹ prev next ›