Changes between Version 1 and Version 2 of Sysel

2010-04-11T09:56:39Z (14 years ago)
Jiri Svoboda


  • Sysel

    v1 v2  
    4141 * method and operator overloading
    4242 * packaging
     44== Ideas for Sysel ==
     46=== Dynamic linking ===
     48It should be possible to use, with similar simplicity and the same level of static type checking, not only ''compulsory libraries'', but also ''optional libraries'' and ''plugin libraries''.
     50Compulsory libraries are those required every time the executable is invoked (equivalent to `gcc -lname`). Optional libraries are only loaded once the application touches some symbol from the library. This is a very useful feature that allows building binaries with all optional dependencies enabled, yet the user need not install all these libraries if they do not want to. This helps avoiding ''dependency avalanches''.
     52Plugin libraries are those where multiple libraries can exist written again some common plugin interface. One possibility is to have ''packages'' implement ''package interfaces''. A package could be loaded at run time, a reference to it stored to a variable whose type is the ''package interface'' type. Then it would be possible to refer to symbols within the dynamic package using standard qualified names (e.g. `P.symbol`). This enables full static type checking / interface checking for both the implementor and user of the plugin.
     54=== Remote objects ===
     56==== Basics ====
     58HelenOS IPC is usually employed in an RPC-like style. Remote objects would support asynchronous messaging in the language itself. Remote object classes (and interfaces) form a separate hierarchy of inheritance to the ''local'' classes and interfaces. Remote interfaces are equivalent to IPC interfaces now usually defined in HelenOS in `uspace/lib/c/include/ipc`. They would naturally support (multiple) inheritance. Servers contain remote classes which implement these interfaces.
     60When a client wants to use some service, they are given a reference to a remote object. This reference identifies not only the server which we talk to, but possibly also the individual resource within the server that we are accessing. For a contrived example, a console server might provide the two interfaces:
     63interface IConsole, remote is
     64        fun GetVC(vc_index : int) : IVC;
     67interface IVC, remote is
     68        fun GotoXY(x, y : int);
     69        fun Write(s : string);
     73When we invoke the GetVC() method, the console server will pass us a reference to the remote object implementing the requested VC. Then we can work with this particular VC using that reference:
     76var Con : IConsole;
     77var VC : IVC;
     79C = NameService.GetConnection("console") as IConsole;
     80VC = C.GetVC(2);
     83Connection creation and termination, as well as transaction management (identifying the objects being worked with) is automatically handled by the language run-time. Also handled automatically is the creation of threads and fibrils within a server. A server can potentially handle any number of parallel requests (though it might be possible to limit this with some quota, if required). Concurrent access to remote objects is possible (and often desired).
     85==== Remote invocation ====
     87When a method of a remote object is invoked, the method ID and its parameters are serialized and the resulting message is sent to the server. On the server the method ID and arguments are de-serialized and the implementation of the method is invoked. When the method returns, the return value (and possibly output arguments) are serialized and sent back to the client. At the client the return value(s) are de-serialized and returned to the caller.
     89Some notes:
     90 * Multiple threads/fibrils may use the same remote object in parallel without fear of blocking each other (as long as the server is properly implemented)
     91 * Stateful services can be implemented by the server handing out state objects (such as open-file object on a file server).
     93==== Promises ====
     95[ Promises] can be used to express asynchronous behavior and potentially allow for [ promise pipelining] (a form of optimization). In our case it would suffice to have a specialized form of promise, one that promises some data to be delivered from a remote object. Promises would be declared using a prefix type operator `future`.
     97As long as the data received from a remote object stays in a type that is `future`, it is handled in an asynchronous fashion. Once the data is converted to a non-future type, the execution blocks until the data is received.
     102interface IAsyncIO is
     103        fun AReadBlock(addr : int) : future Block;
     108fun ReadBlocksParallel(start_addr, count : int) : Block[] is
     109        var fblock : future Block[];
     111        for i in range(0, count) do
     112                -- This does not block
     113                fblock[i] = AReadBlock(start_addr + i);
     114        end
     116        -- All reads are now being executed in parallel.
     118        -- Each array element is implicitly converted from future Block[] to Block[].
     119        -- This blocks until all data has been received.
     120        return fblock;