@@ -455,11 +455,44 @@ mod inner {
455
455
/// Create a new pool. The given closure is used to create values in
456
456
/// the pool when necessary.
457
457
pub ( super ) fn new ( create : F ) -> Pool < T , F > {
458
- // MSRV(1.63): Mark this function as 'const'. I've arranged the
459
- // code such that it should "just work." Then mark the public
460
- // 'Pool::new' method as 'const' too. (The alloc-only Pool::new
461
- // is already 'const', so that should "just work" too.) The only
462
- // thing we're waiting for is Mutex::new to be const.
458
+ // FIXME: Now that we require 1.65+, Mutex::new is available as
459
+ // const... So we can almost mark this function as const. But of
460
+ // course, we're creating a Vec of stacks below (we didn't when I
461
+ // originally wrote this code). It seems like the best way to work
462
+ // around this would be to use a `[Stack; MAX_POOL_STACKS]` instead
463
+ // of a `Vec<Stack>`. I refrained from making this change at time
464
+ // of writing (2023/10/08) because I was making a lot of other
465
+ // changes at the same time and wanted to do this more carefully.
466
+ // Namely, because of the cache line optimization, that `[Stack;
467
+ // MAX_POOL_STACKS]` would be quite big. It's unclear how bad (if
468
+ // at all) that would be.
469
+ //
470
+ // Another choice would be to lazily allocate the stacks, but...
471
+ // I'm not so sure about that. Seems like a fair bit of complexity?
472
+ //
473
+ // Maybe there's a simple solution I'm missing.
474
+ //
475
+ // ... OK, I tried to fix this. First, I did it by putting `stacks`
476
+ // in an `UnsafeCell` and using a `Once` to lazily initialize it.
477
+ // I benchmarked it and everything looked okay. I then made this
478
+ // function `const` and thought I was just about done. But the
479
+ // public pool type wraps its inner pool in a `Box` to keep its
480
+ // size down. Blech.
481
+ //
482
+ // So then I thought that I could push the box down into this
483
+ // type (and leave the non-std version unboxed) and use the same
484
+ // `UnsafeCell` technique to lazily initialize it. This has the
485
+ // downside of the `Once` now needing to get hit in the owner fast
486
+ // path, but maybe that's OK? However, I then realized that we can
487
+ // only lazily initialize `stacks`, `owner` and `owner_val`. The
488
+ // `create` function needs to be put somewhere outside of the box.
489
+ // So now the pool is a `Box`, `Once` and a function. Now we're
490
+ // starting to defeat the point of boxing in the first place. So I
491
+ // backed out that change too.
492
+ //
493
+ // Back to square one. I maybe we just don't make a pool's
494
+ // constructor const and live with it. It's probably not a huge
495
+ // deal.
463
496
let mut stacks = Vec :: with_capacity ( MAX_POOL_STACKS ) ;
464
497
for _ in 0 ..stacks. capacity ( ) {
465
498
stacks. push ( CacheLine ( Mutex :: new ( vec ! [ ] ) ) ) ;
0 commit comments