Amanieu / parking_lot

Compact and efficient synchronization primitives for Rust. Also provides an API for creating custom synchronization primitives.
Apache License 2.0
2.71k stars 213 forks source link

lock_api and abstracting over Mutexes which require initialization #117

Open Matthias247 opened 5 years ago

Matthias247 commented 5 years ago

I'm currently working on a library which provides some higher level synchronized data-structures, and aims to work on std environments as well as on bare-metal and other environments. The main thing that is not in common between those environments are Mutexes for my case, so I would like to be able to abstract over those.

I tried building a custom trait first, but without GATs it doesn't seem to work well with the associated data and lockguards with lifetimes. Now I discovered lock_api, which seems to roughly do what I want - making it possible to define predefined data-types which make use of parking_lot mutexes, and allow the users to override e.g. to a SpinLock using a template parameter.

However I'm wondering about the support for some platforms, where the following applies: Some RawMutex types require an explicit call for initialization, e.g. native system mutexes on lots of platforms from Windows to FreeRTOS. They require to call some kind of CreateMutex() call, which may fail. This seems to not be covered by lock_api, since the RawMutex trait accepts only a const init value instead of a new() function. I guess this is intentional, and not subject for change?

How would we support using lock_api based types on top of a platform like FreeRTOS? Would we port parking_lot to it? Or maybe set INIT to 0 and try to initialize the mutex on the first call to lock() within a global critical section? Those init functions can obviously also fail, so new() could be allowed to return an error, which however would then also require Mutex::new() to return an error. It probably might not make sense to support this, since it would clutter up the APIs for all other platforms, and the best practice should be not to allocate those kinds of resources after startup. So panic!ing might be ok.

And an unrelated question: How stable is the lock_api API? It seems like all the basics should be covered. Yet it still sits only at a very low version number of 0.1.5?

Amanieu commented 5 years ago

How would we support using lock_api based types on top of a platform like FreeRTOS? Would we port parking_lot to it? Or maybe set INIT to 0 and try to initialize the mutex on the first call to lock() within a global critical section? Those init functions can obviously also fail, so new() could be allowed to return an error, which however would then also require Mutex::new() to return an error. It probably might not make sense to support this, since it would clutter up the APIs for all other platforms, and the best practice should be not to allocate those kinds of resources after startup. So panic!ing might be ok.

My recommendation would be to lazily initialize the mutex using CAS. For an example, see this code. And just panic if initialization fails, since Mutex::new cannot return an error.

And an unrelated question: How stable is the lock_api API? It seems like all the basics should be covered. Yet it still sits only at a very low version number of 0.1.5?

The version number is low because I have never had the need to make a breaking change. This should be a pretty good sign that the API is stable.