@nepx posted a new topic, subject "Best practices for a CPU emulation library?". It read:

   My project has, among other things, emulation of a rather complex CPU. It would be useful to isolate it as a separate crate, so that it's easy to reuse in other projects.
    
    In order to use the CPU, of course, you need to implement a number of functions so that it can communicate with the outside world. This often has to happen somewhere deep within the emulator, several call stacks deep.
    
    One wrinkle is that for speed, I use `static mut`s instead of the more dynamic `self` references. In the original C code, which this project is a port of, using statically allocated structures with a fixed compile-time address resulted in a 15-30% speedup over runtime allocated ones. Yes, I know this doesn't lead to very pretty code, but in this case, the performance improvements are large enough that I'm willing to stick to this.
    
    In C, it was easy enough to pass around a few function pointers:
    [code] 
        typedef void (*io_write_t)(void* opaque, int port, int value);
        
        void cpu_register_io_write(int port_range_start, int port_range_end, void* opaque, io_write_t handler);
        
    [/code]
    
    `opaque`, in this case, roughly corresponds to `&mut self`; you supply a reference to `&mut self` along with the handler so that the handler has some idea what object it's supposed to act on, if more than one instance of `self` exists.
    
    In Java, it was possible to create an interface containing all the functions that I needed. `this` would be passed automatically, and personally I prefer this method over C's function pointers, since the interface lets you know beforehand what methods you need to implement.
    
    The only way that I would be able to implement this with my current understanding of Rust is to create function pointers, passing `*mut u8` around as a `void*` pointer and having the callee convert that back into a `&mut self` reference. But that would lead to really ugly code, and I'd like to use traits instead. So far, trying to mix traits with statics has been exceedingly frustrating, and nothing has worked.
    
    Is there a better way?

Then @RustyYato said

    You can use `trait` in pretty much the exact same way as Java interfaces.
    [code] 
        // Java
        
        interface SomeInterface {
            int get();
            int set(value: u32);
        }
        
        // later
        
        class SomeUser {
           void take_interface(iface: SomeInterface) {
                int value = iface.get();
                iface.set(value + 1);
            }
        }
        
    [/code]
    [code] 
        // Rust
        
        trait SomeInterface {
            fn get(&self) -> u32;
            fn set(&mut self, u32);
        }
        
        // later
        
        fn take_interface(iface: &mut dyn SomeInterface) {
            let value = iface.get();
            iface.set(value + 1);
        }
        
    [/code]
    
    You could also use generics
    [code] 
        fn take_interface<I: SomeInterface + ?Sized>(iface: &mut I) {
            let value = iface.get();
            iface.set(value + 1);
        }
        
    [/code]
    
    If you have a list of methods, I can help you build the `trait`

To which @nepx replied

    I understand how traits work (kinda...) but my main issue is how to store them, especially with statics. In Java, it was quite easy to do this:
    [code] 
        interface TestInterface {
            public void test();
        }
        class Test {
            static TestInterface iface;
            public static something() {
                iface.test(); 
            } 
        }
        
    [/code]
    
    In Rust, though, this is impossible:
    [code] 
        trait TestTrait {
            fn test(&mut self);
        }
        static mut IFACE: dyn TestTrait = ?;
        
        fn something() {
            unsafe { IFACE.test(); };
        }
        
    [/code]
    
    I'm wondering if it's possible to do the same in Rust, having a `static mut` that holds a trait and is able to dispatch from that. I've tried all sorts of combinations of raw pointers, `Box<>`, `Option<>`, but none of that seems to work.
    
    Sorry if I'm not being clear. This is a really esoteric usecase, so apologies for any confusion.

@RustyYato replied

    First I recommend against using `static mut`. It's really hard to use correctly because of Rust's aliasing rules (near impossible if you don't follow some _very_ strict guidelines). I would recommend you use `once_cell` \+ `Mutex` instead. If you know that you are single-threaded _and_ that `test` isn't reentrant, then you could potentially use `static mut`. But that's quite strict.
    
    Here's what I recommend.
    [code] 
        use once_cell8b7c:f320:99b9:690f:4595:cd17:293a:c069syn8b7c:f320:99b9:690f:4595:cd17:293a:c069Lazy;
        use st8b7c:f320:99b9:690f:4595:cd17:293a:c069syn8b7c:f320:99b9:690f:4595:cd17:293a:c069Mutex;
        
        static IFACE: Lazy<Mutex<Box<dyn TestInterface + Send>>> = Lazy8b7c:f320:99b9:690f:4595:cd17:293a:c069new(|| Mutex8b7c:f320:99b9:690f:4595:cd17:293a:c069new(Box8b7c:f320:99b9:690f:4595:cd17:293a:c069new(SomeImpl { ... })));
        
    [/code]
    
    If you are single-threaded and can't guarantee that test won't be reentrant, then you should use `thread_local`+`RefCell`
    [code] 
        thread_local! {
            static IFACE: RefCell<Box<dyn TestInterface>> = RefCell8b7c:f320:99b9:690f:4595:cd17:293a:c069new(Box8b7c:f320:99b9:690f:4595:cd17:293a:c069new(SomeImpl { ... }));
        }
        
    [/code]
    
    The best option is to not use a global! Instead just put it on the stack and pass around a `&mut dyn TestInterface`.
    
    edit: whoops, forgot `+ Send` in the first snippet

So @RustyYato replied

    If after you measure the cost of these apporaches (which will likely give different results from `Java`), and you are still unsatisfied, you can use this method. Rust Playground. Which does some minimal checks, but is still just as unsafe as `static mut`.
    
    I'll explain here why `static mut` is so dangerous in Rust.
    [code] 
        static mut X: u32 = 0;
        
        fn main() {
            unsafe {
                let x = &mut X;
                X = 10;
                let y = x; // this is UB, because `x` was invalidated by `X = 10`
            }
        }
        
    [/code]
    
    Code like this is _very_ easy to write, and a nightmare to debug. Because Rust has _much_ stricter aliasing rules compared to `C`, (`&mut _` may _**never**_ alias a different reference), it's much easier to cause UB.
    
    Avoid globals where you can, because it's not as worthwhile in Rust. Especially `static mut`.

After which, @system (system) added

    This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.


{'source': 'discourse', 'url': 'https://users.rust-lang.org/t/best-practices-for-a-cpu-emulation-library/56141', 'title': 'Best practices for a CPU emulation library?', 'views': 332, 'has_accepted_answer': False, 'word_count': 913, 'like_count': 2, 'reply_count': 2, 'participant_count': 2, 'posts': 6, 'tags': '', 'author': '@nepx', 'participants': '@nepx, @RustyYato, @system (system)', 'image_url': [None], 'created_at': '2021-02-25T17:08:51.308Z', 'last_posted_at': '2021-05-26T22:02:14.582Z'}