Let T(E <:Ok) <:Ok = word.Handle(E)
let lib = runtimeCore.auxiliaryLibraryName("test")
let list_new = bind(:Fun(E <:Ok) :T(E) lib "list_new" "w")
Create a new subdirectory 'src/test' and use this library definition:
library test
with
library machineenv stdenv bulkenv
interface
CList
module
cList :CList
end;
Write an implementation 'cList.tm' for this interface 'CList.ti' using the C functions from the C module 'test.c':
interface CList
(* System: test
File: CList.ti
Author: Gerald Schr"oder
Date: 24-jun-1996
Purpose: Lists using C functions
*)
export
T(E <:Ok) <:Ok
(* Type of polymorphic lists. *)
error :Exception end
(* Raised when trying to access freed list. *)
new(E <:Ok) :T(E)
(* Create a new (empty) list. *)
insert(E <:Ok :T(E) :E) :Ok
(* Insert an element into the list. Raise error if list has been freed. *)
iterate(E <:Ok :T(E) :Fun(:E) :Ok) :Ok
(* Call iteration function for each element of the list.
Raise error if list has been freed. *)
free(E <:Ok :T(E)) :Ok
(* Free list. Do not call 'insert', 'iterate' or 'free' on this list again!
Raise error if list has been freed. *)
end;
Test your implementation with:
do makeLibraries test;
import print cList;
Let Person = Tuple name :String age :Int end;
let peter = tuple "Peter" 22 end;
let paul = tuple "Paul" 32 end;
let mary = tuple "Mary" 28 end;
let printPerson(p :Person) :Ok =
begin
print.string(p.name)
print.string(" (")
print.int(p.age)
print.string(")\n")
end;
let myList = cList.new(:Person);
cList.insert(myList peter);
cList.insert(myList paul);
cList.insert(myList mary);
cList.iterate(myList printPerson);
cList.free(myList);
Hints: Take the definitions of 'T' and 'list_new' given above as a starting point. Use (only) the modules 'runtimeCore', 'word' and 'cCallback' from 'machineenv'. Note the parameter descriptions 'w' for C values and '=' for TL values. Refer to other module implementations using the 'bind' construct.
tycoon -create -store test.ts
do makeLibraries test;
import print cList;
Let Person = Tuple name :String age :Int end;
let peter = tuple "Peter" 22 end;
let paul = tuple "Paul" 32 end;
let mary = tuple "Mary" 28 end;
let printPerson(p :Person) :Ok =
begin
print.string(p.name)
print.string(" (")
print.int(p.age)
print.string(")\n")
end;
let myList = cList.new(:Person);
cList.insert(myList peter);
cList.insert(myList paul);
cList.insert(myList mary);
cList.iterate(myList printPerson);
do saveSystem;
cList.free(myList);
do exit;
tycoon -restart -store test.ts
cList.iterate(myList printPerson);
This may lead to bus errors or other unpredictable behaviour. Why? Think about the two storage areas: the persistent Tycoon store and the transient C heap. Try to paint a map with references between these stores, i.e. where are pointers from the Tycoon to store to the C heap and vice versa? What happens if the Tycoon store is stabilized? Where does this leave the transient data, the pointers to transient data and the references from the external data to the Tycoon store objects? When should the transient C heap objects be deallocated? (Note that this cannot be done automatically in Tycoon yet. Refer to Deallocating transient data structures.) When should the transient C heap objects be allocated again?
Taking this into account, rewrite the implementation of 'cList' using tge module 'volatile' from 'machineenv' to reconstruct the transient data on restart. Test with the script above, but insert the statements
import volatile; volatile.recreateAll();after restart before calling 'cList.iterate'.