On 8 Aug 2006, at 10:03, Michael van der Gulik wrote: > Hi Howard. > > I forgot to mention that the reason I'm doing this is to allow > untrusted foreign code to run in the same image as trusted code. > Untrusted code must be carefully managed - it must not be able to > consume large amounts of memory, CPU or disk space to which it is > not entitled. Untrusted code / objects must not prevent trusted > code from operating well. This is not exactly what you asked for, but - as an experiment why not run your untrusted code in a separate image? If you were running this on unix then you could limit the memory given to this separate image - either via say ulimit in the shell or something fancier (maybe via the os process plugin). You could then talk to the 'jail' image via remote messaging. It wouldn't take very long to knock up and it might give you interesting results early. As for limiting CPU or disk space that's a bit harder but there are various things you could do on Linux to try it out. Run a separate squeak image inside User Mode Linux for example. That would allow finer control of virtual CPU and disk space. Cheers, Mike |
In reply to this post by Howard Stearns
On Tue, 08 Aug 2006 18:04:07 +0200, Howard Stearns wrote:
> Klaus D. Witzel wrote: >> On Tue, 08 Aug 2006 16:53:46 +0200, Howard Stearns wrote: >> >>> Imagine that a magic fairy comes and creates a system that works >>> exactly as you prescribe. >>> Now, how will you or your users guess that 64MB RAM / 100MB disk >>> / 100MB traffic/day is appropriate for one application, while others >>> use different figures? >> >> Would you say that the above is any different from a single computer >> system with exactly the capacity limits you gave? If so, mind to >> explain? > > I agree that they're the same. And I would never order a computer saying > that it must not have more than 64MB, 100MB disk, nor allow more than > 100MB traffic/day. Nor would I attempt to implement "safety" that way on > a single or partitioned computer. Then, how would you "implement" it? >> BTW: in ancient (computer age) times we had to implement contingency >> systems (sometimes mistakenly called accounting systems) because there >> was only one computer for 1,000's of users, like for example here: > > Indeed, and there is good reason that computers are no longer > implemented that way. I don't believe that. Do you mean that you can upload your malicious code to one of the grids - http://en.wikipedia.org/wiki/Grid_computing and it (the grid) will immediately allocate all its resources and all its processing power that your code asks for? Indeed, there *are* good reasons that computer (systems) *are* implemented that way (regardless of the # of CPU's etc). And the grid is not an exception: every OS constrains *all* available resources, one way or the other, even its own resources. There is no way out. The question in the original post was, how to do that with Squeak (cross platform, of course!). > While I certainly don't feel that "no body does it that way" is a valid > argument that something should not be done, I do feel it is instructive > to note that, while there are many projects to build distributed systems > that allow resources to be shared among computers, the opposite does not > appear to be true (e.g., hardware systems that segregate or cap > resources). But the physical "hard" limits of computer systems are indistinguishable from "soft" (administrated) limits. There is no difference observable by any piece of software of any kind. > It's rather suspect that the original project spec of how to limit > resource use on a single processor My example below was about a *single computer system* with multiple CPUs and tons of time-shared terminals for use by the students. > should come out of a problem in distributed computing, which by > definition is an attempt to gain overall system power and access by > sharing resources between computers. There's a good heuristic: Don't > create a feature requirement that contravenes the overriding project > goal! The project goal is that no student can crash the university's computer system(s) and also can not dominate available resources. Every student must be given the compiler, disk space, etc, in order that they can work and can produce their malicious code (by chance or by using their free will). This is the (typical) situation when you give Squeak to a user (regardless of the institution and of the application). >> >> - http://www.unibw.de/ >> >> on a B7800/B7900, the successor of the B5000. >> > Thanks for making my point! NP. /Klaus |
In reply to this post by Michael Roberts-2
On Tue, Aug 08, 2006 at 09:29:00PM +0100, Michael Roberts wrote:
> > On 8 Aug 2006, at 10:03, Michael van der Gulik wrote: > > >Hi Howard. > > > >I forgot to mention that the reason I'm doing this is to allow > >untrusted foreign code to run in the same image as trusted code. > >Untrusted code must be carefully managed - it must not be able to > >consume large amounts of memory, CPU or disk space to which it is > >not entitled. Untrusted code / objects must not prevent trusted > >code from operating well. > > This is not exactly what you asked for, but - > > as an experiment why not run your untrusted code in a separate > image? If you were running this on unix then you could limit the > memory given to this separate image - either via say ulimit in the > shell or something fancier (maybe via the os process plugin). You > could then talk to the 'jail' image via remote messaging. It > wouldn't take very long to knock up and it might give you interesting > results early. An easy way to do start the remote images is UnixProcess class>>forkSqueakAndDo:, but you'll want to do something to make sure the remote images are not writing to their original changes file, otherwise you'll have a swarm of images all scribbling on the same changes file. If the remote images are short-lived and do not do things that result in a lot of garbage collection, then the overall memory usage is surprisingly light. I presume that this would do reasonable things on a multiprocessor system also, although I don't have a system to try it on. Dave |
In reply to this post by Klaus D. Witzel
Klaus D. Witzel wrote: > On Tue, 08 Aug 2006 18:04:07 +0200, Howard Stearns wrote: >> Klaus D. Witzel wrote: >>> On Tue, 08 Aug 2006 16:53:46 +0200, Howard Stearns wrote: >>> >>>> Imagine that a magic fairy comes and creates a system that works >>>> exactly as you prescribe. >>>> Now, how will you or your users guess that 64MB RAM / 100MB >>>> disk / 100MB traffic/day is appropriate for one application, while >>>> others use different figures? >>> >>> Would you say that the above is any different from a single computer >>> system with exactly the capacity limits you gave? If so, mind to >>> explain? >> >> I agree that they're the same. And I would never order a computer >> saying that it must not have more than 64MB, 100MB disk, nor allow >> more than 100MB traffic/day. Nor would I attempt to implement >> "safety" that way on a single or partitioned computer. > > Then, how would you "implement" it? Rats, I thought I answered that in my first message on this thread. ;-) I don't know of a silver bullet to implementing safety. No one thing with a catchy name that has been articulated as a necessary and sufficient strategy. Sandboxes and Access Control Lists have already been shown to be neither necessary nor sufficient. (And to me, Michael's original formulation of "Domains" are just ACLs by another name.) Through the thread, I and others have mentioned some principles that I do feel are helpful enough to be significant (if not necessarily "solving" the problem). These include defense-in-depth, end-to-end, capabilities, and the thing I mentioned in my first message, which I don't have a name for, in which you make the user pick a resource when you really need one so that the user knows what's happening, rather than just barring access altogether. In addition to using the above to figure out what behavior should be controlled and how to manage that control, there's still the issue of enforcing that control. I suspect that in a class-based system, this is precisely equivalent to versioned classes: you want to ensure that an instance is using a version of a class that implements the behavior safely, and dynamic changes to the class create new versions. I think there are only two strategies for versioning classes: either you include the class with the mobile code, or you have a form of linking in which you specify (in a secure way) what "version" of the class is required. Both Andreas and Craig are working in this area. (For my part, my faith in the religion of classes has been shaken over the last year and a half, and I'm toying with converting to prototype/delegationism. This makes it easier for different objects in the same application to implement versions of behaviors. But I don't know yet how this all fits together with enforcing, e.g., capabilities.) > >>> BTW: in ancient (computer age) times we had to implement contingency >>> systems (sometimes mistakenly called accounting systems) because >>> there was only one computer for 1,000's of users, like for example >>> here: >> >> Indeed, and there is good reason that computers are no longer >> implemented that way. > > I don't believe that. Do you mean that you can upload your malicious > code to one of the grids > > - http://en.wikipedia.org/wiki/Grid_computing > > and it (the grid) will immediately allocate all its resources and all > its processing power that your code asks for? > > Indeed, there *are* good reasons that computer (systems) *are* > implemented that way (regardless of the # of CPU's etc). And the grid > is not an exception: every OS constrains *all* available resources, > one way or the other, even its own resources. There is no way out. > > The question in the original post was, how to do that with Squeak > (cross platform, of course!). that's what's happening here. Klaus, what you and Danil are quite rightly describing is the the goal of assuring that you have the resources to do your work. Michael's original post is about a particular technique (essentially, implementing ACLs for objects/processes/islands/whatever to bind them to a particular sandbox). While this technique is an interesting puzzle (the part I like about the subject line of the original message), it is not, IMHO, a good strategy for providing the goal of a meaningful, practical measure of security in a mobile code system (the part that I and others have not liked about the subject line of the original message). I think (?) that most of the large scale grid system, including Seti and my university's own Condor, take a trivial approach to "level of service": they DO take over the whole processor, but only when there's no keyboard/mouse activity for a long enough time. They checkpoint periodically, and lose all their work since the last checkpoint when you interrupt it by typing again. It's really all quite crude. Ensuring "enough resources" is a "hard problem." ("Here's a Turing machine," said the professor to the student. "Please make sure there's enough tape in it to run this program. But don't run the program first.") I think it's pretty clear that I feel that asking users to pick limits (configure the tape) isn't going to get you anywhere. > >> While I certainly don't feel that "no body does it that way" is a >> valid argument that something should not be done, I do feel it is >> instructive to note that, while there are many projects to build >> distributed systems that allow resources to be shared among >> computers, the opposite does not appear to be true (e.g., hardware >> systems that segregate or cap resources). > > But the physical "hard" limits of computer systems are > indistinguishable from "soft" (administrated) limits. There is no > difference observable by any piece of software of any kind. > >> It's rather suspect that the original project spec of how to limit >> resource use on a single processor > > My example below was about a *single computer system* with multiple > CPUs and tons of time-shared terminals for use by the students. > >> should come out of a problem in distributed computing, which by >> definition is an attempt to gain overall system power and access by >> sharing resources between computers. There's a good heuristic: Don't >> create a feature requirement that contravenes the overriding project >> goal! > > The project goal is that no student can crash the university's > computer system(s) and also can not dominate available resources. > Every student must be given the compiler, disk space, etc, in order > that they can work and can produce their malicious code (by chance or > by using their free will). This is the (typical) situation when you > give Squeak to a user (regardless of the institution and of the > application). > >>> >>> - http://www.unibw.de/ >>> >>> on a B7800/B7900, the successor of the B5000. >>> >> Thanks for making my point! > > NP. > > /Klaus > > -- Howard Stearns University of Wisconsin - Madison Division of Information Technology mailto:[hidden email] jabber:[hidden email] voice:+1-608-262-3724 |
On Wed, 09 Aug 2006 15:57:58 +0200, Howard Stearns wrote:
...cut away many interesting details... > (For my part, my faith in the religion of classes has been shaken over > the last year and a half, and I'm toying with converting to > prototype/delegationism. Hhm, same toy that I have here for about a year and a half or so ;-) But there is a way for class religion and prototype/delegationism to coexist (compiler already works here, in Squeak). Further to self includes: Smalltalk, Smalltalk includes: self :) > This makes it easier for different objects in the same application to > implement versions of behaviors. But I don't know yet how this all fits > together with enforcing, e.g., capabilities.) Yes, problem class does not change, because of the aforementioned mutual implication. ... > Ensuring "enough resources" is a "hard problem." ("Here's a Turing > machine," said the professor to the student. "Please make sure there's > enough tape in it to run this program. But don't run the program first.") No problem if that problem where in NP-complete. But it apparently isn't, for example it can be reduced to Turing's halting problem. > I think it's pretty clear that I feel that asking users to pick limits > (configure the tape) isn't going to get you anywhere. ...hhm, and I thought that: >> But the physical "hard" limits of computer systems are >> indistinguishable from "soft" (administrated) limits. There is no >> difference observable by any piece of software of any kind. Howard, this was an interesting discussion. Take care with the capabilities (they are fragile) and may you never run out of Turing tape 8-) /Klaus |
In reply to this post by Andreas.Raab
Major modifications to the VM? Good grief.
I was thinking that you could re-write new or basicNew or equivalent entry point to increment a domain's memory counter. If that memory counter goes over a limit, then new or basicNew would wait on a Semaphore until the limit has gone under again. Or it could throw an Exception or something. Then I believe >>finalize is the method called when the GC happens. This would do the opposite. I'll be putting my code where my mouth is soon and see if this would work. Oh, and the references all look useful. I really need to get looking at Islands properly; I believe it solves a few other problems I'm working around. Michael. Andreas Raab wrote: > None of the cited references will solve the original problem(s). They > are related but they won't solve it. Managing memory limits alone would > require *major* modifications of the VM. > > Cheers, > - Andreas > > Frank Shearar wrote: > >> "Michael van der Gulik" <[hidden email]> wrote: >> >>> Hi Howard. >>> >>> I forgot to mention that the reason I'm doing this is to allow untrusted >>> foreign code to run in the same image as trusted code. Untrusted code >>> must be carefully managed - it must not be able to consume large amounts >>> of memory, CPU or disk space to which it is not entitled. Untrusted code >>> / objects must not prevent trusted code from operating well. >> >> >> Have you looked at the (Tweak) Islands [1] work? Lex Spoon also did work >> with the same name [2], IIRC. And there's the Squeak-E [3] stuff too. >> >> [1] http://tweak.impara.de/TECHNOLOGY/Whitepapers/Islands/ >> [2] http://minnow.cc.gatech.edu/squeak/2074 >> [3] http://www.erights.org/history/squeak-e.html >> >> frank >> >> >> > > > |
In reply to this post by David T. Lewis
David T. Lewis wrote:
> On Tue, Aug 08, 2006 at 09:29:00PM +0100, Michael Roberts wrote: > >>On 8 Aug 2006, at 10:03, Michael van der Gulik wrote: >> >> >>>Hi Howard. >>> >>>I forgot to mention that the reason I'm doing this is to allow >>>untrusted foreign code to run in the same image as trusted code. >>>Untrusted code must be carefully managed - it must not be able to >>>consume large amounts of memory, CPU or disk space to which it is >>>not entitled. Untrusted code / objects must not prevent trusted >>>code from operating well. >> >>This is not exactly what you asked for, but - >> >>as an experiment why not run your untrusted code in a separate >>image? If you were running this on unix then you could limit the >>memory given to this separate image - either via say ulimit in the >>shell or something fancier (maybe via the os process plugin). You >>could then talk to the 'jail' image via remote messaging. It >>wouldn't take very long to knock up and it might give you interesting >>results early. That idea actually has potential. I'll ponder on it. Some methods of keeping it OS independant would need to be thought about. Hmm. It would mean that objects in separate domains couldn't reference each other. > An easy way to do start the remote images is UnixProcess class>>forkSqueakAndDo:, > but you'll want to do something to make sure the remote images are not > writing to their original changes file, otherwise you'll have a swarm > of images all scribbling on the same changes file. Yea; I've been hit with that problem already. Damn near lost my code. I should record that as a bug in Squeak - the changes file needs a lock system on it so that only one Squeak instance writes to it. In fact, I've gotten to the stage of saving everything to Monticello after every small change, and then restarting the image after I run it (the code I have so far completely frobs the image beyond repair...). Michael. |
In reply to this post by Klaus D. Witzel
Klaus D. Witzel wrote:
> Hi Michael, > > on Tue, 08 Aug 2006 11:19:37 +0200, you wrote: > > Klaus D. Witzel wrote: > That's the easy part: clones of classes share their method dictionary > (in form of a pointer, not as a copy). Only the class pointer of per > domain created instances is changed, nothing more and nothing else. A > very good ROI, that is :) ....wow. That is thinking outside the square. I had never considered stripping a thin layer off Class/Metaclass like that. So, a concrete example is needed. Say I have a class "Person". Then, normally: alice := Person new. bob := Person new. In a domained image, say I have two domains, alicesDomain ("ad") and bobsDomain ("bd"). Now: adPerson = Person class copy new. " adPerson is a Class " "<<Do class initialisation and stuff here, copying stuff from Person>>" adPerson methodDict: Person methodDict. adPerson domain: alicesDomain. " Sets an instance variable in the Class" bdPerson = Person class copy new. "<<Do class initialisation here>>" bdPerson methodDict: Person methodDict. bdPerson domain: bobsDomain. Now we can do: alice := adPerson new. bob := bdPerson new. In other words, each domain has its own set of classes, but each class shares its instance variables (methodDict, instanceVariables, superclass, format etc) with other classes of the same... er... class. I could probably cludge up some Namespacing or other magic to get "Person" to resolve to the domain's local version of the Person class, so you don't need to use "adPerson" and "bdPerson" but just "Person". So now, finding the domain of any given object would be easy: Object>>domain ^ self class domain. Trivial! The code below hasn't been properly thought out wrt security etc, but looks good in theory :-). I'll probably break a few images trying to get it working as well. Object>>new self domain waitUntilCanMakeMoreObjects. ^ self basicNew initialize. Domain>>waitUntilCanMakeMoreObjects objectCounter := objectCounter + 1. (objectCounter > maxObjects) ifTrue: [ tooManyObjectsSemaphore wait ]. Object>>finalize " This may or may not work... I haven't used >>finalize before" self domain freeOneObject. Domain>>freeOneObject objectCounter := objectCounter - 1. ( do bug-free magic ) ifTrue: [ tooManyObjectsSemaphore signal ]. And ditto for Processes :-). Advantages: - should hopefully be more efficient than adding an instance variable ("domain") to Object. - Can also do Class>>allInstances to count up object memory usage in a domain. - Can also do this with special objects like SmallInteger, Array, CompiledMethod, ... - Also has nice side-effects, e.g. pools, class variables, class-side instance variables, Environments/Namespaces/SystemDictionaries can be domain specific. Disadvantages: - umm... well its a bit hard to implement, but no less so than any other ways of doing this. So who takes the credit for this? Alexandre Bergel and Klaus Witzel? Michael. |
On Sat, 12 Aug 2006 03:41:17 +0200, Michael van der Gulik wrote:
> Klaus D. Witzel wrote: >> Hi Michael, >> on Tue, 08 Aug 2006 11:19:37 +0200, you wrote: >> Klaus D. Witzel wrote: >> That's the easy part: clones of classes share their method dictionary >> (in form of a pointer, not as a copy). Only the class pointer of per >> domain created instances is changed, nothing more and nothing else. A >> very good ROI, that is :) > > ....wow. That is thinking outside the square. I had never considered > stripping a thin layer off Class/Metaclass like that. > > So, a concrete example is needed. Say I have a class "Person". Then, > normally: > > alice := Person new. > bob := Person new. > > In a domained image, say I have two domains, alicesDomain ("ad") and > bobsDomain ("bd"). Now: > > adPerson = Person class copy new. " adPerson is a Class " > "<<Do class initialisation and stuff here, copying stuff from Person>>" > adPerson methodDict: Person methodDict. > adPerson domain: alicesDomain. " Sets an instance variable in the Class" > > bdPerson = Person class copy new. > "<<Do class initialisation here>>" > bdPerson methodDict: Person methodDict. > bdPerson domain: bobsDomain. and/or #new in the presence of a metaclass. I would'nt even whisper such words when a class is around; classes/behavior have (too) tight a relation with ClassBuilder and comrades, so I tend to think of it as #copy being reserved for exclusive use by that comradeship. I always use #clone for classes (after checking with the implementors of #clone in the releases of Squeak, of course). > Now we can do: > alice := adPerson new. > bob := bdPerson new. 8-) > In other words, each domain has its own set of classes, but each class > shares its instance variables (methodDict, instanceVariables, > superclass, format etc) with other classes of the same... er... class. Yes, and it would be sufficient to just clone the fields superclass, methodDict and format (like in an instance of Behavior). This is all that the VM needs. I have direct subclasses of Behavior in my projects, see attached example on negotiable interfaces. Message category '*required-by-my-users' keeps users of direct subclasses of Behavior not bark so loud. > I could probably cludge up some Namespacing or other magic to get > "Person" to resolve to the domain's local version of the Person class, > so you don't need to use "adPerson" and "bdPerson" but just "Person". > > So now, finding the domain of any given object would be easy: > > Object>>domain > ^ self class domain. > > Trivial! > Disadvantages: > - umm... well its a bit hard to implement, but no less so than any other > ways of doing this. Yes, I think so, too. > So who takes the credit for this? Alexandre Bergel and Klaus Witzel? Alex was the first person that I met who understood what I was talking about. So yes, it was invented by the two of us. /Klaus > Michael. NegotiableInterface.st (22K) Download Attachment |
In reply to this post by Michael van der Gulik
On Sat, 12 Aug 2006 03:41:17 +0200, Michael van der Gulik wrote:
... > In other words, each domain has its own set of classes, but each class > shares its instance variables (methodDict, instanceVariables, > superclass, format etc) with other classes of the same... er... class. > > I could probably cludge up some Namespacing or other magic to get > "Person" to resolve to the domain's local version of the Person class, > so you don't need to use "adPerson" and "bdPerson" but just "Person". Have you considered using classboxes for that, see - http://citeseer.ist.psu.edu/684648.html Though classboxes is about local methods, it can be put to use for "just" local classes. /Klaus |
But classboxes were an experiment. The tool support is not deep enough
On 12 août 06, at 05:45, Klaus D. Witzel wrote: > On Sat, 12 Aug 2006 03:41:17 +0200, Michael van der Gulik wrote: > ... >> In other words, each domain has its own set of classes, but each >> class shares its instance variables (methodDict, >> instanceVariables, superclass, format etc) with other classes of >> the same... er... class. >> >> I could probably cludge up some Namespacing or other magic to get >> "Person" to resolve to the domain's local version of the Person >> class, so you don't need to use "adPerson" and "bdPerson" but just >> "Person". > > Have you considered using classboxes for that, see > > - http://citeseer.ist.psu.edu/684648.html > > Though classboxes is about local methods, it can be put to use for > "just" local classes. > > /Klaus > > |
On Sat, 12 Aug 2006 10:50:56 +0200, stéphane ducasse wrote:
> But classboxes were an experiment. The tool support is not deep enough Thanks for the hint, Stef. Nevertheless, I'd say it is worth the investigation, just to find out what can be stolen from others (err, reused). And tool support is not an issue here, just "clones of local classes on the fly", which become garbage after an app (or a client or so) is closed. /Klaus |
In reply to this post by Klaus D. Witzel
On Thu, 24 Aug 2006 09:46:18 +0200, Alexandre Bergel wrote:
> Sorry to answer so late, I got few emergencies in my work. So we have to thank you twice for your response :) > The technique you describes, Classboxes and selector namespace are > similar somehow. They provide way to (i) support changes in an > unanticipated ways and to (ii) obtain a better modularity of cross- > cutting concern. Note that these techniques are not alone, family > polymorphism (i.e., the gbeta programming language), virtual classes > (i.e., caesarJ), mixin-based inheritance (i.e., Units in MZScheme) help > in achieving similar goals. > > The differences between those systems reside in some very subtle detail > in their semantics. In your example, what happens if a a method in the > "bd" domain calls a method foo in the "ad" domain. Now ad.foo call bar, > which is defined in both domain. In domaining using classes, this is exactly what is wanted, all behavior (=methodDict's) is shared at the oop level, no copy hangs around :) > Which one get invoked ? Domain a and domain b have precisely the same superclass (oop). So the answer is: always the right one, since there exists only one implementor. /Klaus > Depending on the answer, you have the behavior of Classboxes or selector > namespace. If you want more about those difference, I can point out a > paper we wrote on it. > > Regards, > Alexandre > > > Am Aug 12, 2006 um 4:45 AM schrieb Klaus D. Witzel: > >> On Sat, 12 Aug 2006 03:41:17 +0200, Michael van der Gulik wrote: >> ... >>> In other words, each domain has its own set of classes, but each class >>> shares its instance variables (methodDict, instanceVariables, >>> superclass, format etc) with other classes of the same... er... class. >>> >>> I could probably cludge up some Namespacing or other magic to get >>> "Person" to resolve to the domain's local version of the Person class, >>> so you don't need to use "adPerson" and "bdPerson" but just "Person". >> >> Have you considered using classboxes for that, see >> >> - http://citeseer.ist.psu.edu/684648.html >> >> Though classboxes is about local methods, it can be put to use for >> "just" local classes. >> >> /Klaus >> > |
Hi Alex,
can we keep this discussion thread in squeak-dev (and if so then please don't reply just to me). On Thu, 24 Aug 2006 10:55:40 +0200, Alexandre Bergel wrote: >> Domain a and domain b have precisely the same superclass (oop). So the >> answer is: always the right one, since there exists only one >> implementor. > > It means that a client is always in one (and only one) domain. How those > domains are composed each other ? > > For instance, a short example of a class Person that has two domains: > employee and student. Initially, "domaining using classes" has only a Person class. This class (and all other classes in the same image) belong to the single #system domain by default. When an #employee domain or #student domain is created, instances of Person become member of the respective domain as follows: employeePerson := (Person clone nowYouClonedClassBelongsToDomain: #employee) new. studentPerson := (Person clone nowYouClonedClassBelongsToDomain: #student) new. Observe when and where #new is executed. Then, (employeePerson domain) printIt => #employee (studentPerson domain) printIt => #student (employeePerson class) printIt => 'a Person in domain #employee' (studentPerson class) printIt => 'a Person in domain #student' > Person>>employeeDomain.salary > ^ 2000 > > Person>>studentDomain.nbOfCoursesTaken > ^ 4 > > Easy. I think that our subject "domaining using classes" does not have such methods. The methods do not change when domain membership becomes effective (i.e. do not have the domainName. prefix from your examples), they change neither automagically nor manually. > the method salary can be invoked by an object x only if x "is" in a > domain employee. Same thing for nbOfCourseTaken. > > Imagine now the few methods: > > "Public methods" > Person>>employeeDomain.printString > ^ self printOn: (WriteStream on: String new). > > Person>>studentDomain.printString > ^ self printOn: (WriteStream on: String new). > > > Person>>printOn: stream > self generalInfo printOn: steram "CRITICAL QUESTION HERE" > self description printOn: stream "CRITICAL QUESTION HERE" > > Person>>employeeDomain.description > "Description for being an employee" An instance of Person in domain #employee does not have the "is an employeePerson" property. Instead, it has the "my class belongs to the #employee domain" property. This implies that the "domained" Person instance belong the their class' domain. > Person>>employeeDomain. generalInfo > "Description for being an employee" Same as above. > Person>>studentDomain.description > "Description for being a student" Same as above with s/employee/student/. > Person>>studentDomain. generalInfo > "Description for being a student" Same as above with s/employee/student/. > printOn: is not part of any domain (or belongs to a 'default' domain). > When printOn: is invoked, how do you know the right method to select ? Since we have "just" clones of classes, we always select the right method, because only that one method exists? > What does it mean to "be" in a domain ? Any class can be cloned and the clone is added to a domain (a domain has an identifier and a collection of members, i.e. a collection of cloned classes). Instances of a domained class belong to their class' domain. > I am really interested by this discussion! :) /Klaus > cheers, > Alexandre |
> Initially, "domaining using classes" has only a Person class. This
> class (and all other classes in the same image) belong to the > single #system domain by default. > > When an #employee domain or #student domain is created, instances > of Person become member of the respective domain as follows: > > employeePerson := (Person clone nowYouClonedClassBelongsToDomain: > #employee) new. > studentPerson := (Person clone nowYouClonedClassBelongsToDomain: > #student) new. > > Observe when and where #new is executed. Then, > > (employeePerson domain) printIt => #employee > (studentPerson domain) printIt => #student What is the difference between this and a classical namespace ? With namespaces I would have: employeePerson := Employee.Person new. studentPerson := Student.Person new. (employeePerson class namespace) printIt => #employee (studentPerson class namespace) printIt => #student What is the impact of domaining on the method lookup ? cheers, Alexandre Am Aug 24, 2006 um 10:57 AM schrieb Klaus D. Witzel: > Hi Alex, > > can we keep this discussion thread in squeak-dev (and if so then > please don't reply just to me). > > On Thu, 24 Aug 2006 10:55:40 +0200, Alexandre Bergel wrote: > >>> Domain a and domain b have precisely the same superclass (oop). >>> So the answer is: always the right one, since there exists only >>> one implementor. >> >> It means that a client is always in one (and only one) domain. How >> those domains are composed each other ? >> >> For instance, a short example of a class Person that has two >> domains: employee and student. > > Initially, "domaining using classes" has only a Person class. This > class (and all other classes in the same image) belong to the > single #system domain by default. > > When an #employee domain or #student domain is created, instances > of Person become member of the respective domain as follows: > > employeePerson := (Person clone nowYouClonedClassBelongsToDomain: > #employee) new. > studentPerson := (Person clone nowYouClonedClassBelongsToDomain: > #student) new. > > Observe when and where #new is executed. Then, > > (employeePerson domain) printIt => #employee > (studentPerson domain) printIt => #student > > (employeePerson class) printIt => 'a Person in domain #employee' > (studentPerson class) printIt => 'a Person in domain #student' > >> Person>>employeeDomain.salary >> ^ 2000 >> >> Person>>studentDomain.nbOfCoursesTaken >> ^ 4 >> >> Easy. > > I think that our subject "domaining using classes" does not have > such methods. The methods do not change when domain membership > becomes effective (i.e. do not have the domainName. prefix from > your examples), they change neither automagically nor manually. > >> the method salary can be invoked by an object x only if x "is" in >> a domain employee. Same thing for nbOfCourseTaken. >> >> Imagine now the few methods: >> >> "Public methods" >> Person>>employeeDomain.printString >> ^ self printOn: (WriteStream on: String new). >> >> Person>>studentDomain.printString >> ^ self printOn: (WriteStream on: String new). >> >> >> Person>>printOn: stream >> self generalInfo printOn: steram "CRITICAL QUESTION HERE" >> self description printOn: stream "CRITICAL QUESTION HERE" >> >> Person>>employeeDomain.description >> "Description for being an employee" > > An instance of Person in domain #employee does not have the "is an > employeePerson" property. Instead, it has the "my class belongs to > the #employee domain" property. This implies that the "domained" > Person instance belong the their class' domain. > >> Person>>employeeDomain. generalInfo >> "Description for being an employee" > > Same as above. > >> Person>>studentDomain.description >> "Description for being a student" > > Same as above with s/employee/student/. > >> Person>>studentDomain. generalInfo >> "Description for being a student" > > Same as above with s/employee/student/. > >> printOn: is not part of any domain (or belongs to a 'default' >> domain). When printOn: is invoked, how do you know the right >> method to select ? > > Since we have "just" clones of classes, we always select the right > method, because only that one method exists? > >> What does it mean to "be" in a domain ? > > Any class can be cloned and the clone is added to a domain (a > domain has an identifier and a collection of members, i.e. a > collection of cloned classes). Instances of a domained class belong > to their class' domain. > >> I am really interested by this discussion! > > :) > > /Klaus > >> cheers, >> Alexandre > -- _,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;: Alexandre Bergel http://www.cs.tcd.ie/Alexandre.Bergel ^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;._,.;:~^~:;. |
On Thu, 24 Aug 2006 16:14:05 +0200, Alexandre Bergel wrote:
> Klaus wrote: >> Initially, "domaining using classes" has only a Person class. This >> class (and all other classes in the same image) belong to the single >> #system domain by default. >> >> When an #employee domain or #student domain is created, instances of >> Person become member of the respective domain as follows: >> >> employeePerson := (Person clone nowYouClonedClassBelongsToDomain: >> #employee) new. >> studentPerson := (Person clone nowYouClonedClassBelongsToDomain: >> #student) new. >> >> Observe when and where #new is executed. Then, >> >> (employeePerson domain) printIt => #employee >> (studentPerson domain) printIt => #student > > What is the difference between this and a classical namespace ? Several differences are at work here: - Squeak doesn't have such thing - same class (#clone) is in multiple name spaces, what other system does that? - Michael van der Gulik, the first potential user, "just" wants to partition object memory into domains (by coloring classes, as discussed with you in Bern) - the domained instances have only a "thin" change: just their class pointer differs between domains - behavior is the same in all domains > With namespaces I would have: > employeePerson := Employee.Person new. > studentPerson := Student.Person new. Nice. In which system (language, programmable) is this fully supported (having only one class object named Person)? > (employeePerson class namespace) printIt => #employee > (studentPerson class namespace) printIt => #student > > What is the impact of domaining on the method lookup ? At the current stage of discussion: none, but that will change as soon as the next idea arrives :) /Klaus > cheers, > Alexandre |
In reply to this post by Alexandre Bergel-2
Alexandre Bergel wrote:
>> Initially, "domaining using classes" has only a Person class. This >> class (and all other classes in the same image) belong to the single >> #system domain by default. >> >> When an #employee domain or #student domain is created, instances of >> Person become member of the respective domain as follows: >> >> employeePerson := (Person clone nowYouClonedClassBelongsToDomain: >> #employee) new. >> studentPerson := (Person clone nowYouClonedClassBelongsToDomain: >> #student) new. Umm... yea... whatever. It depends how its all implemented. >> Observe when and where #new is executed. Then, >> >> (employeePerson domain) printIt => #employee >> (studentPerson domain) printIt => #student > > > What is the difference between this and a classical namespace ? > > With namespaces I would have: > employeePerson := Employee.Person new. > studentPerson := Student.Person new. Domains are used for managing resources. Namespaces are used for managing the uniqueness of class names. Many objects of the same class (and thus in the same Namespace) could be in different domains. The concept of a "Domain" is my own invention, and I'm not entirely happy with the name; it's already overused in many areas of computer science. Perhaps "ResourceDomain" would be a better name? Also; don't get too caught up with implementation details. At the moment I've got working code which basically copies a class, adds a domain instance var to that class object and returns a new object of that class. It works, but it's a big hack and is only excusable because I couldn't think of a better way of implementing it without massive VM changes. Ideally, there would be VM changes which would group objects of the same domain physically in memory. I also think a Domain like I'm using it is just like Lex Spoon's Islands, so I'll be looking at his code soon. Incidentally, it seems I've implemented one of the few things he didn't - managing memory usage. Islands: http://minnow.cc.gatech.edu/squeak/2074 > (employeePerson class namespace) printIt => #employee > (studentPerson class namespace) printIt => #student > > > What is the impact of domaining on the method lookup ? Hopefully none, but that's dependent on how it is all implemented. When my code is usable by others, I'll be putting it online somewhere. Cheers, Michael. |
Free forum by Nabble | Edit this page |