From f9069baa70ea78117f2087fe6e359fb2ea0ae16a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Sun, 21 Apr 2013 16:28:17 -0700 Subject: [PATCH] core::rt: Add LocalServices for thread-local language services Things like the GC heap and unwinding are desirable everywhere the language might be used, not just in tasks. All Rust code should have access to LocalServices. --- src/libcore/rt/local_services.rs | 63 ++++++++++++++++++++++++++++++++ src/libcore/rt/mod.rs | 3 +- src/libcore/rt/sched/mod.rs | 6 ++- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 src/libcore/rt/local_services.rs diff --git a/src/libcore/rt/local_services.rs b/src/libcore/rt/local_services.rs new file mode 100644 index 000000000000..8e386f80b77d --- /dev/null +++ b/src/libcore/rt/local_services.rs @@ -0,0 +1,63 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Language-level runtime services that should reasonably expected +//! to be available 'everywhere'. Local heaps, GC, unwinding, +//! local storage, and logging. Even a 'freestanding' Rust would likely want +//! to implement this. + +//! Local services may exist in at least three different contexts: +//! when running as a task, when running in the scheduler's context, +//! or when running outside of a scheduler but with local services +//! (freestanding rust with local services?). + +use prelude::*; +use super::sched::{Task, local_sched}; + +pub struct LocalServices { + heap: LocalHeap, + gc: GarbageCollector, + storage: LocalStorage, + logger: Logger, + unwinder: Unwinder +} + +pub struct LocalHeap; +pub struct GarbageCollector; +pub struct LocalStorage; +pub struct Logger; +pub struct Unwinder; + +impl LocalServices { + pub fn new() -> LocalServices { + LocalServices { + heap: LocalHeap, + gc: GarbageCollector, + storage: LocalStorage, + logger: Logger, + unwinder: Unwinder + } + } +} + +/// Borrow a pointer to the installed local services. +/// Fails (likely aborting the process) if local services are not available. +pub fn borrow_local_services(f: &fn(&mut LocalServices)) { + do local_sched::borrow |sched| { + match sched.current_task { + Some(~ref mut task) => { + f(&mut task.local_services) + } + None => { + fail!(~"no local services for schedulers yet") + } + } + } +} diff --git a/src/libcore/rt/mod.rs b/src/libcore/rt/mod.rs index cf896dd18f34..e0190418b132 100644 --- a/src/libcore/rt/mod.rs +++ b/src/libcore/rt/mod.rs @@ -48,6 +48,7 @@ mod stack; mod context; mod thread; pub mod env; +pub mod local_services; /// Tools for testing the runtime #[cfg(test)] @@ -97,7 +98,7 @@ pub fn start(main: *u8, _argc: int, _argv: **c_char, _crate_map: *u8) -> int { /// Different runtime services are available depending on context. #[deriving(Eq)] pub enum RuntimeContext { - // Only default services, e.g. exchange heap + // Only the exchange heap is available GlobalContext, // The scheduler may be accessed SchedulerContext, diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs index 28946281628b..30136e443ee3 100644 --- a/src/libcore/rt/sched/mod.rs +++ b/src/libcore/rt/sched/mod.rs @@ -16,6 +16,7 @@ use super::work_queue::WorkQueue; use super::stack::{StackPool, StackSegment}; use super::rtio::{EventLoop, EventLoopObject}; use super::context::Context; +use super::local_services::LocalServices; use cell::Cell; #[cfg(test)] use super::uvio::UvEventLoop; @@ -38,7 +39,7 @@ pub struct Scheduler { /// Always valid when a task is executing, otherwise not priv saved_context: Context, /// The currently executing task - priv current_task: Option<~Task>, + current_task: Option<~Task>, /// An action performed after a context switch on behalf of the /// code running before the context switch priv cleanup_job: Option @@ -326,6 +327,8 @@ pub struct Task { /// These are always valid when the task is not running, unless /// the task is dead priv saved_context: Context, + /// The heap, GC, unwinding, local storage, logging + local_services: LocalServices } pub impl Task { @@ -337,6 +340,7 @@ pub impl Task { return Task { current_stack_segment: stack, saved_context: initial_context, + local_services: LocalServices::new() }; }