You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Now that libuv is almost here we're going to need some way to set up tasks whose handles are accessible globally. I would like to pursue both global and task-local data for 0.3.
We discussed this on IRC today and came to the conclusion (I think, @brson please correct me if I'm misrepresenting you here) that unsafe globals would be ok if we avoid any sort of static initializer code. That is, only permit globals initialized as constants, and make all access to them unsafe. Then we could build a variety of safer abstractions on top (lazily-initialized singletons, single-writer / multi-reader dataflow variables, etc.)
IOW I still think this is something we should be getting to. Agreed?
Agreed, but my impression was that you were sort of trying to sidestep the global issue by using const addresses/types as a unique key into some kernel-owned global table (as opposed to keying them off strings). I liked that idea because it also works for implementing task-local data / dynamically-scoped variables.
Ok, spent a few more hours sketching and came up with slightly fighter design. Criticism / modification welcome.
Declaring a mutable global (let x : foo = <const_expr>;) is legal anywhere ourside fns. Not unsafe.
Reading or writing from such a global is unsafe.
We either extend the word const to be a type operator that strips all mut qualifiers from its operand (to unlimited depth), or implement a const kind that is a subkind of send.
We implement (in library code) a bunch of 1-argument enums that wrap pointers / other atomic datatypes, and have methods that safely / atomically implement better things:
Mutexes, cvars, semaphores. Straight-up old-fashioned per-process global bottlenecks. Sometimes you need one.
Write-once, read-many global w/ static initializer function. First reader CAS-reserves the word, runs the initializer, writes the result and registers a global atexit-like cleanup function with the runtime. Constrained to work kind const, or send on a type that is const'ed in the result of the get method.
Broadcast globals similar to the write-once case, except no static initializer. Anyone can write to it, repeatedly; the readers borrow a region-pointer (presumably from an @-box or something) that's kept alive for the duration of the get() call and its callback.
Task-local general-purpose values. Not necessarily even using a mutable global. Can just use the address of a const item as a key into a per-task hashtable, as @brson mentions above.
Task-local dynamically scoped general-purpose values. Really just a task-local list with methods for binding a new head-of-list and getting the current head-of-list. Nothing too crazy.
Sounds reasonable. I think the const kind will be much more straightforward if we want to do something relatively quickly.
I do think a deep read-only type operator is useful but there are various issues to consider and I think it takes some design work, particularly around classes/methods/other things that are still in flight. I have been thinking about such an operator for a while, partially modeled on Javari, for the purposes of deterministic, in-process parallelism, but I haven't gotten around to writing much of it out...
core::priv::chan_from_global_ptr still requires access to per-rt globals in order to be generally useful - right now it relies on fields in rust_kernel.
Activity
brson commentedon Feb 15, 2012
Now that libuv is almost here we're going to need some way to set up tasks whose handles are accessible globally. I would like to pursue both global and task-local data for 0.3.
brson commentedon Mar 14, 2012
pcwalton convinced me that we shouldn't take this step lightly. for my current use cases we can add some privileged runtime functions
graydon commentedon May 2, 2012
We discussed this on IRC today and came to the conclusion (I think, @brson please correct me if I'm misrepresenting you here) that unsafe globals would be ok if we avoid any sort of static initializer code. That is, only permit globals initialized as constants, and make all access to them unsafe. Then we could build a variety of safer abstractions on top (lazily-initialized singletons, single-writer / multi-reader dataflow variables, etc.)
IOW I still think this is something we should be getting to. Agreed?
brson commentedon May 2, 2012
Agreed, but my impression was that you were sort of trying to sidestep the global issue by using
const
addresses/types as a unique key into some kernel-owned global table (as opposed to keying them off strings). I liked that idea because it also works for implementing task-local data / dynamically-scoped variables.graydon commentedon May 4, 2012
Ok, spent a few more hours sketching and came up with slightly fighter design. Criticism / modification welcome.
let x : foo = <const_expr>;
) is legal anywhere ourside fns. Not unsafe.const
to be a type operator that strips allmut
qualifiers from its operand (to unlimited depth), or implement aconst
kind that is a subkind ofsend
.atexit
-like cleanup function with the runtime. Constrained to work kindconst
, orsend
on a type that isconst
'ed in the result of theget
method.@
-box or something) that's kept alive for the duration of theget()
call and its callback.const
item as a key into a per-task hashtable, as @brson mentions above.brson commentedon May 4, 2012
This sounds good to me.
nikomatsakis commentedon May 5, 2012
Sounds reasonable. I think the
const
kind will be much more straightforward if we want to do something relatively quickly.I do think a deep read-only type operator is useful but there are various issues to consider and I think it takes some design work, particularly around classes/methods/other things that are still in flight. I have been thinking about such an operator for a while, partially modeled on Javari, for the purposes of deterministic, in-process parallelism, but I haven't gotten around to writing much of it out...
bblum commentedon Jun 27, 2012
Is this subsumed by TLS? Or do things truly need to be accessible cross-task?
brson commentedon Jun 27, 2012
core::priv::chan_from_global_ptr
still requires access to per-rt globals in order to be generally useful - right now it relies on fields in rust_kernel.15 remaining items