DRAFT -- ECLiPSe 7.0 Release Notes

The main news for this release is the introduction of the multi-engine/multi-thread functionality.

Engines and Threads

An 'engine' is an entity with independent control flow and data areas. In previous versions of ECLiPSe, all code executed in a single, implicit engine. Starting with release 7, engines can be freely created and manipulated.

The essential characteristics of engines are:

This opens up a range of new programming techniques, such as

The four basic new primitives for this are:
engine_create(-Engine, ++Options)
Create a new ECLiPSe engine
engine_resume(+Engine, +Term, -Status)
Resume execution of an engine and return result status
engine_resume_thread(+Engine, +Term)
Asynchronously resume execution of an engine (in a separate thread)
engine_join(+Engine, +Timeout, -Status)
Wait for an engine to stop running, and return its status
Note that the resume/yield model of engine control is a generalisation of the model that was already used previously in the foreign language interface to control ECLiPSe execution.

As an alternative interface to the multithreading functionality, we provide library(threads), which implements the functionality defined in ISO/IEC DTR 13211-5:2007.

New Built-In Predicates

Further engine-related functionality

engine_post_event(+Engine, +Event)
Post an event to an engine
engine_properties(+Engine, -Properties)
Obtain a list of the engine's properties
engine_self(-Engine)
Get a handle of the engine executing the call
engine_status(+Engine, -Status)
Obtain the status of an engine
yield(+ToParent, -FromParent)
Stop the running engine in the yielded-state, and wait for resume

Array functionality

array_sort(+Key,+Order,+Array,-Sorted)
term_variables_array(?Term, -VarArr)

String functionality

New string operations have been added in coordination with SWI-Prolog.

atomics_to_string(+Atomics,-String)
atomics_to_string(+Atomics,+Glue,-String)
get_string_code(+Index,+String,-Code)
read_string(+Stream, +SepChars, +PadChars, -Separator, -String)
string_char(?Index, +String, ?Char)
string_chars(?String, ?Chars)
string_code(?Index, +String, ?Code)
string_codes(?String, ?Codes)
string_concat(?String1, ?String2, ?String3)
string_lower(++String, -Upper)
string_upper(++String, -Upper)
sub_string(+String, ?Before, ?Length, ?After, ?SubString)
text_to_string(++Text, -String)
term_string(?Term, ?String, +Options)

Storage primitives

New storage primitives have been introduced, mainly for convenience in multithreaded applications.

recorded_count(+RecordHandle,-Count)
record_wait_append(+RecordHandle,+Value,+Timeout,+Max)
record_wait_remove(+RecordHandle,-Value,+Timeout)
shelf_get_and_dec(+ShelfHandle, +Index, -OldValue)
shelf_inc_and_get(+ShelfHandle, +Index, -NewValue)
shelf_test_and_set(+ShelfHandle, +Index, +Expected, ?NewValue)
store_insert(+StoreHandle, ++Key, ?Value)
store_remove(+StoreHandle, ++Key, -Value)
store_update(+StoreHandle, ++Key, -OldValue, ?NewValue)
store_test_and_set(+StoreHandle, ++Key, ++OldValue, ?NewValue)
In addition, all storage handles can serve as mutexes and condition variables.

Names and handles

getref(+Name,-Term)
Replaces getval/2 for named references
setref(+Name,?Term)
Replaces setval/2 for named references
is_handle(+Handle,?Class)
Test for a handle of a particular class, or query a handle's class
name_to_handle(+Class,+Name,-Handle)
Get an anonymous handle from a name

Mutual exclusion and thread synchronisation

with_mutex(++Handle, +Goal)
Equivalent to once(Goal) but with mutual exclusion
condition_signal(+Handle, +Mode)
Signal a condition on a handle
condition_wait(+Handle, +Timeout)
Wait for a condition to be signaled on a handle
record_wait_append(+Key,+Value,+Timeout,+Max)
like recordz/2, but with synchronization
record_wait_remove(+Key,-Value,+Timeout)
like erase/2, but with synchronization
All storage handles can serve as mutexes and condition variables, and stream handles can serve as mutexes.

Term testing and manipulation

term_variables(?Term, -Vars) - semantic change!
See below.
term_variables_array(?Term, -VarArray)
Like term_variables/2, but returning an array.
term_variables_count(?Term, -VarCount)
Count of distinct variables.
All these operations now handle cyclic terms as well.

Libraries

New Libraries

lib(concurrency)
A library providing higher-level primitives for concurrent/multi-thread programming, implemented using engines.
lib(best_first_search)
A library implementing sequential best-first-search in conjunction with propagation-based solvers. It works by recomputing search states.
lib(lists_of_structures)
A library handling operations on lists of structures, in particular where one structure element serves as a key.

New Compatibility Libraries

lib(eclipse_6)
A small library containing predicates whose semantics changed in this release, in particular term_variables/2.
lib(clpfd)
A compatibility wrapper for library(ic) to simplify running of code developed for SICStus Prolog's library(clpfd) and SWI-Prolog's library(clpfd).
lib(dynamic_attributes)
Implements Bart Demoen's attributed variable API (as used by hProlog and SWI-Prolog). These are implemented on top of ECLiPSe's native attributed variable functionality, and can be mixed with those.
lib(error)
A utility library to help type checking and raising ISO-Prolog compatible exceptions.
lib(threads)
A compatibility wrapper that implements a thread-interface as defined in ISO/IEC DTR 13211-5:2007 on top of ECLiPSe's multi-engine functionality.

Contributed Libraries

lib(lambda)
A library simplifying the use of higher-order terms.

Library Enhancements

library(atts)
Allowed 3rd argument for goal-return to pre_unify handler for attributes. Full implementation of verify_attributes/3 in lib(atts), runs SICStus manual examples without change.
library(branch_and_bound)
bb_min/3 has a new option for finding all optimal solutions (solutions:one/all)
library(calendar)
added easter_mjd/2
library(hash)
added hash_list/2, hash_insert/3
library(iso_strict) and library(iso)
conformance to ISO-Prolog corrigendum 3, and elimination of remaining discrepancies in output spacing
library(lists)
added maplist/2, collection_to_array/2
library(swi)
improved compatibility

Gecode Interface

Other Changes

Global flags (get_flag/2)
A new flag cpu_count indicates the number of logical processors on the machine, which can be helpful in deciding how many threads to create. The new flags default_localsize and default_globalsize determine the default stack sizes for additional engines. The enable_interrupts flag has been removed (interupts are now handled by a separate thread).
Statistics statistics/2 and cputime/1
New statistics items: cputime (like cputime/1, gives thread cpu time), dict_gc_countdown (remaining functor creations until dictionary garbage collection gets triggered), dict_gc_running (true if a dictionary GC is currently underway).
Generalized sort/4 and merge/5
The sort/4 and merge/5 predicates accept additional order specifications, making number_sort/4 and number_merge/5 obsolete (coordinated with SWI).
Updated printf/2,3
Better formatting options for strings, removed restrictions regarding bignums.
New DCG implementation
The Definite Clause Grammar translator (for clauses of the form H-->B) has been revised, maximising compatibility and fixing some long-standing bugs.

Incompatibilities

Interrupt/Signal handling
Non-fatal signals are now handled by a dedicated thread, and because of multi-threading, there is no longer a notion of "the interrupted execution". As a result, an interrupt handler can no longer abort a running execution by calling throw/1, but has to be designed to deal appropriately with all the running application threads.
Term variables
The term_variables/2 built-in predicate historically returned a variable list in reverse order of left-to-right occurrence in Term. This was unusual, made the predicate non-idempotent, and didn't agree with the ISO Prolog standard. The order has now changed to correspond to the order in which the variables occur in Term in a depth-first, left-to-right traversal. Unfortunately, the change may have subtle effects on programs developed on previous ECLiPSe versions, such as different search trees in constaint programs. The old version can be imported from library(eclipse_6) if necessary.
Syntax - back-quote character
For eclipse_language, we have changed the default character class of the back-quote character ` (code point 96) from symbol to list_quote. This allows lists of character codes to be written like `abc` (compatible with SWI-Prolog). Applications that use this character for constructing unquoted symbolic atoms (like `=) will have to use a chtab(0'`,symbol) declaration to locally restore the original behaviour.
Syntax - radix notation
The syntax option based_bignums is now enabled by default. This means that integers written in radix notation can be larger than the machine's word size, and are not interpreted as two's complements. E.g. 16'ffffffffffffffff is read as 18446744073709551615 rather than -1.
Term writing - spacing
In compact-mode (write-option compact(true), or per-module syntax_option(dense_output)), the term writing built-ins now suppress redundant blank space more aggressively than previously. In non-compact mode, spaces are always printed between operators and their arguments.
Term writing - parentheses
When printing terms with prefix functor -/1 and +/1, redundant parentheses are no longer printed. Instead, space is inserted if necessary. (This applies only to modules using traditional ECLiPSe syntax; for modules using ISO syntax, the rules required by standard corrigendum 3 apply).

Performance

Performance should generally not be very different from release 6.1. However, there were a number of implementation changes related to the multithread capability, for example related to locking access to shared data structures. If you notice any unexpected effects, please contact eclipse-clp-bugs@lists.sourceforge.net. Other points are:

Supported Architectures

This release is available for the following architectures: