> {
48 | let (parent, deps) =
49 | try!(self.create_deps_for_any_parent(TypeId::of::(), Box::new(obj), to_shared::
));
50 | Ok(Scope::from_any_instance(parent, deps))
51 | }
52 |
53 | /// Collect all the items registered as `collectable` into a `Collection` of that type.
54 | pub fn collect(&self) -> Result> {
55 | self.create(Collection::new()).map(|v| v.explode())
56 | }
57 |
58 | pub fn when_ready(&mut self, action: F)
59 | where T: 'static + Any,
60 | F: for<'r> Fn(&Deps, &mut T) -> Result<()> + 'static + Send + Sync
61 | {
62 | match self.type_scope_created.entry(TypeId::of::()) {
63 | Entry::Occupied(mut list) => {
64 | list.get_mut().push(into_action_with_deps(action));
65 | }
66 | Entry::Vacant(e) => {
67 | e.insert(vec![into_action_with_deps(action)]);
68 | }
69 | };
70 | }
71 |
72 | /// Single dependency on a parent.
73 | pub fn attach(&mut self, constructor: F)
74 | where P: 'static + Any, // Parent
75 | C: 'static + Any, // Child
76 | F: for<'r> Fn(&Deps, &mut P) -> Result + 'static + Send + Sync
77 | {
78 | if TypeId::of::() == self.empty_type {
79 | self.register_isolated_constructor::(into_isolated_constructor_with_ignored_child_deps(constructor));
80 | } else {
81 | self.register_isolated_constructor::
(into_isolated_constructor_with_child_deps(constructor));
82 | }
83 | }
84 |
85 | /// Single dependency on multiple parents.
86 | pub fn bridge(&mut self, constructor: F)
87 | where P1: 'static + Any + Send + Sync, // Parent 1
88 | P2: 'static + Any + Send + Sync, // Parent 2
89 | C: 'static + Any, // Child
90 | F: for<'r> Fn(&mut P1, &mut P2) -> Result + 'static + Send + Sync
91 | {
92 | // Get or insert inceptor that is used to manage P1 and P2 instances.
93 | let inceptor_1 = match self.inceptors
94 | .entry((TypeId::of::(), TypeId::of::())) {
95 | Entry::Occupied(entry) => {
96 | entry.get()
97 | .downcast_ref::>>>()
98 | .expect("expected to find Inceptor of correct type in map")
99 | .clone()
100 | }
101 | Entry::Vacant(entry) => {
102 | let arc = Arc::new(Mutex::new(if TypeId::of::() == self.empty_type {
103 | Inceptor::new_with_ignored_return_val(constructor)
104 | } else {
105 | Inceptor::new_with_return_val(constructor)
106 | }));
107 | entry.insert(Box::new(arc.clone()));
108 | arc
109 | }
110 | };
111 |
112 | // Create inceptor clone for P2 instances
113 | let inceptor_2 = inceptor_1.clone();
114 |
115 | self.register_shared_constructor::(
116 | into_shared_constructor::(
117 | inceptor_1,
118 | Box::new(|inceptor: &Arc>>, parent: &mut Box|
119 | {
120 | let parent_for_inceptor = parent.downcast_mut::>>()
121 | .expect("expected downcast P1")
122 | .clone();
123 | inceptor.lock()
124 | .expect("failed to lock ic1")
125 | .incept_1(parent_for_inceptor)
126 | }),
127 | 1
128 | )
129 | );
130 | self.register_shared_constructor::(
131 | into_shared_constructor::(
132 | inceptor_2,
133 | Box::new(|inceptor: &Arc>>, parent: &mut Box|
134 | {
135 | let parent_for_inceptor = parent.downcast_mut::>>()
136 | .expect("expected downcast P2")
137 | .clone();
138 | inceptor.lock()
139 | .expect("failed to lock ic2")
140 | .incept_2(parent_for_inceptor)
141 | }),
142 | 2
143 | )
144 | );
145 | }
146 |
147 | pub fn collectable(&mut self, constructor: F)
148 | where C: 'static + Any,
149 | F: for<'r> Fn(&Deps) -> C + 'static + Send + Sync
150 | {
151 | self.register_isolated_constructor::>(
152 | into_isolated_constructor_without_child_deps(move |deps: &Deps, parent: &mut Collection| {
153 | parent.push(constructor(deps))
154 | })
155 | );
156 | }
157 |
158 | fn create_deps_for_any_parent(&self,
159 | type_id: TypeId,
160 | mut parent_not_shared: Box,
161 | to_shared: F)
162 | -> Result<(AnyInstance, Vec>)>
163 | where F: Fn(Box) -> Box
164 | {
165 | let mut deps = Vec::new();
166 |
167 | // First, construct any instances that do not need parent wrapped in mutex
168 |
169 | match self.isolated_constructors.get(&type_id) {
170 | Some(isolated_list) => {
171 | for any_constructor in isolated_list {
172 | match any_constructor(&self, &mut parent_not_shared) {
173 | Ok(Constructed { children }) => deps.extend(children),
174 | Err(any_err) => return Err(any_err),
175 | };
176 | }
177 | }
178 | None => (),
179 | }
180 |
181 | // Then, check if there are shared constructors, and if so, wrap value in mutex
182 | // and return it in AnyInstance::Shared, otherwise, return it in AnyInstance::Isolated.
183 |
184 | let mut parent_result = match self.shared_constructors.get(&type_id) {
185 | Some(shared_list) => {
186 | let mut parent_shared = to_shared(parent_not_shared);
187 |
188 | for any_constructor in shared_list {
189 | match any_constructor(&self, &mut parent_shared) {
190 | Ok(ConstructedShared { children }) => deps.extend(children),
191 | Err(any_err) => return Err(any_err),
192 | };
193 | }
194 |
195 | AnyInstance::Shared(parent_shared)
196 | }
197 | None => AnyInstance::Isolated(parent_not_shared),
198 | };
199 |
200 | // Execute post create actions for the value
201 |
202 | if let Some(actions) = self.type_scope_created.get(&type_id) {
203 | for action in actions {
204 | try!(action(&self, &mut parent_result));
205 | }
206 | }
207 |
208 | Ok((parent_result, deps))
209 | }
210 |
211 | /// Register child constructor that will be invoked when the parent `P` type is
212 | /// created.
213 | fn register_isolated_constructor(&mut self,
214 | any_constructor: Box)
215 | -> Result + Send + Sync>) {
216 | match self.isolated_constructors.entry(TypeId::of::()) {
217 | Entry::Occupied(mut list) => {
218 | list.get_mut().push(any_constructor);
219 | }
220 | Entry::Vacant(e) => {
221 | e.insert(vec![any_constructor]);
222 | }
223 | };
224 | }
225 |
226 | /// Register child constructor that will be invoked when the parent `P` type is
227 | /// created.
228 | fn register_shared_constructor(&mut self,
229 | any_constructor: Box)
230 | -> Result + Send + Sync>) {
231 | match self.shared_constructors.entry(TypeId::of::()) {
232 | Entry::Occupied(mut list) => {
233 | list.get_mut().push(any_constructor);
234 | }
235 | Entry::Vacant(e) => {
236 | e.insert(vec![any_constructor]);
237 | }
238 | };
239 | }
240 | }
241 |
242 | unsafe impl Send for Deps {}
243 | unsafe impl Sync for Deps {}
244 |
245 | fn into_action_with_deps
(action: F)
246 | -> Box Result<()> + Send + Sync>
247 | where F: for<'r> Fn(&Deps, &mut P) -> Result<()> + 'static + Send + Sync,
248 | P: 'static + Any
249 | {
250 | Box::new(move |deps: &Deps, parent: &mut AnyInstance| -> Result<()> {
251 | match *parent {
252 | AnyInstance::Isolated(ref mut value) => {
253 | try!(action(deps,
254 | &mut value.downcast_mut::()
255 | .expect("expected to downcast type in post create action")))
256 | }
257 | AnyInstance::Shared(ref mut value) => {
258 | try!(action(deps,
259 | &mut value.downcast_mut::>>()
260 | .expect("expected to downcast type in post create action")
261 | .lock()
262 | .expect("expected to lock value for AnyInstance::Shared action")))
263 | }
264 | };
265 | Ok(())
266 | })
267 | }
268 |
269 | fn into_shared_constructor
270 | (
271 | inceptor: Arc>>,
272 | incept_fun: Box>>, &mut Box) -> Result<(usize, Vec>)> + Send + Sync>,
273 | index: usize
274 | )
275 | -> Box) -> Result + Send + Sync>
276 | where P1: 'static + Any + Send + Sync, // Parent 1
277 | P2: 'static + Any + Send + Sync, // Parent 2
278 | C: 'static + Any // Child
279 | {
280 | Box::new(move |deps: &Deps, parent: &mut Box| -> Result {
281 | let (id, instances) = try!(incept_fun(&inceptor, parent));
282 |
283 | let mut children: Vec> = Vec::with_capacity(instances.len() + 1);
284 |
285 | for instance in instances {
286 | let instance_artifacts =
287 | try!(deps.create_deps_for_any_parent(TypeId::of::(), instance, to_shared::));
288 | children.push(Box::new(instance_artifacts));
289 | }
290 |
291 | children.push(Box::new(Destructor::new(inceptor.clone(), index, id)));
292 |
293 | Ok(ConstructedShared { children: children })
294 | })
295 | }
296 |
297 | fn into_isolated_constructor_with_child_deps
298 | (constructor: F)
299 | -> Box) -> Result + Send + Sync>
300 | where F: for<'r> Fn(&Deps, &mut P) -> Result + 'static + Send + Sync,
301 | P: 'static + Any,
302 | C: 'static + Any
303 | {
304 | Box::new(move |deps: &Deps, parent: &mut Box| -> Result {
305 | let child = {
306 | let concrete_parent = parent.downcast_mut::()
307 | .expect("expected to downcast type in into_isolated_constructor_with_child_deps");
308 | try!(deps.create(try!(constructor(deps, concrete_parent))))
309 | };
310 | Ok(Constructed { children: vec![Box::new(child)] })
311 | })
312 | }
313 |
314 | fn into_isolated_constructor_with_ignored_child_deps
315 | (constructor: F)
316 | -> Box) -> Result + Send + Sync>
317 | where F: for<'r> Fn(&Deps, &mut P) -> Result + 'static + Send + Sync,
318 | P: 'static + Any,
319 | C: 'static + Any
320 | {
321 | Box::new(move |deps: &Deps, parent: &mut Box| -> Result {
322 | try!(constructor(deps,
323 | parent.downcast_mut::()
324 | .expect("expected to downcast type in \
325 | into_isolated_constructor_with_ignored_child_deps")));
326 | Ok(Constructed { children: vec![] })
327 | })
328 | }
329 |
330 | fn into_isolated_constructor_without_child_deps
331 | (constructor: F)
332 | -> Box) -> Result + Send + Sync>
333 | where F: for<'r> Fn(&Deps, &mut P) + 'static + Send + Sync,
334 | P: 'static + Any
335 | {
336 | Box::new(move |deps: &Deps, parent: &mut Box| -> Result {
337 | constructor(deps,
338 | parent.downcast_mut::()
339 | .expect("expected to downcast type in \
340 | into_isolated_constructor_without_child_deps"));
341 | Ok(Constructed { children: vec![] })
342 | })
343 | }
344 |
345 | #[cfg(test)]
346 | mod test {
347 | use Deps;
348 | use std::thread;
349 | use std::sync::{Arc, Mutex};
350 |
351 | #[derive(Clone, Debug, Eq, PartialEq)]
352 | struct A(String);
353 |
354 | #[derive(Clone, Debug, Eq, PartialEq)]
355 | struct B(String);
356 |
357 | #[derive(Clone, Debug, Eq, PartialEq)]
358 | struct C(String);
359 |
360 | #[test]
361 | fn creates_dependency() {
362 | let mut deps = Deps::new();
363 |
364 | // here we want to know what is the state of dependency in closure, hence
365 | // shared mutable reference to it
366 | let created_b_ref = Arc::new(Mutex::new(None));
367 |
368 | deps.attach({
369 | let created_b_ref = created_b_ref.clone();
370 | move |_: &Deps, a: &mut A| {
371 | let b = B([&a.0[..], "+B"].concat());
372 | *created_b_ref.lock().unwrap() = Some(b.clone());
373 | Ok(b)
374 | }
375 | });
376 |
377 | deps.create(A("Hello".into())).unwrap();
378 |
379 | assert_eq!("Hello+B",
380 | (*created_b_ref.lock().unwrap()).clone().unwrap().0);
381 | }
382 |
383 | #[test]
384 | fn creates_dependency_of_dependency() {
385 | let mut deps = Deps::new();
386 |
387 | // here we want to know what is the state of dependency in closure, hence
388 | // shared mutable reference to it
389 | let created_c_ref = Arc::new(Mutex::new(None));
390 |
391 | deps.attach(|_: &Deps, a: &mut A| Ok(B([&a.0[..], "+B"].concat())));
392 |
393 | deps.attach({
394 | let created_c_ref = created_c_ref.clone();
395 | move |_: &Deps, b: &mut B| {
396 | let c = C([&b.0[..], "+C"].concat());
397 | *created_c_ref.lock().unwrap() = Some(c.clone());
398 | Ok(c)
399 | }
400 | });
401 |
402 | deps.create(A("Hello".into())).unwrap();
403 |
404 | assert_eq!("Hello+B+C",
405 | (*created_c_ref.lock().unwrap()).clone().unwrap().0);
406 | }
407 |
408 | #[test]
409 | fn creates_mutable_dependency() {
410 | let mut deps = Deps::new();
411 |
412 | deps.attach(|_: &Deps, a: &mut A| {
413 | *a = A("Hi!".into());
414 | Ok(())
415 | });
416 |
417 | let mut a = deps.create(A("Hello".into())).unwrap();
418 | let al = a.lock().unwrap();
419 |
420 | assert_eq!("Hi!", al.0);
421 | }
422 |
423 | #[test]
424 | fn should_work_accross_threads() {
425 | let mut deps = Deps::new();
426 |
427 | deps.attach(|_: &Deps, _: &mut A| Ok(B("b".into())));
428 | deps.attach(|_: &Deps, _: &mut B| Ok(C("c".into())));
429 |
430 | let dep_refs = Arc::new(deps);
431 |
432 | let a = thread::spawn({
433 | let a_deps = dep_refs.clone();
434 | move || a_deps.create(A("a".into())).unwrap()
435 | });
436 |
437 | let b = thread::spawn({
438 | let b_deps = dep_refs.clone();
439 | move || b_deps.create(B("b".into())).unwrap()
440 | });
441 |
442 | assert_eq!(b.join().unwrap().explode(), B("b".into()));
443 | assert_eq!(a.join().unwrap().explode(), A("a".into()));
444 | }
445 |
446 | #[test]
447 | fn can_create_bridge_dependency() {
448 | let mut deps = Deps::new();
449 |
450 | let created_bridge = Arc::new(Mutex::new(None));
451 | let created_bridge_clone = created_bridge.clone(); // so we can modify this from inside the closure
452 |
453 | deps.bridge(|a: &mut A, b: &mut B| Ok(vec![a.0.clone(), b.0.clone()]));
454 |
455 | // Use this to copy created Vec value from bridge to mutex protected clone
456 | deps.when_ready(move |_: &Deps, parent: &mut Vec| {
457 | *created_bridge_clone.lock().unwrap() = Some(parent.clone());
458 | Ok(())
459 | });
460 |
461 | // Bind to created A and modify the value from "Hello" to "Hi"
462 | deps.attach(|_: &Deps, a: &mut A| {
463 | *a = A("Hi".into());
464 | Ok(5)
465 | });
466 |
467 | // Attach to any type Vec and append "Nice" to last element
468 | deps.attach(|_: &Deps, created_bridge_result: &mut Vec| {
469 | created_bridge_result.push("Nice".to_string());
470 | Ok(())
471 | });
472 |
473 | // Create both instigators and result should appear
474 | let mut a = deps.create(A("Hello".into())).unwrap();
475 | let mut b = deps.create(B("World".into())).unwrap();
476 |
477 | {
478 | let al = a.lock().unwrap();
479 | let bl = b.lock().unwrap();
480 |
481 | assert_eq!("Hi", al.0);
482 | assert_eq!("World", bl.0);
483 | }
484 |
485 | {
486 | let val = created_bridge.lock()
487 | .unwrap();
488 | assert_eq!("HiWorldNice",
489 | val.as_ref().expect("expected bridge val to be created").concat());
490 | }
491 |
492 | let mut c = deps.create(B("Rust".into())).unwrap();
493 |
494 | {
495 | let cl = c.lock().unwrap();
496 |
497 | assert_eq!("Rust", cl.0);
498 | }
499 |
500 | {
501 | let val = created_bridge.lock()
502 | .unwrap();
503 | assert_eq!("HiRustNice",
504 | val.as_ref().expect("expected bridge val to be created").concat());
505 | }
506 |
507 | assert_eq!(c.explode(), B("Rust".into()));
508 | assert_eq!(a.explode(), A("Hi".into()));
509 | assert_eq!(b.explode(), B("World".into()));
510 | }
511 | }
512 |
--------------------------------------------------------------------------------