|
1 |
| -use std::path::Path; |
| 1 | +use std::{ |
| 2 | + path::Path, |
| 3 | + sync::{ |
| 4 | + atomic::{AtomicBool, Ordering}, |
| 5 | + Arc, |
| 6 | + }, |
| 7 | + thread, |
| 8 | +}; |
2 | 9 |
|
3 | 10 | use globset::{Candidate, GlobBuilder, GlobMatcher};
|
| 11 | +use once_cell::sync::Lazy; |
4 | 12 |
|
5 | 13 | use crate::error::Result;
|
6 | 14 | use builtin::BUILTIN_MAPPINGS;
|
@@ -44,14 +52,50 @@ pub struct SyntaxMapping<'a> {
|
44 | 52 | ///
|
45 | 53 | /// Rules in front have precedence.
|
46 | 54 | custom_mappings: Vec<(GlobMatcher, MappingTarget<'a>)>,
|
| 55 | + |
47 | 56 | pub(crate) ignored_suffixes: IgnoredSuffixes<'a>,
|
| 57 | + |
| 58 | + /// A flag to halt glob matcher building, which is offloaded to another thread. |
| 59 | + /// |
| 60 | + /// We have this so that we can signal the thread to halt early when appropriate. |
| 61 | + halt_glob_build: Arc<AtomicBool>, |
| 62 | +} |
| 63 | + |
| 64 | +impl<'a> Drop for SyntaxMapping<'a> { |
| 65 | + fn drop(&mut self) { |
| 66 | + // signal the offload thread to halt early |
| 67 | + self.halt_glob_build.store(true, Ordering::Relaxed); |
| 68 | + } |
48 | 69 | }
|
49 | 70 |
|
50 | 71 | impl<'a> SyntaxMapping<'a> {
|
51 | 72 | pub fn new() -> SyntaxMapping<'a> {
|
52 | 73 | Default::default()
|
53 | 74 | }
|
54 | 75 |
|
| 76 | + /// Start a thread to build the glob matchers for all builtin mappings. |
| 77 | + /// |
| 78 | + /// The use of this function while not necessary, is useful to speed up startup |
| 79 | + /// times by starting this work early in parallel. |
| 80 | + /// |
| 81 | + /// The thread halts if/when `halt_glob_build` is set to true. |
| 82 | + pub fn start_offload_build_all(&self) { |
| 83 | + let halt = Arc::clone(&self.halt_glob_build); |
| 84 | + thread::spawn(move || { |
| 85 | + for (matcher, _) in BUILTIN_MAPPINGS.iter() { |
| 86 | + if halt.load(Ordering::Relaxed) { |
| 87 | + break; |
| 88 | + } |
| 89 | + Lazy::force(matcher); |
| 90 | + } |
| 91 | + }); |
| 92 | + // Note that this thread is not joined upon completion because there's |
| 93 | + // no shared resources that need synchronization to be safely dropped. |
| 94 | + // If we later add code into this thread that requires interesting |
| 95 | + // resources (e.g. IO), it would be a good idea to store the handle |
| 96 | + // and join it on drop. |
| 97 | + } |
| 98 | + |
55 | 99 | pub fn insert(&mut self, from: &str, to: MappingTarget<'a>) -> Result<()> {
|
56 | 100 | let matcher = make_glob_matcher(from)?;
|
57 | 101 | self.custom_mappings.push((matcher, to));
|
|
0 commit comments