= Compatibility and layout of code =
== Overview ==
The coThreads library treat compatibility seriously:
* No touch to the compiler, run-time and libraries from the standard distribution, pure implementation at user space
* No modification to the original Threads library, all extension is provided as extra modules
Under such principles, the final layout of engines turns out to be a set of directories with isomorphic structure (files from standard distribution postfixed with (*)
STDLIBDIR/
|
`- common interface: cothread.cmi, mutex.cmi, condition.cmi, event.cmi, stm.cmi
|
`- vmthreads/: threads.cm(x)a*, cothreads.cm(x)a, ...
|
`- threads/: threads.cm(x)a*, cothreads.cm(x)a, ...
|
`- process/: threads.cm(x)a, cothreads.cm(x)a, ...
|
`- networker/: (TODO)
threads.cm(x)a = threads.cm[ox], mutex.cm[ox], condition.cm[ox], event.cm[ox]
cothreads.cm(x)a = threads.cm[ox], mutex.cm[ox], condition.cm[ox], event.cm[ox], cothread.cm[ox], stm.cm[ox]
Here, threads.cm(x)a is the library compatible with standard Threads implementation, and cothreads.cm(x)a is a super set of Threads which has extra modules such as CoThread, STM included.
There are several advantages:
* Your legacy code can now compile to other back-ends without any modification ((Be sure to read the [[pitfall]] page before you start)). You don't have to be aware of the existence of cothreads.cm(x)a, because threads.cm(x)a is provided for each engine.
* The isomorphic file structure(structure) make it quite easy to write concise Makefile.
* the common interface files, located in the upper level directory, can help to achieve object-level compatibility, as well as source-level compatibility, among different engines.
== Object-level compatability ==
Source-level compatibility means that a single copy of source code can be independently compiled to different copies of executable without any modification. The standard Threads library already has this property((Well, almost true, as far as you don't use "Thread.sleep", "Thread.wakeup", "Thread.sigmask" "Thread.critical_section".)), and coThreads does the same. Object-level compatibility means that a single copy of source code can be compiled to a **single** copy of object files, which in turn links against different engines to get different copies of executable. With coThreads, as far as you compile your source code against the common interfaces in the upper level directory((Or, you can still compile your source code against interfaces in the sub-directories, but don't make use of Thread module (use its super set CoThread instead).)), you can get the object-level compatibility.
What are the benefits of object-level compatibility between engines?
* Object files are built just once, save time and energy
* Debugging, building, keeping and distributing a single copy of object files --- this is especially useful to those developing modules based on Threads. Previously, they have to maintenance several copies, which is tedious and confusing sometimes.
It's fairly simple to achieve object-level compatability. The only principle is --- do not use Thread module because Thread interfaces (thread.cmi) of different engines don't agree! Use Cothread module if you can. Note that this is not the problem from coThreads, it's a limitation of standard Threads library:
* The Thread interfaces of system threads and VM threads coming with the standard distribution **already** differ with each other, so that the objects compiled with system Thread won't be able to mix with objects compiled with VM thread, vice versa.
* We have no way to unify the three of them without modifying the files from original distribution, which is exactly what we manage to avoid.
All other modules, e.g. Mutex, Event and STM, don't have this problem. The best practice is to compile your source code against the common interface files of $STDLIBDIR instead of a specific engine directory such as $STDLIBDIR/vmthreads. Once compiled, you will be ensured that the result objects can be linked against any of the engines with no problems. That's why ''thread.cmi'' is absent from the common interface files at $STDLIBDIR --- it's not **common**!
== Comptability guide-line ==
It's not in every case you'd bother to get object-level compatability, especially with legacy code. Here are several typical scenarios:
* You have some legacy code written in standard Threads, and you'd like to compile it into process engine to get speedup. You don't want to change a single line of source and don't care about other newly introduced modules of coThreads at all. In such case, add one line to your Makefile:
# Previously, with system threads
ocamlopt -I +threads -o myprog.nath.opt unix.cmxa threads.cmxa myprog.ml
# Now, also compiled to process
ocamlopt -I +process -o myprog.proc.opt unix.cmxa threads.cmxa myprog.ml
* You have some legacy code written in standard Threads, and you'd like to have it run with processes. Though you don't care about the newly introduced modules of coThreads, you do want to have a single copy of object files for each engines. In such case, you need to add one line to any source code which makes use of the Thread module:
module Thread = Cothread
which substitute the use of Thread module with Cothread module, and change any occurrence of "threads.cm(x)a" to "cothreads.cm(x)a" in your Makefile. Now you can compile your source code against the common interface in the upper level directory (or still the sub-directory, that's fine) but link to library files of different engines in the sub-directories.
ocamlopt -c myprog.ml
# Or you can still compile your source against some engine like
# ocamlopt -c -I +threads myprog.ml
ocamlopt -I +threads -o myprog.nath.opt unix.cmxa cothreads.cmxa myprog.cmx
ocamlopt -I +process -o myprog.proc.opt unix.cmxa cothreads.cmxa myprog.cmx
* You program some library/application from scratch and want to parallel the computation. In such case,
** make use of coThreads instead of Threads unless your destination platform restrict your choice to standard OCaml libraries, choose the right [[paradigm]]
** follow the instruction in the last case to compile, or better, use pattern rules of Makefile to automate the compilation (check the ''example'' directory of coThreads distribution for a simple one)