An "ambient service" is one that is pervasively available without
significant semantic difference switching from one implementation to
another. When a service is pervasively available, one may avoid
various network-bandwidth and latency costs by using a 'local'
implementation of a given service rather than a remote implementation
thereof. Beyond optimization, ambient services may also greatly
improve system robustness in the face of disruption.
Some examples of ambient services include:
* obtaining the approximate current time
* subscribing to a clock to receive a 'tick' signal every 100
* domain-name-service cache (caches in general, really)
* random-number services when pseudo-random determinism isn't required
* subscription-objects supporting an Akamai network feed
* switching to a local compiler/interpreter for a simple evaluation
language rather than calling a global version thereof
From above, one might generalize that there are two aspects of ambient
services: one either queries such a service (as for random numbers,
current time, caches, etc.), or is subscribed to it (as for the clock-
Those which might be queried could reasonably be represented as
procedures, but there are some considerable advantages in turning such
things as 'obtain the current time' and 'random-number services' into
true capabilities. Two such advantages are:
* (1) the ability to achieve confinement and control when performing
unit-tests and integration-tests of a subsystem (i.e. you can speed up
or slow down the clock, or provide precise overrides to random-number
services), and for security in general. Object-capability model allows
confinement of an object graph by construction, but direct procedural
access to time or random numbers (and other 'globals' of any sort)
damages such confinement.
* (2) a reduction in implementation-complexity of the language, since
you no longer need to provide 'primitive' procedures for accessing
random numbers or to support HTTP caching. Instead, the support for
ambients becomes abstract and extensible.
Due to these two advantages in addition to the considerable
optimization and robustness advantages of ambients in general, I spent
a good bit of yesterday thinking about how to handle ambient services
in a language supporting automatic distribution and mobile objects
(actors, really) without violating object-capability model security.
CONTEXT: the distributed objects of the language run atop a variety of
non-homogeneous processors and machines, which I'll call "platforms".
Each platform hosts a number of objects. Constructed object
99a686f1de2d230a?hl=en) introduce objects that are distributed or
mobilized automatically across platforms. Some objects in each
configuration represent potentially ambient services such as time-
servers and true-random number generators.
(a) when a potential ambient service is accessed or subscribed by a
remote object, the subscription or access is routed automatically to a
local implementation of the same service.
(b) goal (a) is achieved without any change in functional semantics of
the overall system.
(c) if the potential-ambient service cannot be implemented locally
(e.g. on an embedded system without a clock or limited memory), it
shall still be available through remote sources (potentially including
neighboring platforms, rather than just the origin platform).
(d) in event of mobilization of existing objects these ambient
services will automatically follow again.
(e) avoid duplicate subscription messages, plus avoid missing relevant
subscription messages, during mobilization
(f) transparency; ability to switch to non-ambient implementations of
the same service in order to achieve confinement or control in a
manner transparent to the user code.
(g) object-capability model and confinement by construction: systems
are confined unless explicitly given a capability (or possibly the
capability to forge capabilities).
(a) only stateless+asynchronous actors can be arbitrarily duplicated
without violating (goal.b). Actors meeting the stateless+asynchronous
criterion can be duplicated whether or not they are ambient services.
(b) subscribed ambient services will somehow need to actively forward
their subscription information to follow mobile actors.
(c) this is ultimately an optimization - a pervasively useful
optimization potentially on the order of tail-recursion, but still an
optimization - and so does not need to receive first-class attention
within the language.
CONCLUSION / IMPLEMENTATION:
What I concluded from the above is deceptively simple, seemingly
obvious in retrospect, which to me marks it as a reasonable approach,
though I would like opinions and to hear of alternative approaches to
achieve the above goals.
* (A) Each 'platform' is to support a registry of 'drivers' for
ambient service-objects. E.g. there might be a 'time' driver, or a
'clock signal' driver.
* (B) Ambient service-objects are represented under-the-hood by simple
Uniform Resource Identifiers (albeit potentially with some non-
standard protocols such as 'time://minimum_accuracy=picosecond' or
'random://secure'). This serves as the 'stateless, asynchronous'
representation that can be duplicated from one platform to another.
* (C) An ambient service-object is duplicated by serializing and
transporting a representation of the object's message handlers across
the network between platforms. This is the same as for other
asynchronous+stateless objects. The difference, however, is that an
ambient service-object appeals to a driver for a local implementation,
whereas other asynchronous+stateless actors would generally appeal to
an interpreter or compiler.
* (D) As with all object-capability languages, the under-the-hood
representation of an object, and that it happens to be a URI, does not
need to be made available within the language. This achieves
transparency and identical semantics to non-ambient objects.
* (E) The language provides no primitives to take a URI and produce an
ambient service-object. This could be added as a service from outside
the language. The inability to forge capabilities being granted the
capability to do so is useful for achieving confinement for testing
and is necessary to object-capability model.
* (F) Ambient service-object actors have normal inter-platform actor
names (which may also be URIs), and a platform without the appropriate
driver can simply fire a message back to the actor's normal object
name (or may optionally push the actor to a nearby neighbor).
I still haven't come up with a great way to handle mobility of
subscriptions, so the above probably needs a bit more work.
I assume that the platform/runtime for any decent object-oriented or
actors model language already provides mechanisms to abstract *non*-
ambient resources as objects/actors. For example, objects that
represent printers aren't ambient - a given printer might be globally
accessible in this language, but there are some very significant
semantic differences in printing to a server-side printer vs. printing
to a client-side printer.
Of course, while specific actuators and sensors tend to not be
ambient, global services like DDS that store and transport sensor data
and actuator commands might be usefully represented as ambient. It is
probably difficult to draw hard lines between ambient and non-ambient
services. That's alright: hard lines aren't required since gains/
losses here are not semantic. Treating a service as 'ambient' where
not useful simply results in a highly specialized URI plus a local
indirection. Sometimes even that indirection can be useful... e.g.
while 'http' pages could be treated as specific actors (accepting
get,put,post,delete,etc. messages), treating them as ambients allows
the indirection to leverage local page caches.
Thoughts and criticism welcome.