1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
use crossbeam::sync::ShardedLock;
use downcast_rs::{impl_downcast, Downcast};
use std::any::TypeId;
use std::cell::UnsafeCell;
use std::collections::HashMap;
use std::fmt::*;
use std::sync::Arc;
pub use storage::*;

mod storage;

pub trait Resource: 'static {}

impl<T: 'static> Resource for T {}

pub trait ResourceStorage: Downcast {}
impl_downcast!(ResourceStorage);
struct ResourceData<T: 'static> {
    value: UnsafeCell<T>,
    _mutated: UnsafeCell<bool>,
}

impl<T: 'static> ResourceStorage for ResourceData<T> {}

#[derive(Default)]
pub struct ResourceList {
    /// List of resources
    pub(crate) resources: HashMap<TypeId, Arc<ShardedLock<Box<dyn ResourceStorage>>>>,
}

impl Debug for ResourceList {
    fn fmt(&self, f: &mut Formatter<'_>) -> Result {
        f.debug_struct("ResourceList")
            .field("resources", &self.resources.len())
            .finish()
    }
}

unsafe impl Send for ResourceList {}
unsafe impl Sync for ResourceList {}

#[allow(dead_code)]
impl ResourceList {
    pub fn new() -> Self {
        Self {
            resources: HashMap::new(),
        }
    }

    pub fn add_resource<T: Resource>(&mut self, resource: T) {
        self.resources.insert(
            TypeId::of::<T>(),
            Arc::new(ShardedLock::new(Box::new(ResourceData {
                value: UnsafeCell::new(resource),
                _mutated: UnsafeCell::new(true),
            }))),
        );
    }

    pub fn get_resource<T: Resource>(
        &self,
    ) -> Option<LockedValue<'_, Box<dyn ResourceStorage>, T>> {
        if let Some(r) = self.resources.get(&TypeId::of::<T>()) {
            let lock = r.read().unwrap();
            if let Some(data) = lock.downcast_ref::<ResourceData<T>>() {
                return Some(LockedValue {
                    data: data.value.get(),
                    _lock: lock,
                });
            }
        }

        None
    }

    pub fn get_resource_mut<T: Resource>(
        &self,
    ) -> Option<LockedValueMut<'_, Box<dyn ResourceStorage>, T>> {
        if let Some(r) = self.resources.get(&TypeId::of::<T>()) {
            let mut lock = r.write().unwrap();
            if let Some(data) = lock.downcast_mut::<ResourceData<T>>() {
                data._mutated = UnsafeCell::new(true);
                return Some(LockedValueMut {
                    data: data.value.get(),
                    _lock: lock,
                });
            }
        }

        None
    }
}

#[cfg(test)]
mod tests {
    use super::ResourceList;
    struct ScoreBoard(usize);

    #[test]
    fn test_scheduler() {
        let mut resources = ResourceList::new();

        resources.add_resource(ScoreBoard(0));
        // let system_count = 32768;
        // let additions_per_thread = 256;
        assert!(resources.get_resource::<ScoreBoard>().is_some());

        // scheduler.run(&resources, &world);

        // if let Some(resource) = resources.get_resource::<ScoreBoard>() {
        // assert_eq!(resource.0, system_count * additions_per_thread);
        // };
    }
}

// use rfw_scene::Scene;
// use std::{any::TypeId, collections::HashMap};

// use crate::system::System;
// use downcast::Downcast;

// pub trait IntoResource {
//     fn init(&mut self, scene: &mut Scene, system: &mut System);
// }

// pub trait Resource: 'static {
//     fn tick(&mut self, scene: &mut Scene, system: &mut System);
// }

// downcast::impl_downcast!(Resource);

// pub struct ResourceList {
//     pub(crate) resources: HashMap<TypeId, Box<dyn Resource>>,
// }

// impl Default for ResourceList {
//     fn default() -> Self {
//         Self {
//             resources: Default::default(),
//         }
//     }
// }

// impl ResourceList {
//     pub fn new() -> Self {
//         Self::default()
//     }

//     pub fn get_resource<T: Resource>(&mut self) -> Option<&mut T> {
//         let type_id = TypeId::of::<T>();
//         if let Some(r) = self.resources.get_mut(&type_id) {
//             let r = r.downcast_mut().unwrap();
//             Some(r)
//         } else {
//             None
//         }
//     }

//     pub fn register_plugin<T: Resource>(&mut self, resource: T) {
//         let type_id = TypeId::of::<T>();
//         self.resources.insert(type_id, Box::new(resource));
//     }

//     pub fn tick(&mut self, scene: &mut Scene, system: &mut System) {
//         for (_, r) in self.resources.iter_mut() {
//             r.tick(scene, system);
//         }
//     }
// }