Next: Introduction, Previous: (dir), Up: (dir) [Contents][Index]
This is the stmx Reference Manual, version 2.0.5, generated automatically by Declt version 3.0 "Montgomery Scott" on Tue Dec 22 15:08:03 2020 GMT+0.
• Introduction | What stmx is all about | |
• Systems | The systems documentation | |
• Modules | The modules documentation | |
• Files | The files documentation | |
• Packages | The packages documentation | |
• Definitions | The symbols documentation | |
• Indexes | Concepts, functions, variables and data types |
STMX is a high-performance implementation of composable Transactional Memory (TM) for Common Lisp. TM is a concurrency control mechanism aimed at making concurrent programming easier to write and understand. Instead of traditional lock-based programming, one programs with atomic memory transactions, which can be composed together to make larger atomic memory transactions.
A memory transaction gets committed if it returns normally, while it gets rolled back if it signals an error (and the error is propagated to the caller).
Finally, memory transactions can safely run in parallel in different threads, are re-executed from the beginning in case of conflicts or if consistent reads cannot be guaranteed, and their effects are not visible from other threads until they commit.
Memory transactions give freedom from deadlocks, are immune to thread-safety bugs and race conditions, provide automatic roll-back on failure, and aim at resolving the tension between granularity and concurrency.
Fixed STMX for internal changes in SBCL 2.0.0 and SBCL 2.0.2. Updated list of Intel CPUs supporting memory transactions in hardware (Intel TSX) - see below.
Version 2.0.1 released. It adds support for transactional structs in addition to transactional CLOS objects, and a faster, struct-based implementation of transactional CONS cells and lists, including several list-manipulating functions - see util/tcons.lisp and util/tlist.lisp
Unluckily, the hardware bug that prompted Intel to disable hardware transactional memory (TSX) in August 2014 is still there, and very few new models are available without the bug. So for the moment STMX will be software-only on many CPUs.
See the file NEWS.md
An introduction is available to explain more in detail what STMX is, what it is not, and how it is implemented.
For background information, Composable Memory Transactions is a very good - though a bit technical - explanation of memory transactions and how they are used and combined. For the interested reader, it also goes in deep detail on how to actually implement them.
STMX is currently tested on the following Common Lisp implementations:
Versions < 1.2 have too old builtin ASDF, and must be manually upgraded to ASDF >= 3.1 to load STMX.
CLISP lacks multi-threading, and its builtin ASDF must be manually upgraded to ASDF >= 3.1 to load STMX.
Version >= 20f no longer support the command line options "-fpu" "x87" and STMX runs reliably only in single-thread mode.
CMUCL has too old builtin ASDF, and must be manually upgraded to ASDF >= 3.1 to load STMX.
There are known issues running STMX on ECL, see Github issues
ECL versions 16.0.0 and 16.1.2 run STMX reliably enough for lightweight use, but sometimes still hang in test suite.
STMX will probably work on several other Common Lisp implementations as long as they support log4cl, closer-mop, bordeaux-threads and trivial-garbage, but the author gives no guarantees.
STMX is available from Quicklisp. The simplest way to obtain it is to first install Quicklisp then run these commands from REPL:
CL-USER> (ql:quickload "stmx")
;; lots of output...
CL-USER> (use-package :stmx)
If all goes well, this will automatically download and install the stable branch of STMX and its dependencies:
log4cl
closer-mop
bordeaux-threads
trivial-garbage
In case you want to use the "latest and greatest" version directly from the author, in order to get the newest features - most notably hardware memory transactions - improvements, bug fixes, and occasionally new bugs, you need to download it into your Quicklisp local-projects folder. Open a shell and run the commands:
$ cd ~/quicklisp/local-projects
$ git clone git://github.com/cosmos72/stmx.git
then proceed as before - load a REPL and run:
CL-USER> (ql:quickload "stmx")
;; lots of output...
CL-USER> (use-package :stmx)
If all goes well, it will automatically load STMX and its dependencies.
Note: unless you know what you are doing, do not try to load different STMX versions one after the other from the same REPL - strange things may happen.
All the stable versions of STMX, present and past, are also available from Sourceforge, including version 1.9.0.
In case you get errors:
check that Quicklisp is installed correctly, for example by executing at REPL:
CL-USER> (ql:quickload "closer-mop")
if you tried to download the stable version from Quicklisp, check that your quicklisp is updated and knows about STMX:
CL-USER> (ql:system-apropos "stmx")
should print something like
#<SYSTEM stmx / stmx-stable-7e68763b-git / quicklisp 2013-06-15>
#<SYSTEM stmx.test / stmx-stable-7e68763b-git / quicklisp 2013-06-15>
If it doesn't, you need to update Quicklisp as described here - search for "To get updated software" in the page.
if you tried to download the latest version from GIT,
check that you downloaded STMX creating an stmx/
folder inside
your Quicklisp local-projects folder, usually ~/quicklisp/local-projects
After loading STMX for the first time, it is recommended to run the test suite to check that everything works as expected. From the REPL, run:
CL-USER> (ql:quickload "stmx.test")
;; lots of output...
CL-USER> (fiveam:run! 'stmx.test:suite)
;; even more output...
Did 7133 checks.
Pass: 7133 (100%)
Skip: 0 ( 0%)
Fail: 0 ( 0%)
Note: (ql:quickload "stmx.test")
intentionally works only after
(ql:quickload "stmx")
has completed successfuly.
The test suite should report zero Skip and zero Fail; the number of Pass may vary. You are welcome to report any failure you get while running the test suite, please include in the report:
See "Contacts, help, discussion" below for the preferred method to send the report.
STMX offers the following Lisp macros and functions, also heavily documented
in the sources - remember (describe 'some-symbol)
at REPL.
TRANSACTIONAL
declares that a class or struct is transactional, i.e. that its
slots contain transactional data. Use it to wrap a class or a struct definition:
(transactional
(defclass foo ()
((value1 :type integer :initarg :value1 :initform 0)
(value2 :type string :initarg :value2 :initform ""))))
(transactional
(defstruct bar ()
(value1 0 :type integer)
(value2 "" :type string)))
If you want to declare a slot as non-transactional, for example because it is
immutable, add the option :transactional nil
:
(transactional
(defclass tred-black-tree ()
((root :type t)
(key-comparator :type function :transactional nil))))
Note: on all Common Lisp implementations listed above, CLOS slot accessors have been tested to work correctly, i.e. they honour the transactional machinery (implemented with MOP slot-value-using-class) and return the same values as SLOT-VALUE.
In the past, some cases were found - and fixed - where slot accessors would not work correctly on transactional classes. It is strongly recommended to run the test suite when using STMX for the first time on a system: it will also check that accessors work on transactional classes.
Support for (TRANSACTIONAL (DEFSTRUCT ...))
was added in STMX version 2.0.1
on January 2015. Previously, only (TRANSACTIONAL (DEFCLASS ...))
was supported.
ATOMIC
is the main macro: it wraps Lisp forms into an atomic
memory transaction then executes them. For example, defining
(defun show-foo (obj)
(declare (type foo obj))
(multiple-value-bind (value1 value2)
(atomic
(values (slot-value obj 'value1)
(slot-value obj 'value2)))
(format t "atomic function show-foo: foo contains ~S, ~S~%"
value1 value2)))
(defmethod set-foo ((obj foo) value1 value2)
(declare (type integer value1)
(type string value2))
(atomic
(setf (slot-value obj 'value1) value1)
(setf (slot-value obj 'value2) value2))
(format t "atomic method set-foo: foo now contains ~S, S~%"
value1 value2))
SHOW-FOO will atomically read the slots VALUE1 and VALUE2 of a FOO
instance, then print both. Note that (format t ...)
is outside the atomic
block - more on this later.
SET-FOO will atomically set the slots VALUE1 and VALUE2 of a FOO instance.
Using these two functions, STMX guarantees that multiple threads accessing the same FOO instance will always see consistent values for both slots, i.e. SHOW-FOO will never see intermediate states of a transaction, where for example one slot has been updated by SET-FOO, but the other slot has not been updated yet.
This is the main feature of STMX: if an atomic block completes normally,
it is assumed to be successful and it gets committed: all its writes
to transactional memory become visible simultaneously to other threads.
If instead an atomic block exits with a non-local control transfer
(signals an error, throws, or invokes a (go some-label)
), it is assumed
to be failed and it gets rolled back: all its writes to transactional memory
are discarded.
Warning: in order to avoid deadlocks and conflicts while still reaching good
performance, STMX may execute more than once the contents of an atomic block.
Also, some instructions as (retry)
described below, explicitly cause an
atomic block to be re-executed from the beginning. For this reasons,
atomic blocks should not contain irreversible operations such as
input/output. More details in the paragraph INPUT/OUTPUT DURING TRANSACTIONS
below.
Note: new threads must be created with (bordeaux-threads:start-thread)
in order to establish thread-local bindings needed by STMX. A safety check
that detects missing thread-local bindings has been recently added to STMX.
Note: STMX allows using transactional data both inside and outside atomic
blocks, but be aware that accessing transactional data from outside
atomic transactions is only intended for debugging purposes at the REPL:
in a program it can cause a lot of problems, due to inconsistencies and due to
other threads not being notified when a transactional memory location is
updated.
Future versions may remove this convenience hack and replace it with a cleaner,
stricter mechanism.
In a program, always make sure that all code that accesses transactional data
is directly or indirectly executed inside an (atomic ...)
block.
TRANSACTION
declares that a method or function is an atomic memory
transaction, and is actually just a macro that wraps the body of a function
or method in an (atomic ...)
block.
In the past, it was suggested as a more convenient alternative to ATOMIC
,
but for various stylistic reasons the current recommendation is to avoid it.
The main reason is that it encourages performing too many operations inside
an atomic block, including irreversible ones as input/output, which has
impredictable behaviour and should be really avoided. Examples:
(transaction
(defun get-foo-values (obj)
(declare (type foo obj))
(values
(value1-of obj) (value2-of obj))))
(transaction
(defmethod set-foo-values ((obj foo) value1 value2)
(declare (type integer value1)
(type string value2))
(setf (value1-of obj) value1)
(setf (value2-of obj) value2)
obj))
Composing transactions
A key feature of ATOMIC
is its composability:
smaller transactions can be composed to create larger transactions.
For example, the following three program fragments are perfectly equivalent:
use (atomic ...)
to wrap into a single transaction many smaller (atomic ...)
blocks
(defmethod swap-value1-of ((x foo) (y foo)) (format t "swapping value1 of ~S and ~S~%" x y) (atomic (rotatef (slot-value x 'value1) (slot-value y 'value1))))
(defmethod swap-value2-of ((x foo) (y foo)) (format t "swapping value2 of ~S and ~S~%" x y) (atomic (rotatef (slot-value x 'value2) (slot-value y 'value2))))
(defmethod swap-contents ((x foo) (y foo)) (atomic (swap-value1-of x y) (swap-value2-of x y)))
write redundant (atomic ...)
blocks
(defmethod swap-contents ((x foo) (y foo)) (format t "swapping value1 and value2 of ~S and ~S~%" x y) (atomic (atomic (rotatef (slot-value x 'value1) (slot-value y 'value1))) (atomic (rotatef (slot-value x 'value2) (slot-value y 'value2)))))
write a single (atomic ...)
block
(defmethod swap-contents ((x foo) (y foo)) (format t "swapping value1 and value2 of ~S and ~S~%" x y) (atomic (rotatef (slot-value x 'value1) (slot-value y 'value1)) (rotatef (slot-value x 'value2) (slot-value y 'value2))))
This composability property has an important consequence: transactional code, possibly written by different people for unrelated purposes, can be combined into larger transactions without modifying it - actually, without looking at the source code at all - as long as it all uses the same transactional library.
The STMX machinery will guarantee that transactions intermediate status, where an atomic block is half-way through its job, will never be visible to other transactions.
For example, it becomes trivial to write some code that atomically removes an object from a transactional container and adds it to another one: just write something like
(defmethod move-obj-from-a-to-b ((a some-container) (b another-container))
(atomic
(let ((obj (take-obj-from-some-container a)))
(put-obj-into-another-container obj b))))
and it will work as long as both container are transactional and use the same transaction library (in this case, STMX).
A lot of facts that in other concurrent programming paradigms can be
great obstacles to such a solution become completely irrelevant
when using transactions:
it is irrelevant that the two containers may be unrelated classes,
that the respective authors may not have anticipated such need in the APIs,
that the internal details of the two implementations may be unknown to the
author of code that combines them atomically (the move-obj-from-a-to-b
in the example),
that other existing code in the program uses the same containers a
and b
but does not cooperate with move-obj-from-a-to-b
.
Style suggestion: in order to guarantee that all transactional memory accesses
are performed inside an atomic block, it may be tempting to wrap each function
or method body inside (atomic ...)
. While safe and correct, this approach
has a small performance penalty that performance-critical code may want to
avoid by minimizing the number of (atomic ...)
blocks: it is enough to have
a top-level atomic block that corresponds to the largest transaction that one
wants to execute, and omit inner atomic blocks in the same or other functions
called directly or indirectly from the top-level atomic block. In such case,
it is strongly recommended to insert in the documentation of the functions
accessing transactional memory without a direct atomic block a sentence like
"This function should be always invoked from inside an STMX atomic block."
RETRY
is a function. It is more tricky to understand, but really powerful.
As described in the summary, transactions will commit if they return normally,
while they will rollback if they signal an error or condition.
The (retry)
function call offers a third option: if invoked inside
a transaction, it tells STMX that the transaction cannot complete
immediately, for example because some necessary data is not currently
available, and instructs STMX to wait until the data has changed,
then re-execute the transaction from scratch.
How does (retry)
know which data it should monitor for changes?
Simple: it will monitor all transactional data (including slots of
transactional objects) that was read since the beginning of the
transaction and until (retry)
was invoked.
With RETRY
, reliable communication among threads is (hopefully)
extremely simple to implement: a thread can read one (or more)
transactional data, checking for values that some other thread
will write there, and just (retry)
if no appropriate values are
there yet.
ORELSE
is a macro to execute two or more Lisp forms as alternatives
in separate, nested transactions: if the first retries or detects an
inconsistent read, the second will be executed and so on, until one
transaction either commits (returns normally) or rollbacks (signals
an error or condition). It can only be used inside a transaction.
NONBLOCKING
is an utility macro based on ORELSE
to convert a blocking
transaction into another that returns NIL instead of waiting
(and otherwise returns T followed by the values or the original transaction)
(nonblocking (x) (y) (z))
basically expands to
(orelse (values t (progn (x) (y) (z))) nil)
with the difference that (nonblocking ...)
actually captures all the values
returned by the transaction, not just the first as in the example above.
WARNING: since transactions will be re-executed in case of conflicts with others and can also rollback or retry, all code inside an atomic block may be executed more times than expected, or may be executed when not expected.
Some transactional memory implementations, especially for statically-typed languages, forbid performing input/output during a transaction on the ground that I/O is not transactional: if a transaction sends an irreversible command to the outside world, there is no way to undo it in case the transaction rolls back, retries or conflicts.
STMX does not implement such restrictions, i.e. I/O and any other irreversible action can also be performed inside an atomic block. This means you are free to launch missiles during a transaction, and destroy the world when you shouldn't have. You have been warned.
Despite the risk, there are at least two reasons for such a design choice:
The typical solution for the above risk is: during a transaction, perform I/O only for debugging purposes, for example using a logging library as log4cl (or whatever is appropriate for your program), and queue any I/O operation in a transactional buffer. Then, invoke a separate function that first runs a transaction to atomically consume the buffer and only later, outside any transaction, performs the actual I/O operation.
An alternative solution is: during a transaction, instead of performing I/O
pass to AFTER-COMMIT
a function that will perform I/O when executed.
Note: AFTER-COMMIT
is described in Advanced usage below, read it carefully
because functions executed by AFTER-COMMIT
have several restrictions on what
they are allowed to do.
For those cases where the basic features are not sufficient, or where more control is desired during the execution of transactional code, some advanced features are available:
RUN-ATOMIC
is the function version of ATOMIC
: takes a single function
argument and executes it in a transaction. This means the following two code
snippets are equivalent:
(defvar a (make-instance 'foo))
(defvar b (make-instance 'foo))
(atomic
(set-foo a 1 "abc")
(set-foo b 2 "def"))
and
(defvar a (make-instance 'foo))
(defvar b (make-instance 'foo))
(defun init-foo-a-and-b ()
(set-foo a 1 "abc")
(set-foo b 2 "def"))
(run-atomic #'init-foo-a-and-b)
RUN-ORELSE
is the function version of ORELSE
: it accepts any number
of functions and executes them as alternatives in separate, nested
transactions:
if the first retries or is invalid, the second will be executed and so on,
until one function either commits (returns normally) or rollbacks
(signals an error or condition).
If X, Y and Z are no-argument functions, the following two lines are equivalent:
(orelse (x) (y) (z))
(run-orelse #'x #'y #'z)
BEFORE-COMMIT
is a macro that registers Lisp forms to be executed later,
just before the transaction tries to commit.
It can be useful to normalize or simplify some transactional data, or perform
any kind of bookkeeping activity.
Be aware that the transaction is not yet committed when the forms registered with BEFORE-COMMIT run. This means in particular:
There is no guarantee that the commit will succeed.
If the forms signal an error when executed, the error is propagated to the caller, forms registered later with BEFORE-COMMIT are not executed, and the transaction rolls back.
The forms can read and write normally to transactional memory, and in case of conflicts the whole transaction, including all forms registered with BEFORE-COMMIT, is re-executed from the beginning.
The forms cannot (retry) - attempts to do so will signal an error. Starting a nested transaction and retrying inside that is acceptable, as long as the (retry) does not propagate outside the forms themselves.
AFTER-COMMIT
is another macro that registers Lisp forms to be executed
later, but in this case they are executed immediately after the
transaction has been successfully committed.
It can be useful to notify some subsystem that for any reason cannot call
(retry)
to be informed of changes in transactional memory - for example
because it is some existing code that one does not wish to modify.
In this case, the transaction is already committed when the forms registered with AFTER-COMMIT run, and (since STMX 1.3.2) the forms are executed outside any transaction. There are some limitations on what the forms can do:
If the forms signal an error when executed, the error is propagated to the caller, forms registered later with AFTER-COMMIT are not executed, but the transaction remains committed.
The forms are not executed inside a transaction: while it is certainly
possible to explicitly run an (atomic)
block from them, doing so would
probably defeat the purpose of AFTER-COMMIT and it may also cause
a significant performance penalty.
CALL-BEFORE-COMMIT
is the function version of BEFORE-COMMIT
: it accepts a
single function and registers it to be executed before the transaction tries
to commit.
CALL-AFTER-COMMIT
is the function version of AFTER-COMMIT
: it accepts a
single function and registers it to be executed after the transaction
has been successfully committed.
TVAR
is the class implementing transactional memory behind the scenes.
It is used internally by slots of transactional classes, but can also be used
directly. Except if specified, all its functions and methods work both inside
and outside transactions (remember that using transactional memory outside
transactions is only intended for debugging purposes). Functions and
methods:
(tvar [initial-value])
Create a new TVAR, optionally bound to a value.($-slot var)
Get the value of VAR. Signals an error if VAR is not bound
to any value. Note: before STMX 1.9.0, this function was named ($ var)
.(setf ($-slot var) value)
Store VALUE into VAR.
Note: before STMX 1.9.0, this function was named (setf ($ var) value)
.(bound-$? var)
Return true if VAR is bound to some value.(unbind-$ var)
Unbind VAR from its value.(value-of var)
getter method, equivalent to ($-slot var)
(setf (value-of var) value)
setter method, equivalent to
(setf ($-slot var) value)
For programmers that want to squeeze the last CPU cycle out of STMX, there are also some more specialized functions:
($ var)
Get the value of VAR. Return +unbound-tvar+
if VAR is not
bound to any value.(setf ($ var) value)
Set the value of VAR. Identical to (setf ($-slot var) value)
and provided for simmetry with ($ var)
.STMX versions 1.9.0 or later can take advantage of hardware transactions on Intel CPUs that support Transactional Synchronization Extensions (TSX) As of February 2020, many recent consumer and server Intel CPUs support them, including at least:
7th generation Core i5: 7500 7500T 7600 7600K 7600T 7Y57
8th generation Core i5: 8500 8500T 8600 8600T 8600K
9th generation Core i5: 9500 9500E 9500F 9500T 9500TE 9600 9600K 9600KF 9600T
10th generation Core i7: -
7th generation Core i7: 7600U 7660U 7700 7700K 7700T 7820EQ 7820HK 7820HQ 7920HQ 7Y75
8th generation Core i7: 8086K 8650U 8665U 8665UE +8700 8700 8700B 8700K 8700T 8706G 8850H
9th generation Core i7: 9700 9700E 9700F 9700K 9700KF 9700T 9700TE 9850H 9850HE 9850HL
10th generation Core i7: -
8th generation Core i9: 8950HK
9th generation Core i9: 9880H 9900 9900K 9900KF 9900KS 9900T 9980HK
(This list is necessarily incomplete. To check whether a specific Intel CPU supports Transactional Synchronization Extensions (TSX) browse https://ark.intel.com/)
To actually use hardware transactions from STMX, there are two more requirements:
Also, hardware transactions only work in compiled code - SBCL sometimes interprets very short functions and simple code executed at REPL instead of compiling them, which may cause hardware transactions to fail.
There are several ways. The easiest are:
(HW-TRANSACTION-SUPPORTED?)
.
It internally calls the CPUID assembler instruction and returns T if hardware
transactions are supported, or NIL if they are not.(ATOMIC (HW-TRANSACTION-SUPPORTED-AND-RUNNING?))
in compiled code - hardware transactions typically do not work in interpreted code.
Thus actually execute something like
(DEFUN HW-TRANSACTION-TEST () (ATOMIC (HW-TRANSACTION-SUPPORTED-AND-RUNNING?))) (HW-TRANSACTION-TEST)
STMX automatically uses hardware transactions if they are supported.
There is no need for special commands, just execute the usual (ATOMIC ...)
or (RUN-ATOMIC ...)
forms.
Hardware transactions have several limitations, and STMX will seamlessly switch to (slower) software transactions in the following cases:
hardware limits are exceeded, for example read-set or write-set are larger than CPU L1 cache
executing a function or macro not supported by hardware transactions. The list is subject to change, it currently includes:
executing a CPU instruction not allowed inside hardware transaction. In particular, Intel TSX guarantees that CPU instructions
will always abort a hardware transaction, but many other CPU instructions typically have the same effect, including possibly:
For details and up-to-date information, see Intel Instruction Set Programming Reference, Chapter "Transactional Synchronization Extensions".
See the example and util folder, which contains several
examples and utilities built with STMX and should be relatively straightforward
to understand. The folder util contains the following classes with
related methods and functions, all in the STMX.UTIL package - for more details,
use (describe 'some-symbol)
at REPL:
TCELL
is the simplest transactional class. It is created with
(tcell [initial-value])
and it can be empty or hold a
single value.
Methods: FULL?
EMPTY?
EMPTY!
PEEK
TAKE
PUT
TRY-TAKE
TRY-PUT
.
When empty, taking a value will (retry) and wait until some other thread puts a value.
When full, putting a value will (retry) and wait until some other thread removes the current value.
Note: raw TVARs support exactly the same methods.
TCONS
is a transactional cons cell. It is created with
(tcons first-value second-value)
.
Functions: TFIRST
(SETF TFIRST)
TREST
(SETF TREST)
.
Seldom used directly.
TLIST
is a transactional list, composed of TCONS
cells. It is created with
(tlist [values ...])
.
Functions: TFIRST
(SETF TFIRST)
TREST
(SETF TREST)
TPUSH
TPOP
TSECOND
TTHIRD
TFOURTH
TNTH
TLAST
TLIST-LENGTH
TLIST*
and many others.
See util/tlist.lisp for details.
Normal lists are perfectly suitable for transactional use as long as they are not destructively modified, so TLIST is often unnecessary: it becomes needed only to support transactional destructive modifications.
TSTACK
is a transactional first-in-last-out buffer. It is created with
(tstack)
and it can be empty or hold unlimited values.
Methods: FULL?
EMPTY?
EMPTY!
PEEK
TAKE
PUT
TRY-TAKE
TRY-PUT
.
All methods append or remove values from the end, and putting a value
always succeeds, even when other values are already present: the new
value is simple appended at the end.
For the rest, the methods behave as described for the TCELL
class.
TFIFO
is a transactional first-in-first-out buffer. It is created with
(make-instance 'tfifo)
and it can be empty or hold unlimited values.
Methods: FULL?
EMPTY?
EMPTY!
PEEK
TAKE
PUT
TRY-TAKE
TRY-PUT
.
PUT
and TRY-PUT
append values at the end, PEEK
TAKE
and TRY-TAKE
get or remove them from the beginning, shifting the remaining values.
For the rest, the methods behave as described for the TCELL
and TSTACK
classes.
TCHANNEL
is a transactional multicast channel. It is created with
(make-instance 'tchannel)
, can contain unlimited values and it is write-only.
To read from it, create a TPORT
as described below.
Methods: FULL?
EMPTY?
PUT
TRY-PUT
.
PUT
and TRY-PUT
append values at the end, making them available to
connected ports.
FULL?
always returns nil, since a channel can contain unlimited values.
EMPTY?
always returns t, since it is not possible to get values from a
channel.
It is possible to write into the same channel from multiple threads: added elements will be interleaved and made available to all connected ports.
TPORT
is a transactional reader for TCHANNEL
. It is created with
(make-instance 'tport :channel some-channel)
.
Ports do not support putting values, they are used to retrieve values from the
channel they are connected to.
Methods: FULL?
EMPTY?
EMPTY!
PEEK
TAKE
TRY-TAKE
.
PEEK
TAKE
and TRY-TAKE
get or consume values previously added to the
connected channel. All ports connected to the same channel receive all the
values in the same order, and they consume values independently: taking a
value from a port does not consume it from the other ports.
FULL?
always returns t, since it is not possible to put values in a port.
EMPTY?
returns t if some values are available to read or consume.
EMPTY!
consumes all values currently available.
It is also possible to use the same port from multiple threads: elements consumed by one thread will not be available to other threads using the same port.
THASH-TABLE
is a transactional hash table.
It is created with
(make-instance 'thash-table [:test 'some-test-function] [:hash 'some-hash-function])
.
One difference from standard Common Lisp HASH-TABLE:
:hash 'some-hash-function
For the usual test functions, i.e. 'eq
'eql
'equal
and 'equalp
the hash function
can be omitted and a safe default (usually 'sxhash
) will be used.
For other test functions, the hash function becomes mandatory.Methods: GHASH-TABLE-COUNT
GHASH-TABLE-COUNT>
GHASH-TABLE-COUNT<=
GHASH-TABLE-EMPTY?
CLEAR-GHASH
GET-GHASH
(SETF GET-GHASH)
SET-GHASH
REM-GHASH
MAP-GHASH
DO-GHASH
COPY-GHASH
GHASH-KEYS
GHASH-VALUES
GHASH-PAIRS
GHASH-TEST
GHASH-HASH
.
Warning: retrieving the number of elements in a transactional container is potentially expensive:
to maintain consistency, it inhibits concurrent insertion and removal from other threads.
For this reason, use GHASH-TABLE-COUNT
sparingly.
THASH-TABLE constructor arguments test
and hash
changed in STMX 2.0.0.
They now must be function names (i.e. symbols), previously they were actual functions.
TMAP
is a transactional sorted map, backed by a red-black tree.
It is created with (make-instance 'tmap :pred compare-function)
where COMPARE-FUNCTION must be the name of a function accepting two arguments,
KEY1 and KEY2, and returning t if KEY1 is smaller that KEY2.
For numeric keys, typical COMPARE-FUNCTIONs are '<
or '>
and the faster
'fixnum<
or 'fixnum>
.
For string keys, typical COMPARE-FUNCTIONs are 'string<
and 'string>
.
Note: COMPARE-FUNCTIONs changed in STMX 2.0.0. They now must be function names (i.e. symbols), previously they were actual functions.
Methods: GMAP-PRED
GMAP-COUNT
GMAP-EMPTY?
CLEAR-GMAP
GET-GMAP
(SETF GET-GMAP)
SET-GMAP
REM-GMAP
MIN-GMAP
MAX-GMAP
MAP-GMAP
DO-GMAP
GMAP-KEYS
GMAP-VALUES
GMAP-PAIRS
.
Warning: retrieving the number of elements in a transactional container is potentially expensive:
to maintain consistency, it inhibits concurrent insertion and removal from other threads.
For this reason, use GMAP-COUNT
sparingly.
GHASH-TABLE
is the non-transactional version of THASH-TABLE
. Not so
interesting by itself, as Common Lisp offers a standard (and usually faster)
HASH-TABLE implementation. It supports exactly the same methods as THASH-TABLE
.
RBMAP
is the non-transactional version of TMAP
. Not so interesting by
itself, as many other red-black trees implementations exist already on the
net. It supports exactly the same methods as TMAP
.
STMX automatically discovers and takes advantage of many optional, non-standard features of the underlying Common Lisp compiler. It also performs graceful degradation, i.e. if the fastest version of a feature is not available it automatically switches to a slower, available alternative.
Depending on the available features, STMX performance can vary up to a factor 100 or more (!).
To reach its peak performance, several requirements need to be satisfied by the hardware and by the Lisp compiler being used. They are listed here in order of importance:
Hardware requirements:
Lisp compiler requirements:
Among the non-commercial Lisp compilers, SBCL is the only one known to STMX author that satisfies all the compiler requirements, and (guess why) the only one where STMX author has implemented support for hardware transactions.
Actually, all the other tested free Lisp compilers (ABCL, CCL, CMUCL, ECL) are at least somewhat lacking in the area "fast, highly optimized code", and none of them offers atomic compare-and-swap or memory barrier operations at all. One - CMUCL - produces relatively fast code, but does not support native threads. STMX is not tested on any commercial Lisp compiler, so performance on them is simply unknown.
For these reasons, STMX will reach the highest known performance on SBCL by a large margin - possibly by a factor from 10 to 100 or more with respect to other tested systems.
For more performance considerations and a lot of raw numbers produced by running micro-benchmarks, see the included files doc/benchmark.md, doc/benchmark-abcl.md, doc/benchmark-ccl64.md and doc/benchmark-cmucl.md.
The short version is: as of March 2015, on a fast consumer PC (Core i7 4770 @ 3.5GHz or better) with 64-bit SBCL 1.1.9 or better, STMX can execute more than 35 millions hardware transactions per second per CPU core, and more than 7 millions software transactions per second per CPU core. The second platform in terms of performance is CCL (x86_64), that reaches 1.1 millions software transactions per second per CPU core using two threads, but STMX performance quickly decreases with more threads (reason still needs to be investigated).
A small example with very short transactions is the dining philosophers, with 5 reads and 5 writes to transactional memory per atomic block, where each CPU core runs approximately 4.5 millions software transactions per second - hyperthreading has very limited effects.
Obviously, performance in other usage scenarios will depend on the complexity of the code inside transactions, on the availability of hardware transactions, on the number of reads and writes to transactional memory, and the rate of conflicts and rollbacks.
These result are not absolute performance considerations of the tested Lisp systems. They are simply the outcome of running micro-benchmarks of a particular library optimized for SBCL (see the hardware transactions, atomic compare-and-swap and memory barriers considerations) on several other Lisp systems. Do not try to construct these results as STMX author's opinions on the mentioned Lisp systems.
For a less artificial and hopefully more realistic benchmark, the author has ported Lee-TM, a non-trivial benchmark suite for transactional memory developed in 2007 by the University of Manchester (UK). The result is Lee-STMX - as of July 2013, its status is BETA.
As long as the traffic is low enough, GitHub Issues can be used to report test suite failures, bugs, suggestions, general discussion etc.
If the traffic becomes high, more appropriate discussion channels will be set-up.
The author will also try to answer support requests, but gives no guarantees.
As of July 2013, STMX is being written by Massimiliano Ghilardi and is considered by the author to be stable.
STMX is a full rewrite of CL-STM, which has been developed by Hoan Ton-That for the Google Summer of Code 2006.
STMX is a spare-time project. Donations can help the project by recognizing its usefulness and covering expenses.
You can donate with PayPal or credit card.
STMX is released under the terms of the Lisp Lesser General Public License, known as the LLGPL.
Next: Modules, Previous: Introduction, Up: Top [Contents][Index]
The main system appears first, followed by any subsystem dependency.
• The stmx system |
Massimiliano Ghilardi
LLGPL
Composable Transactional Memory
2.0.5
stmx.asd (file)
Modules are listed depth-first from the system components tree.
• The stmx/asm module | ||
• The stmx/lang module | ||
• The stmx/main module | ||
• The stmx/util module |
Next: The stmx/lang module, Previous: Modules, Up: Modules [Contents][Index]
stmx (system)
asm/
Next: The stmx/main module, Previous: The stmx/asm module, Up: Modules [Contents][Index]
asm (module)
stmx (system)
lang/
Next: The stmx/util module, Previous: The stmx/lang module, Up: Modules [Contents][Index]
lang (module)
stmx (system)
main/
Previous: The stmx/main module, Up: Modules [Contents][Index]
stmx (system)
util/
Files are sorted by type and then listed depth-first from the systems components trees.
• Lisp files | ||
• Static files |
Next: Static files, Previous: Files, Up: Files [Contents][Index]
Next: The stmx/asm/package․lisp file, Previous: Lisp files, Up: Lisp files [Contents][Index]
stmx.asd
stmx (system)
Next: The stmx/asm/compiler․lisp file, Previous: The stmx․asd file, Up: Lisp files [Contents][Index]
Next: The stmx/asm/x86-32‚64-known․lisp file, Previous: The stmx/asm/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
asm (module)
asm/compiler.lisp
Next: The stmx/asm/x86-32‚64-insts․lisp file, Previous: The stmx/asm/compiler․lisp file, Up: Lisp files [Contents][Index]
compiler.lisp (file)
asm (module)
asm/x86-32,64-known.lisp
Next: The stmx/asm/x86-32‚64-vops․lisp file, Previous: The stmx/asm/x86-32‚64-known․lisp file, Up: Lisp files [Contents][Index]
x86-32,64-known.lisp (file)
asm (module)
asm/x86-32,64-insts.lisp
Next: The stmx/asm/cpuid․lisp file, Previous: The stmx/asm/x86-32‚64-insts․lisp file, Up: Lisp files [Contents][Index]
x86-32,64-insts.lisp (file)
asm (module)
asm/x86-32,64-vops.lisp
+transaction-started+ (constant)
Next: The stmx/asm/transaction․lisp file, Previous: The stmx/asm/x86-32‚64-vops․lisp file, Up: Lisp files [Contents][Index]
x86-32,64-vops.lisp (file)
asm (module)
asm/cpuid.lisp
Next: The stmx/lang/package․lisp file, Previous: The stmx/asm/cpuid․lisp file, Up: Lisp files [Contents][Index]
x86-32,64-vops.lisp (file)
asm (module)
asm/transaction.lisp
transaction-abort-macro (macro)
Next: The stmx/lang/macro․lisp file, Previous: The stmx/asm/transaction․lisp file, Up: Lisp files [Contents][Index]
Next: The stmx/lang/features․lisp file, Previous: The stmx/lang/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
lang (module)
lang/macro.lisp
Next: The stmx/lang/features-reader․lisp file, Previous: The stmx/lang/macro․lisp file, Up: Lisp files [Contents][Index]
macro.lisp (file)
lang (module)
lang/features.lisp
Next: The stmx/lang/thread․lisp file, Previous: The stmx/lang/features․lisp file, Up: Lisp files [Contents][Index]
features.lisp (file)
lang (module)
lang/features-reader.lisp
enable-#?-syntax (macro)
Next: The stmx/lang/features-detect․lisp file, Previous: The stmx/lang/features-reader․lisp file, Up: Lisp files [Contents][Index]
features-reader.lisp (file)
lang (module)
lang/thread.lisp
Next: The stmx/lang/hw-transactions․lisp file, Previous: The stmx/lang/thread․lisp file, Up: Lisp files [Contents][Index]
thread.lisp (file)
lang (module)
lang/features-detect.lisp
Next: The stmx/lang/atomic-ops․lisp file, Previous: The stmx/lang/features-detect․lisp file, Up: Lisp files [Contents][Index]
features-detect.lisp (file)
lang (module)
lang/hw-transactions.lisp
Next: The stmx/lang/mutex․lisp file, Previous: The stmx/lang/hw-transactions․lisp file, Up: Lisp files [Contents][Index]
features-detect.lisp (file)
lang (module)
lang/atomic-ops.lisp
Next: The stmx/lang/atomic-counter․lisp file, Previous: The stmx/lang/atomic-ops․lisp file, Up: Lisp files [Contents][Index]
atomic-ops.lisp (file)
lang (module)
lang/mutex.lisp
Next: The stmx/lang/cons․lisp file, Previous: The stmx/lang/mutex․lisp file, Up: Lisp files [Contents][Index]
lang (module)
lang/atomic-counter.lisp
Next: The stmx/lang/fast-vector․lisp file, Previous: The stmx/lang/atomic-counter․lisp file, Up: Lisp files [Contents][Index]
thread.lisp (file)
lang (module)
lang/cons.lisp
*cons-pool* (special variable)
Next: The stmx/lang/hash-table․lisp file, Previous: The stmx/lang/cons․lisp file, Up: Lisp files [Contents][Index]
macro.lisp (file)
lang (module)
lang/fast-vector.lisp
Next: The stmx/lang/print․lisp file, Previous: The stmx/lang/fast-vector․lisp file, Up: Lisp files [Contents][Index]
cons.lisp (file)
lang (module)
lang/hash-table.lisp
incf-hash-counter (macro)
Next: The stmx/lang/class-precedence-list․lisp file, Previous: The stmx/lang/hash-table․lisp file, Up: Lisp files [Contents][Index]
macro.lisp (file)
lang (module)
lang/print.lisp
Next: The stmx/main/package․lisp file, Previous: The stmx/lang/print․lisp file, Up: Lisp files [Contents][Index]
macro.lisp (file)
lang (module)
lang/class-precedence-list.lisp
clos-compute-class-precedence-list (function)
Next: The stmx/main/version․lisp file, Previous: The stmx/lang/class-precedence-list․lisp file, Up: Lisp files [Contents][Index]
Next: The stmx/main/global-clock․lisp file, Previous: The stmx/main/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
main (module)
main/version.lisp
*stmx-version* (special variable)
Next: The stmx/main/tvar-fwd․lisp file, Previous: The stmx/main/version․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
main (module)
main/global-clock.lisp
Next: The stmx/main/classes․lisp file, Previous: The stmx/main/global-clock․lisp file, Up: Lisp files [Contents][Index]
global-clock.lisp (file)
main (module)
main/tvar-fwd.lisp
Next: The stmx/main/txhash․lisp file, Previous: The stmx/main/tvar-fwd․lisp file, Up: Lisp files [Contents][Index]
tvar-fwd.lisp (file)
main (module)
main/classes.lisp
Next: The stmx/main/tlog․lisp file, Previous: The stmx/main/classes․lisp file, Up: Lisp files [Contents][Index]
classes.lisp (file)
main (module)
main/txhash.lisp
Next: The stmx/main/tvar․lisp file, Previous: The stmx/main/txhash․lisp file, Up: Lisp files [Contents][Index]
txhash.lisp (file)
main (module)
main/tlog.lisp
Next: The stmx/main/optimize-for․lisp file, Previous: The stmx/main/tlog․lisp file, Up: Lisp files [Contents][Index]
tlog.lisp (file)
main (module)
main/tvar.lisp
Next: The stmx/main/tvar-slot․lisp file, Previous: The stmx/main/tvar․lisp file, Up: Lisp files [Contents][Index]
tvar.lisp (file)
main (module)
main/optimize-for.lisp
Next: The stmx/main/tstruct․lisp file, Previous: The stmx/main/optimize-for․lisp file, Up: Lisp files [Contents][Index]
optimize-for.lisp (file)
main (module)
main/tvar-slot.lisp
Next: The stmx/main/tclass․lisp file, Previous: The stmx/main/tvar-slot․lisp file, Up: Lisp files [Contents][Index]
tvar-slot.lisp (file)
main (module)
main/tstruct.lisp
Next: The stmx/main/tslot․lisp file, Previous: The stmx/main/tstruct․lisp file, Up: Lisp files [Contents][Index]
main (module)
main/tclass.lisp
Next: The stmx/main/hw-atomic․lisp file, Previous: The stmx/main/tclass․lisp file, Up: Lisp files [Contents][Index]
tclass.lisp (file)
main (module)
main/tslot.lisp
Next: The stmx/main/commit․lisp file, Previous: The stmx/main/tslot․lisp file, Up: Lisp files [Contents][Index]
classes.lisp (file)
main (module)
main/hw-atomic.lisp
hw-atomic2 (macro)
Next: The stmx/main/sw-atomic․lisp file, Previous: The stmx/main/hw-atomic․lisp file, Up: Lisp files [Contents][Index]
main (module)
main/commit.lisp
Next: The stmx/main/atomic․lisp file, Previous: The stmx/main/commit․lisp file, Up: Lisp files [Contents][Index]
commit.lisp (file)
main (module)
main/sw-atomic.lisp
transaction (macro)
Next: The stmx/main/orelse․lisp file, Previous: The stmx/main/sw-atomic․lisp file, Up: Lisp files [Contents][Index]
main (module)
main/atomic.lisp
hw-transaction-test (function)
Next: The stmx/util/package․lisp file, Previous: The stmx/main/atomic․lisp file, Up: Lisp files [Contents][Index]
atomic.lisp (file)
main (module)
main/orelse.lisp
Next: The stmx/util/misc․lisp file, Previous: The stmx/main/orelse․lisp file, Up: Lisp files [Contents][Index]
Next: The stmx/util/print․lisp file, Previous: The stmx/util/package․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
util (module)
util/misc.lisp
Next: The stmx/util/container․lisp file, Previous: The stmx/util/misc․lisp file, Up: Lisp files [Contents][Index]
package.lisp (file)
util (module)
util/print.lisp
Next: The stmx/util/tcons․lisp file, Previous: The stmx/util/print․lisp file, Up: Lisp files [Contents][Index]
Next: The stmx/util/tcons-list․lisp file, Previous: The stmx/util/container․lisp file, Up: Lisp files [Contents][Index]
misc.lisp (file)
util (module)
util/tcons.lisp
Next: The stmx/util/tcons-alist․lisp file, Previous: The stmx/util/tcons․lisp file, Up: Lisp files [Contents][Index]
tcons.lisp (file)
util (module)
util/tcons-list.lisp
Next: The stmx/util/tcons-set․lisp file, Previous: The stmx/util/tcons-list․lisp file, Up: Lisp files [Contents][Index]
tcons.lisp (file)
util (module)
util/tcons-alist.lisp
Next: The stmx/util/tcons-tree․lisp file, Previous: The stmx/util/tcons-alist․lisp file, Up: Lisp files [Contents][Index]
tcons.lisp (file)
util (module)
util/tcons-set.lisp
Next: The stmx/util/tcons-higher․lisp file, Previous: The stmx/util/tcons-set․lisp file, Up: Lisp files [Contents][Index]
tcons.lisp (file)
util (module)
util/tcons-tree.lisp
copy-ttree (function)
Next: The stmx/util/tvar․lisp file, Previous: The stmx/util/tcons-tree․lisp file, Up: Lisp files [Contents][Index]
tcons-alist.lisp (file)
util (module)
util/tcons-higher.lisp
Next: The stmx/util/tcell․lisp file, Previous: The stmx/util/tcons-higher․lisp file, Up: Lisp files [Contents][Index]
container.lisp (file)
util (module)
util/tvar.lisp
Next: The stmx/util/tstack․lisp file, Previous: The stmx/util/tvar․lisp file, Up: Lisp files [Contents][Index]
container.lisp (file)
util (module)
util/tcell.lisp
+empty-tcell+ (constant)
Next: The stmx/util/tfifo․lisp file, Previous: The stmx/util/tcell․lisp file, Up: Lisp files [Contents][Index]
container.lisp (file)
util (module)
util/tstack.lisp
Next: The stmx/util/tchannel․lisp file, Previous: The stmx/util/tstack․lisp file, Up: Lisp files [Contents][Index]
util (module)
util/tfifo.lisp
Next: The stmx/util/bheap․lisp file, Previous: The stmx/util/tfifo․lisp file, Up: Lisp files [Contents][Index]
util (module)
util/tchannel.lisp
Next: The stmx/util/gmap․lisp file, Previous: The stmx/util/tchannel․lisp file, Up: Lisp files [Contents][Index]
container.lisp (file)
util (module)
util/bheap.lisp
Next: The stmx/util/rbmap․lisp file, Previous: The stmx/util/bheap․lisp file, Up: Lisp files [Contents][Index]
util (module)
util/gmap.lisp
Next: The stmx/util/tmap․lisp file, Previous: The stmx/util/gmap․lisp file, Up: Lisp files [Contents][Index]
gmap.lisp (file)
util (module)
util/rbmap.lisp
rbmap (class)
Next: The stmx/util/simple-tvector․lisp file, Previous: The stmx/util/rbmap․lisp file, Up: Lisp files [Contents][Index]
rbmap.lisp (file)
util (module)
util/tmap.lisp
tmap (class)
Next: The stmx/util/ghash-table․lisp file, Previous: The stmx/util/tmap․lisp file, Up: Lisp files [Contents][Index]
print.lisp (file)
util (module)
util/simple-tvector.lisp
Next: The stmx/util/thash-table․lisp file, Previous: The stmx/util/simple-tvector․lisp file, Up: Lisp files [Contents][Index]
print.lisp (file)
util (module)
util/ghash-table.lisp
Previous: The stmx/util/ghash-table․lisp file, Up: Lisp files [Contents][Index]
util (module)
util/thash-table.lisp
thash-table (class)
Previous: Lisp files, Up: Files [Contents][Index]
• The stmx/stmx.asd file |
Previous: Static files, Up: Static files [Contents][Index]
stmx (system)
stmx.asd
Next: Definitions, Previous: Files, Up: Top [Contents][Index]
Packages are listed by definition order.
• The stmx.asm package | ||
• The stmx.lang package | ||
• The stmx package | ||
• The stmx.util package |
Next: The stmx․lang package, Previous: Packages, Up: Packages [Contents][Index]
package.lisp (file)
common-lisp
Next: The stmx package, Previous: The stmx․asm package, Up: Packages [Contents][Index]
package.lisp (file)
Next: The stmx․util package, Previous: The stmx․lang package, Up: Packages [Contents][Index]
package.lisp (file)
Previous: The stmx package, Up: Packages [Contents][Index]
package.lisp (file)
Definitions are sorted by export status, category, package, and then by lexicographic order.
• Exported definitions | ||
• Internal definitions |
Next: Internal definitions, Previous: Definitions, Up: Definitions [Contents][Index]
Next: Exported special variables, Previous: Exported definitions, Up: Exported definitions [Contents][Index]
hw-transactions.lisp (file)
hw-transactions.lisp (file)
Designator for the SBCL internal package where we look for VOP-related symbols
compiler.lisp (file)
Value returned by (transaction-begin) if the transaction is successfully started. It is an implementation-dependent fixnum, different from all possible transactions abort error codes.
x86-32,64-vops.lisp (file)
Value returned by (transaction-begin) if the transaction was manually aborted
by calling (transaction-abort).
It is an implementation-dependent fixnum, different from +transaction-started+
and from all error codes indicating a spontaneous abort.
transaction.lisp (file)
Unbound TVARs actually contain this value. Use with care.
tvar-fwd.lisp (file)
Next: Exported macros, Previous: Exported constants, Up: Exported definitions [Contents][Index]
thread.lisp (file)
version.lisp (file)
Next: Exported compiler macros, Previous: Exported special variables, Up: Exported definitions [Contents][Index]
Register BODY to be invoked after the current transaction commits.
If BODY signals an error when executed, the error is propagated
to the caller and further code registered with AFTER-COMMIT is not executed,
but the transaction remains committed.
WARNING: Code registered with after-commit has a number or restrictions:
1) if BODY signal an error when executed, the error is propagated to the caller,
forms registered later with AFTER-COMMIT are not executed,
but the transaction remains committed.
2) BODY is *not* executed inside a transaction: while it is certainly possible to explicitly run an (atomic) block from it, doing so would probably defeat the purpose of AFTER-COMMIT and it may also cause a significant performance penalty.
commit.lisp (file)
macro.lisp (file)
Analyze the slots of a non-transactional struct, so that transactional structs can subclass it.
Use this macro to wrap a DEFSTRUCT as follows:
(ANALYZE-STRUCT (DEFSTRUCT {struct-name | (struct-name [options])} slots-description*)
Note: this macro only analyzes the structure definition, does *not* define the structure. See NON-TRANSACTIONAL-STRUCT for that.
tstruct.lisp (file)
Main entry point for STMX.
Run BODY in a memory transaction. All changes to transactional memory
will be visible to other threads only after BODY returns normally (commits).
If BODY signals an error, its effects on transactional memory are rolled back
and the error is propagated normally.
Also, no work-in-progress transactional memory will ever be visible to other
threads.
A memory transaction can also retry: in such case ATOMIC will abort it,
wait until some of the value read by the transaction have changed,
then re-run the transaction from the beginning.
Since STMX transactions do not lock memory, it is possible for different
transactions to try to update the same memory (almost) simultaneously.
In such case, the conflict is detected when they try to commit or rollback,
and only one conflicting transaction is allowed to commit:
all others are immediately re-run again from the beginning.
For this reason, a transaction SHOULD NOT perform any irreversible
operation such as INPUT/OUTPUT: the result would be that I/O is executed
multiple times, or executed even when it shouldn’t have!
Irreversible operations SHOULD be performed OUTSIDE transactions,
for example by queueing them into transactional memory that another thread
will consume and then, OUTSIDE transactions, actually perform them.
For how to create transactional memory, see TRANSACTIONAL or TVAR.
For another way to run transactions, see also TRANSACTION.
For advanced features inside transactions, see RETRY, ORELSE, NONBLOCKING,
BEFORE-COMMIT and AFTER-COMMIT.
For pre-defined transactional classes, see the package STMX.UTIL
atomic.lisp (file)
atomic-ops.lisp (file)
Atomically decrement PLACE by DELTA. Return _previous_ value of PLACE.
atomic-ops.lisp (file)
Atomically increment PLACE by DELTA. Return _previous_ value of PLACE.
atomic-ops.lisp (file)
Like POP, but atomic. PLACE may be read multiple times before the operation completes – the write does not occur until such time that no other thread modified PLACE between the read and the write.
Works only on places supported by ATOMIC-COMPARE-AND-SWAP.
atomic-ops.lisp (file)
macro.lisp (file)
Register BODY to be invoked immediately before the current transaction commits.
If BODY signals an error when executed, the error is propagated to the caller,
further code registered with BEFORE-COMMIT are not executed,
and the transaction rollbacks.
BODY can read and write normally to transactional memory, and in case of conflicts
the whole transaction (not only the code registered with before-commit)
is re-executed from the beginning.
WARNING: BODY cannot (retry) - attempts to do so will signal an error.
Starting a nested transaction and retrying inside that is acceptable,
as long as the (retry) does not propagate outside BODY.
commit.lisp (file)
Same as DEFCONSTANT, but evaluate VALUE only once:
re-executing again the same (DEFINE-CONSTANT-ONCE name ...) has no effects.
features-detect.lisp (file)
Define NAME as a global variable, declaring that it will have the same value
in all threads, i.e. it will not be special nor dynamically bound.
This is implemented either with a compiler-specific macro (for example SB-EXT:DEFGLOBAL on SBCL), or as DEFVAR if no better implementation is available.
features-detect.lisp (file)
print.lisp (file)
fast-vector.lisp (file)
Execute BODY on each KEY/VALUE contained in HASH. Return NIL.
ghash-table.lisp (file)
Execute BODY in order on each key/value pair contained in M:
first execute it on the smallest key, then the second smallest...
finally execute BODY on the largest key. Return nil.
If :FROM-END is true, BODY will be executed first on the largest key,
then on the second largest key... and finally on the smallest key.
Adding or removing keys from M during this call (even from other threads) has undefined consequences. Not even the current key can be removed.
Execute body on each key/value pair contained in hash table
hash-table.lisp (file)
Execute BODY on each ELEMENT contained in simple-tvector TVEC.
Creates an implicit block named NIL, so (return ...) can be used to exit early from the loop with an explicit return value.
simple-tvector.lisp (file)
Execute BODY for each atom inside TREE
macro.lisp (file)
features-reader.lisp (file)
macro.lisp (file)
Possibly slightly faster variant of ATOMIC.
On systems supporting hardware transactions (as of July 2013, very few systems
support them), FAST-ATOMIC and ATOMIC are identical.
On other systems, multiple nested FAST-ATOMIC forms may be slightly faster than
multiple nested ATOMIC blocks, at the price of compiling BODY more than once.
atomic.lisp (file)
If FAST-VECTOR is not empty, remove its last element and return it and t as multiple values. Otherwise evaluate DEFAULT and return (values DEFAULT NIL).
fast-vector.lisp (file)
Return current value of atomic PLACE.
atomic-counter.lisp (file)
Return DELTA plus current value of atomic PLACE.
atomic-counter.lisp (file)
Run BODY in a hardware memory transaction. All changes to transactional memory
will be visible to other threads only after BODY returns normally (commits).
If BODY signals an error, its effects on transactional memory are rolled back
and the error is propagated normally.
Also, no work-in-progress transactional memory will ever be visible to other
threads.
If hardware memory transaction aborts for a conflict, rerun it.
If it fails for some other reason, execute FALLBACK.
hw-atomic.lisp (file)
Abort a hardware memory transaction currently in progress. Causes a rollback of *all* transaction effects, execution resumes at (hw-transaction-begin) by returning abort reason.
hw-transactions.lisp (file)
Start a hardware memory transaction. Return +hw-transaction-started+ if transaction started successfully, otherwise return abort reason.
hw-transactions.lisp (file)
Try to commit a hardware memory transaction currently in progress. If commit is successful, return normally. Otherwise execution resumes at (hw-transaction-begin) by returning abort reason.
hw-transactions.lisp (file)
If ERR-CODE is the result returned by (HW-TRANSACTION-BEGIN) of an *aborted* transaction,
return T if re-running the same transaction has a possibility to succeed,
i.e. if the abort reason was temporary (as for example a conflict with another thread).
Return NIL if re-running the same transaction has no possibility to succeed.
hw-transactions.lisp (file)
Return T if a hardware memory transaction is in progress.
hw-transactions.lisp (file)
hw-transactions.lisp (file)
Return T if the CPU supports hardware memory transactions, and there is a compiler extension to use them, otherwise return NIL.
hw-transactions.lisp (file)
macro.lisp (file)
Increase atomic PLACE by DELTA and return its new value.
atomic-counter.lisp (file)
macro.lisp (file)
macro.lisp (file)
macro.lisp (file)
macro.lisp (file)
Memory read barrier. Execute BEFORE, then put the barrier.
atomic-ops.lisp (file)
Memory write barrier. Execute BEFORE, then put the barrier.
atomic-ops.lisp (file)
macro.lisp (file)
Use this macro to wrap a normal DEFSTRUCT as follows:
(NON-TRANSACTIONAL-STRUCT (DEFSTRUCT {struct-name | (struct-name [options])} slots-description*)
The effect is the same as DEFSTRUCT, plus its slots will be analyzed
so that transactional structs can subclass it
tstruct.lisp (file)
Execute all the forms in BODY in a single nested transaction and:
a) in case of transaction conflicts, re-execute BODY
b) if BODY returns normally, commit and return multiple values:
T followed by the values returned by BODY.
b) if BODY signals an error, rollback and raise such error.
d) if BODY attempts to retry, immediately return NIL without waiting/sleeping.
Can only be used inside an ATOMIC block.
orelse.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
Execute each form in BODY from left to right in separate, nested transactions
until one succeeds (i.e. commits) or signals an error.
If a form calls (RETRY) or has a temporary failure (temporary failures as
for example conflicts are normally invisible because (ATOMIC ...) re-executes
them automatically) advance to the next form and run it instead of retrying
the current one.
Returns the value of the transaction that succeeded,
or signals the error raised by the transaction that failed.
Can only be used inside an ATOMIC block.
orelse.lisp (file)
Equivalent to POP, but also assumes the CONS at PLACE is no longer
used and can be added to free CONS pool.
Removes and returns the first element in PLACE.
Equivalent to PUSH, but uses CONS pool to speedup allocation.
Inserts VALUE as the first element in PLACE.
Return the modified PLACE.
thread.lisp (file)
Set and return value of atomic PLACE.
atomic-counter.lisp (file)
Equivalent to POP, but for TCONS transactional cells. Removes and returns the first element in PLACE.
tcons.lisp (file)
Equivalent to PUSH, but for TCONS transactional cells. Inserts VALUE as the first element in PLACE. Return the modified PLACE.
tcons.lisp (file)
Deprecated. Use ATOMIC instead.
Define FUNC-NAME as a new atomic function or method.
Use this macro to wrap a normal DEFUN or DEFMETHOD as follows:
(TRANSACTION (DEFUN function-name (arguments) body))
or
(TRANSACTION (DEFMETHOD function-name (arguments) body))
The effect is the same as DEFUN - or DEFMETHOD - plus:
- the BODY is wrapped inside (atomic ...)
sw-atomic.lisp (file)
Define CLASS-OR-STRUCT-NAME as a new transactional class or struct.
Use this macro to wrap a normal DEFCLASS as follows: (TRANSACTIONAL (DEFCLASS class-name (superclasses) (slots) [options]))
Or to wrap a normal DEFCLASS as follows:
(TRANSACTIONAL (DEFSTRUCT (class-name (options)) slots))
tclass.lisp (file)
Define CLASS-NAME as a new transactional class.
Use this macro to wrap a normal DEFCLASS as follows:
(TRANSACTIONAL (DEFCLASS class-name (superclasses) (slots) [options]))
The effect is the same as DEFCLASS, plus:
- by default, slots are transactional memory (implemented by TVARs)
- it inherits also from TRANSACTIONAL-OBJECT
- the metaclass is TRANSACTIONAL-CLASS
- it internally defines a method INITIALIZE-INSTANCE :before, do NOT redefine it
tclass.lisp (file)
Define NAME as a new transactional struct.
Use this macro to wrap a normal DEFSTRUCT as follows:
(TRANSACTIONAL-STRUCT (DEFSTRUCT {struct-name | (struct-name [options])} slots-description*)
The effect is the same as DEFSTRUCT, plus:
- by default, direct slots are transactional memory (implemented by TVARs)
tstruct.lisp (file)
macro.lisp (file)
macro.lisp (file)
macro.lisp (file)
Faster replacement for BORDEAUX-THREADS:WITH-LOCK-HELD.
mutex.lisp (file)
Next: Exported functions, Previous: Exported macros, Up: Exported definitions [Contents][Index]
tcons-list.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
Next: Exported generic functions, Previous: Exported compiler macros, Up: Exported definitions [Contents][Index]
Get the value from the transactional variable VAR and return it.
Return +unbound-tvar+ if VAR is not bound to a value.
Works both inside and outside transactions.
During transactions, it uses transaction log to record the read
and to check for any value stored in the log.
Get the value from the transactional variable VAR and return it.
Signal an error if VAR is not bound to a value.
Works both inside and outside transactions.
During transactions, it uses transaction log to record the read
and to check for any value stored in the log.
tvar-slot.lisp (file)
(setf $-slot) (setf expander)
tvar-slot.lisp (file)
$-slot (function)
N-ary version of SET-GMAP and (SETF (GET-GMAP ...) ...):
Given a list of alternating keys and values,
add or replace each of them into M. Return M.
Return T if all features from LIST are present in *FEATURE-LIST* and have non-NIL value.
features.lisp (file)
Return (list F VALUE) if F is present in *FEATURE-LIST*
features.lisp (file)
Return true if transactional variable VAR is bound to a value.
Works both outside and inside transactions.
During transactions, it uses transaction log to record the read and to check for any value stored in the log.
tvar-slot.lisp (file)
Register FUNC function to be invoked after the current transaction commits.
IMPORTANT: See AFTER-COMMIT for what FUNC must not do.
commit.lisp (file)
Register FUNC function to be invoked immediately before the current transaction commits.
IMPORTANT: See BEFORE-COMMIT for what FUNC must not do.
commit.lisp (file)
Remove all keys and values from HASH. Return HASH.
ghash-table.lisp (file)
Remove all keys and values from M. Return M.
Same as (clrhash hash).
hash-table.lisp (file)
class-precedence-list.lisp (file)
compiler.lisp (file)
compiler.lisp (file)
compiler.lisp (file)
Print the things to a string, the convert the string into a symbol interned in current package. Return the symbol
macro.lisp (file)
Get a CONS from free cons pool, otherwise allocate it. Return the CONS.
Create and return a copy of binary tree M. Keys and values in M are shallow copied.
Fill MCOPY with a copy of gmap M and return MCOPY.
Copies all keys and values from M into MCOPY
and removes any other key/value already present in MCOPY.
Copy all key/value pairs from hash-table SRC into hash-table DST. Other keys (and their values) present in DST but not in SRC are not modified. Return DST.
hash-table.lisp (file)
Return a new association list which is EQUAL to TALIST.
tcons-alist.lisp (file)
cpuid.lisp (file)
Add feature F and its VALUE into *FEATURE-LIST*, unless F is already present. Return (values T VALUE) if F was actually inserted in *FEATURE-LIST*, otherwise return NIL and the value already present in *FEATURE-LIST*.
features.lisp (file)
Set the value of each feature in ALIST, unless the feature is already
present in *FEATURE-LIST*. Each element in ALIST must be either
a pair (FEATURE VALUE) or a simple atom FEATURE.
In the latter case, the FEATURE value will default to T.
features.lisp (file)
thread.lisp (file)
thread.lisp (file)
Return current capacity of FAST-VECTOR.
fast-vector.lisp (file)
Remove all elements from FAST-VECTOR. Return FAST-VECTOR.
fast-vector.lisp (file)
Return current length of FAST-VECTOR.
fast-vector.lisp (file)
If FAST-VECTOR is not empty, remove its last element and return it and t as multiple values. Otherwise return (values DEFAULT NIL).
fast-vector.lisp (file)
If FAST-VECTOR is not full, append NEW-ELEMENT to FAST-VECTOR and return
the index of the pushed element.
Otherwise return NIL.
fast-vector.lisp (file)
If FAST-VECTOR is full, resize it. Then append NEW-ELEMENT to FAST-VECTOR and return the index of the pushed element.
fast-vector.lisp (file)
Find and return the symbol named SYMBOL-NAME in PACKAGE
compiler.lisp (file)
Optimized version of (/= x y) for FIXNUM arguments
Optimized version of (< x y) for FIXNUM arguments
Optimized version of (= x y) for FIXNUM arguments
Optimized version of (> x y) for FIXNUM arguments
Add a CONS cell to free cons pool.
Add a list of CONS cells to free cons pool.
Return current value of atomic COUNTER.
atomic-counter.lisp (file)
Return DELTA plus current value of atomic COUNTER.
atomic-counter.lisp (file)
Return value of F in *FEATURE-LIST* and T, or (values DEFAULT NIL) if not present or has NIL value.
features.lisp (file)
If KEY is associated to VALUE in HASH, return (values VALUE t) Otherwise return (values DEFAULT nil).
ghash-table.lisp (file)
(setf get-ghash) (setf expander)
ghash-table.lisp (file)
get-ghash (function)
set-ghash (function)
Find KEY in binary tree M and return its value and T as multiple values. If M does not contain KEY, return (values DEFAULT NIL).
gmap.lisp (file)
(setf get-gmap) (function)
Add KEY to binary tree M if not present, and associate VALUE to KEY in M. Return VALUE.
Same as (gethash key hash), only with reversed arguments.
hash-table.lisp (file)
(setf get-hash) (function)
Same as (setf (gethash key hash) value), only with reversed key and hash arguments.
hash-table.lisp (file)
get-hash (function)
Return a list containing the keys in ghash-table SRC.
If TO-LIST is not nil, it will be appended to the returned list.
TO-LIST contents is not destructively modified.
ghash-table.lisp (file)
Return an alist containing a (key . value) pair for each entry
in ghash-table SRC.
If TO-ALIST is not nil, it will be appended to the returned alist.
TO-ALIST contents is not destructively modified.
ghash-table.lisp (file)
Return the number of KEY/VALUE entries in ghash-table HASH.
ghash-table.lisp (file)
Return T if GHASH-TABLE is empty, i.e. if it contains no entries.
ghash-table.lisp (file)
Return the symbol used by ghash-table HASH to hash keys.
ghash-table.lisp (file)
Return the symbol used by ghash-table HASH to compare keys.
ghash-table.lisp (file)
Return a list containing the values in ghash-table SRC.
If TO-LIST is not nil, it will be appended to the returned list.
TO-LIST contents is not destructively modified.
ghash-table.lisp (file)
Return number of elements in binary tree M.
Return t if binary tree M is empty, otherwise return nil.
Return an ordered list of all keys contained in M.
Return an ordered list of pairs (key . value) containing all entries in M.
Return the predicate symbol used by binary tree M to sort keys.
Return a list of all values contained in M.
The values are returned in the order given by their keys:
first the value associated to the smallest key, and so on.
Return a list containing the keys in hash-table SRC.
If TO-LIST is not nil, it will be appended to the returned list.
TO-LIST contents is not destructively modified.
hash-table.lisp (file)
Return an alist containing a (key . value) pair for each entry
in hash-table SRC.
If TO-ALIST is not nil, it will be appended to the returned alist.
TO-ALIST contents is not destructively modified.
hash-table.lisp (file)
Return a list containing the values in hash-table SRC.
If TO-LIST is not nil, it will be appended to the returned list.
TO-LIST contents is not destructively modified.
hash-table.lisp (file)
Increase atomic COUNTER by DELTA and return its new value.
atomic-counter.lisp (file)
Test for HLE, i.e. hardware lock elision.
HLE is supported if (cpuid 7) returns ebx with bit 4 set.
If a processor does not support HLE, it will ignore the
assembler instruction prefixes XACQUIRE and XRELEASE.
cpuid.lisp (file)
Create and return a new ATOMIC-COUNTER.
atomic-counter.lisp (file)
Create and return an initially empty FAST-VECTOR with specified maximum length.
Note: initial-element MUST be compatible with type element-type,
i.e. (typep initial-element element-type) must return true.
fast-vector.lisp (file)
Create and return a MUTEX.
mutex.lisp (file)
Constructs a tlist with SIZE elements each set to INITIAL-ELEMENT
tcons.lisp (file)
Invoke FUNC on each key/value pair contained in HASH. Return NIL.
FUNC must be a function accepting two arguments: key and value.
Adding or removing keys from HASH during this call (even from other threads) has undefined consequences. Not even the current key can be removed.
ghash-table.lisp (file)
Invoke FUNC in order on each key/value pair contained in M:
first invoke it on the smallest key, then the second smallest...
finally invoke FUNC on the largest key. Return nil.
FUNC must be a function accepting two arguments: key and value.
Adding or removing keys from M during this call (even from other threads) has undefined consequences. Not even the current key can be removed.
Return the largest key in M, its value, and t as multiple values, or (values nil nil nil) if M is empty
Copy hash-table SRC into hash-table DST.
Return t if SRC and DST are compatible,
i.e. if they contain eq values for the keys common to both,
otherwise return nil.
(in the latter case, the merge will not be completed).
hash-table.lisp (file)
Return the smallest key in M, its value, and t as multiple values, or (values nil nil nil) if M is empty.
Return T if MUTEX is free. Return NIL if MUTEX
is currently locked by current thread or some other thread.
mutex.lisp (file)
Return T if MUTEX is free or locked by current thread. Return NIL if MUTEX is currently locked by some other thread.
mutex.lisp (file)
Return T if MUTEX is locked by current thread.
mutex.lisp (file)
mutex.lisp (file)
Release MUTEX. Return NIL. Consequences are undefined if MUTEX is locked by another thread or is already unlocked.
mutex.lisp (file)
Remove KEY from HASH.
Return T if KEY was present in HASH, otherwise return NIL.
ghash-table.lisp (file)
Find and remove KEY and its associated value from binary tree M. Return t if KEY was removed, nil if not found.
Same as (remhash key hash), only with reversed arguments.
hash-table.lisp (file)
N-ary version of REM-GMAP:
remove a list of keys from M. Return M.
Abort the current transaction and re-run it again from the beginning.
Before re-executing, the transaction will wait on all variables that it read until at least one of them changes.
classes.lisp (file)
Function equivalent of the ATOMIC macro.
Run the function TX inside a memory transaction.
If the transaction is invalid (conflicts) re-run TX immediately, ignoring
any error it may signal.
Otherwise, commit if TX returns normally, or rollback if it signals an error.
Finally, if TX called (retry), re-run it after at least some of the transactional memory it read has changed.
atomic.lisp (file)
Function variant of ‘orelse’. Execute the functions in FUNCS list
one by one from left to right in separate, nested transactions until one succeeds
(i.e. commits) or signals an error.
If a nested transaction is invalid or wants to retry, run the next one.
Returns the value of the transaction that succeeded,
or signals the error raised by the transaction that failed.
Can only be used inside an ATOMIC block.
orelse.lisp (file)
Set and return value of atomic COUNTER.
atomic-counter.lisp (file)
Set feature F to VALUE, even if F is already present in *FEATURE-LIST*. Return VALUE.
features.lisp (file)
Set the value of each feature in PLIST, even if the feature is already
present in *FEATURE-LIST*. Each element in PLIST must be either
a pair (FEATURE VALUE) or a simple atom FEATURE.
In the latter case, the FEATURE value will default to T.
features.lisp (file)
Add KEY to HASH, associating it to VALUE. Return VALUE.
ghash-table.lisp (file)
(setf get-ghash) (setf expander)
Add KEY to binary tree M if not present, and associate KEY to VALUE in M. Return VALUE.
Shortcut for (setf (gethash key hash) value)
hash-table.lisp (file)
Create and return a new SIMPLE-TVECTOR.
simple-tvector.lisp (file)
Return the length of simple-tvector TVEC.
simple-tvector.lisp (file)
thread.lisp (file)
thread.lisp (file)
Print the things to a string and return it
macro.lisp (file)
Variant of SXHASH designed for EQUALP tests, i.e.
(equalp x y) implies (= (sxhash-equalp x) (sxhash-equalp y)).
A common use is for ghash-tables and thash-tables that use :test ’equalp
compiler.lisp (file)
Construct a new talist by adding the pair (KEY . DATUM) to TALIST.
tcons-alist.lisp (file)
Return the tcons in TALIST whose tcar is equal (by a given test or EQL) to the ITEM.
tcons-alist.lisp (file)
Return NIL if OBJECT is a TCONS, and T otherwise.
tcons.lisp (file)
Return the CAR of the CAAAR of a TLIST.
tcons-list.lisp (file)
(setf tcaaaar) (function)
Set the CAR of the CAAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaaaar (function)
Return the CAR of the CAADR of a TLIST.
tcons-list.lisp (file)
(setf tcaaadr) (function)
Set the CAR of the CAADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaaadr (function)
Return the CAR of the CAAR of a TLIST.
tcons-list.lisp (file)
(setf tcaaar) (function)
Set the CAR of the CAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaaar (function)
Return the CAR of the CADAR of a TLIST.
tcons-list.lisp (file)
(setf tcaadar) (function)
Set the CAR of the CADAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaadar (function)
Return the CAR of the CADDR of a TLIST.
tcons-list.lisp (file)
(setf tcaaddr) (function)
Set the CAR of the CADDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaaddr (function)
Return the CAR of the CADR of a TLIST.
tcons-list.lisp (file)
(setf tcaadr) (function)
Set the CAR of the CADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaadr (function)
Return the CAR of the CAR of a TLIST.
tcons-list.lisp (file)
(setf tcaar) (function)
Set the CAR of the CAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaar (function)
Return the CAR of the CDAAR of a TLIST.
tcons-list.lisp (file)
(setf tcadaar) (function)
Set the CAR of the CDAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcadaar (function)
Return the CAR of the CDADR of a TLIST.
tcons-list.lisp (file)
(setf tcadadr) (function)
Set the CAR of the CDADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcadadr (function)
Return the CAR of the CDAR of a TLIST.
tcons-list.lisp (file)
(setf tcadar) (function)
Set the CAR of the CDAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcadar (function)
Return the CAR of the CDDAR of a TLIST.
tcons-list.lisp (file)
(setf tcaddar) (function)
Set the CAR of the CDDAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaddar (function)
Return the CAR of the CDDR of a TLIST.
tcons-list.lisp (file)
(setf tcaddr) (function)
Set the CAR of the CDDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcaddr (function)
Return the CAR of the CDR of a TLIST.
tcons-list.lisp (file)
(setf tcadr) (function)
Set the CAR of the CDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcadr (function)
Return the 1st object in a TLIST.
tcons.lisp (file)
(setf tcar) (setf expander)
Set VALUE as the first element in a TCONS or non-null TLIST. This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
tcar (function)
Return the CDR of the CAAAR of a TLIST.
tcons-list.lisp (file)
(setf tcdaaar) (function)
Set the CDR of the CAAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdaaar (function)
Return the CDR of the CAADR of a TLIST.
tcons-list.lisp (file)
(setf tcdaadr) (function)
Set the CDR of the CAADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdaadr (function)
Return the CDR of the CAAR of a TLIST.
tcons-list.lisp (file)
(setf tcdaar) (function)
Set the CDR of the CAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdaar (function)
Return the CDR of the CADAR of a TLIST.
tcons-list.lisp (file)
(setf tcdadar) (function)
Set the CDR of the CADAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdadar (function)
Return the CDR of the CADDR of a TLIST.
tcons-list.lisp (file)
(setf tcdaddr) (function)
Set the CDR of the CADDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdaddr (function)
Return the CDR of the CADR of a TLIST.
tcons-list.lisp (file)
(setf tcdadr) (function)
Set the CDR of the CADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdadr (function)
Return the CDR of the CAR of a TLIST.
tcons-list.lisp (file)
(setf tcdar) (function)
Set the CDR of the CAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdar (function)
Return the CDR of the CDAAR of a TLIST.
tcons-list.lisp (file)
(setf tcddaar) (function)
Set the CDR of the CDAAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcddaar (function)
Return the CDR of the CDADR of a TLIST.
tcons-list.lisp (file)
(setf tcddadr) (function)
Set the CDR of the CDADR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcddadr (function)
Return the CDR of the CDAR of a TLIST.
tcons-list.lisp (file)
(setf tcddar) (function)
Set the CDR of the CDAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcddar (function)
Return the CDR of the CDDAR of a TLIST.
tcons-list.lisp (file)
(setf tcdddar) (function)
Set the CDR of the CDDAR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdddar (function)
Return the CDR of the CDDR of a TLIST.
tcons-list.lisp (file)
(setf tcdddr) (function)
Set the CDR of the CDDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcdddr (function)
Return the CDR of the CDR of a TLIST.
tcons-list.lisp (file)
(setf tcddr) (function)
Set the CDR of the CDR of a TLIST.
This function should always be executed inside an STMX atomic block.
tcons-list.lisp (file)
tcddr (function)
Return all but the first object in a TLIST.
tcons.lisp (file)
(setf tcdr) (setf expander)
Set VALUE as the rest element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
tcdr (function)
Create and return a new TCELL.
tcell.lisp (file)
Create and return a new TCONS.
tcons.lisp (file)
tcons.lisp (file)
Return the 8th object in a TLIST or NIL if there is no 8th object.
tcons-list.lisp (file)
(setf teighth) (function)
Set the 8th object in a TLIST.
tcons-list.lisp (file)
teighth (function)
This is the recommended way to test for the end of a proper TLIST. It returns true if OBJECT is NIL, false if OBJECT is a TCONS, and an error for any other type of OBJECT.
tcons-list.lisp (file)
tfifo.lisp (file)
Return the 5th object in a TLIST or NIL if there is no 5th object.
tcons-list.lisp (file)
(setf tfifth) (function)
Set the 5th object in a TLIST.
tcons-list.lisp (file)
tfifth (function)
Return the first element in a TCONS or TLIST.
tcons.lisp (file)
(setf tfirst) (setf expander)
Set VALUE as the first element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
tfirst (function)
Return the 4th object in a TLIST or NIL if there is no 4th object.
tcons-list.lisp (file)
(setf tfourth) (function)
Set the 4th object in a TLIST.
tcons-list.lisp (file)
tfourth (function)
Return the last N conses (not the last element!) of a TLIST.
tcons-list.lisp (file)
Create and return a new TLIST, whose cells are TCONS.
tcons.lisp (file)
Return a TLIST of the arguments with last TCONS a dotted pair.
tcons.lisp (file)
Return the length of the given TLIST, or NIL if the TLIST is circular.
tcons-list.lisp (file)
Return the 9th object in a TLIST or NIL if there is no 9th object.
tcons-list.lisp (file)
(setf tninth) (function)
Set the 9th object in a TLIST.
tcons-list.lisp (file)
tninth (function)
Return the Nth object in a TLIST where the TCAR is the zero-th element.
tcons-list.lisp (file)
(setf tnth) (function)
Set the Nth element of TLIST to NEWVAL.
tcons-list.lisp (file)
tnth (function)
Performs the TCDR function N times on a TLIST.
tcons-list.lisp (file)
Construct an association list from KEYS and DATA (adding to TALIST).
tcons-alist.lisp (file)
Voluntarily abort a hardware memory transaction
with an error-code equal to +transaction-user-abort+.
If a transaction is in progress, TRANSACTION-ABORT does not return normally:
execution is resumed at the instruction immediately after the outermost
TRANSACTION-BEGIN.
If called without an active transaction, TRANSACTION-ABORT returns normally with an implementation-dependent value.
transaction.lisp (file)
Start a hardware memory transaction.
Return +transaction-started+ if transaction started successfully,
otherwise return code of the error that caused the transaction to abort.
Invoking TRANSACTION-BEGIN while there is already a running hardware memory transaction has implementation-dependent effects.
transaction.lisp (file)
Commit a hardware memory transaction.
Return normally (with an implementation-dependent value) if commit is successful,
otherwise abort the transaction.
In case the transaction is aborted, all effects of code between TRANSACTION-BEGIN
and TRANSACTION-END are rolled back (undone):
execution resumes at the instruction immediately after TRANSACTION-BEGIN,
in such a way that TRANSACTION-BEGIN will appear to have returned
a non-zero error code (that describes the abort reason).
Invoking TRANSACTION-END without a running hardware memory transaction
has undefined consequences.
transaction.lisp (file)
If ERR-CODE is the result returned by (TRANSACTION-BEGIN) of an *aborted* transaction,
return T if re-running the same transaction has a possibility to succeed,
i.e. if the abort reason was temporary (as for example a conflict with another thread).
Return NIL if re-running the same transaction has no possibility to succeed.
transaction.lisp (file)
Return T if a hardware memory transaction is currently in progress, otherwise return NIL.
transaction.lisp (file)
Test for RTM, i.e. hardware memory transactions.
RTM is supported if (cpuid 7) returns ebx with bit 11 set.
If a processor does not support HLE, trying to execute
the assembler instructions XBEGIN, XEND, XABORT and XTEST
will generate faults.
cpuid.lisp (file)
Return true if inside a software or hardware transaction.
classes.lisp (file)
Return the cons in TALIST whose tcdr is equal (by a given test or EQL) to the ITEM.
tcons-alist.lisp (file)
Return the rest element in a TCONS or TLIST.
tcons.lisp (file)
(setf trest) (setf expander)
Set VALUE as the rest element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
trest (function)
Try to acquire MUTEX. Return T if successful, or NIL if MUTEX was already locked.
mutex.lisp (file)
Return the 2nd object in a TLIST or NIL if there is no 2nd object.
tcons-list.lisp (file)
(setf tsecond) (function)
Set the 2nd object in a TLIST.
tcons-list.lisp (file)
tsecond (function)
Return the 7th object in a TLIST or NIL if there is no 7th object.
tcons-list.lisp (file)
(setf tseventh) (function)
Set the 7th object in a TLIST.
tcons-list.lisp (file)
tseventh (function)
Return the 6th object in a TLIST or NIL if there is no 6th object.
tcons-list.lisp (file)
(setf tsixth) (function)
Set the 6th object in a TLIST.
tcons-list.lisp (file)
tsixth (function)
Create and return a new TSTACK.
tstack.lisp (file)
Return the INDEX-th element of simple-tvector TVEC. Works both inside and outside transactions
simple-tvector.lisp (file)
(setf tsvref) (setf expander)
simple-tvector.lisp (file)
tsvref (function)
set-tsvref (function)
Return the 10th object in a TLIST or NIL if there is no 10th object.
tcons-list.lisp (file)
(setf ttenth) (function)
Set the 10th object in a TLIST.
tcons-list.lisp (file)
ttenth (function)
Return the 3rd object in a TLIST or NIL if there is no 3rd object.
tcons-list.lisp (file)
(setf tthird) (function)
Set the 3rd object in a TLIST.
tcons-list.lisp (file)
tthird (function)
Return T if X and Y are isomorphic TLIST trees with identical leaves.
tcons-tree.lisp (file)
tcons-tree.lisp (file)
tcons-tree.lisp (file)
Unbind the value inside transactional variable VAR.
Works both outside and inside transactions.
During transactions, it uses transaction log to record the ’unbound’ value.
tvar-slot.lisp (file)
thread.lisp (file)
print.lisp (file)
Next: Exported structures, Previous: Exported functions, Up: Exported definitions [Contents][Index]
Remove all values contained in PLACE. Return PLACE.
container.lisp (file)
Remove all values from bheap Q. Return Q.
bheap.lisp (file)
tchannel.lisp (file)
tfifo.lisp (file)
tstack.lisp (file)
Remove value from CELL. Return CELL.
tcell.lisp (file)
Remove value from tvar.
tvar.lisp (file)
Return nil if PLACE contains at least one value, otherwise return t.
container.lisp (file)
Return t if bheap Q is empty.
bheap.lisp (file)
tchannel.lisp (file)
Tchannels are write-only: it is never possible to read values from them, so assume they are always empty and return t.
tchannel.lisp (file)
tfifo.lisp (file)
tstack.lisp (file)
tcell.lisp (file)
tvar.lisp (file)
Return t if PLACE cannot contain more values, otherwise return nil.
container.lisp (file)
A bheap is never full, so this method always returns nil.
bheap.lisp (file)
Tports are read-only: it is never possible to store values in them, so assume they are always full and return t.
tchannel.lisp (file)
Tchannels can contain unlimited values: they are never full, so always return nil.
tchannel.lisp (file)
A tfifo is never full, so this method always returns nil.
tfifo.lisp (file)
A tstack is never full, so this method always returns nil.
tstack.lisp (file)
Default implementation: assumes that PLACE can contain only one value.
print.lisp (file)
classes.lisp (file)
tvar-fwd.lisp (file)
Return one value stored in PLACE without removing it, and t as multiple values. If PLACE contains no values, return (values DEFAULT nil).
container.lisp (file)
Return the first value in bheap Q without removing it, and t as multiple values. Return (values DEFAULT nil) if Q contains no values.
bheap.lisp (file)
Return the first value in tport P without removing it, and t as multiple values. Return (values DEFAULT nil) if P contains no value.
tchannel.lisp (file)
Return the first value in tfifo F without removing it, and t as multiple values. Return (values DEFAULT nil) if F contains no value.
tfifo.lisp (file)
Return the first value in tstack S without removing it, and t as multiple values. Return (values DEFAULT nil) if S contains no values.
tstack.lisp (file)
tcell.lisp (file)
tvar.lisp (file)
Wait until PLACE can contain more values, then store VALUE in it and return VALUE.
container.lisp (file)
Store VALUE in bheap Q. Return VALUE.
bheap.lisp (file)
Append VALUE as last element in tchannel C and return VALUE.
Since tchannel can contain unlimited values, this method never blocks.
tchannel.lisp (file)
Append VALUE as last element in tfifo F and return VALUE.
Since tfifo can contain unlimited values, this method never blocks.
tfifo.lisp (file)
Insert VALUE as first element in tstack S and return VALUE. Since tstack can contain unlimited values, this method never blocks.
tstack.lisp (file)
tcell.lisp (file)
tvar.lisp (file)
Wait until PLACE contains at least one value, then remove and return one value.
container.lisp (file)
Wait until tport P contains at least one value, then remove and return the first value.
tchannel.lisp (file)
Wait until tfifo F contains at least one value, then remove and return the first value.
tfifo.lisp (file)
Wait until tstack S contains at least one value, then remove and return the first value.
tstack.lisp (file)
tcell.lisp (file)
tvar.lisp (file)
If PLACE can contain more values, store VALUE it and return t and VALUE as multiple values. Otherwise return (values nil nil)
container.lisp (file)
Store VALUE in bheap Q. Return t and VALUE This method never fails.
bheap.lisp (file)
Append VALUE to tchannel C and return (values t VALUE).
Since tchannel can contain unlimited values, this method never fails.
tchannel.lisp (file)
Append VALUE as last element in tfifo F and return (values t VALUE). Since tfifo can contain unlimited values, this method never fails.
tfifo.lisp (file)
Append VALUE to tstack S and return (values t VALUE).
Since fifo can contain unlimited values, this method never fails.
tstack.lisp (file)
hand-made, nonblocking version of (put place) for tcells. less general but approx. 3 times faster (on SBCL 1.0.57.0.debian, Linux amd64) than the unspecialized (try-put place) which calls (atomic (nonblocking (put place value)))
tcell.lisp (file)
hand-made, nonblocking version of (put place) for TVARs.
Less general but approx. 3 times faster (on SBCL 1.0.57.0.debian,
Linux amd64) than the unspecialized (try-put place) which calls
(atomic (nonblocking (put place value)))
tvar.lisp (file)
this method shows a general technique to convert a blocking, atomic operation into a nonblocking, atomic one: simply wrap it in (atomic (nonblocking ...))
If PLACE contains at least one value, remove one value and return t and it as multiple values. Otherwise return (values nil nil)
container.lisp (file)
If bheap S contains at least one value, remove the first value and return t and the first value as multiple values. Otherwise return (values nil nil)
bheap.lisp (file)
If tport P contains at least one value, remove the first value and return t and the first value as multiple values. Otherwise return (values nil nil)
tchannel.lisp (file)
If tfifo F contains at least one value, remove the first value and return t and the first value as multiple values. Otherwise return (values nil nil)
tfifo.lisp (file)
If tstack S contains at least one value, remove the first value and return t and the first value as multiple values. Otherwise return (values nil nil)
tstack.lisp (file)
hand-made, nonblocking version of (take place) for cells. less general but approx. 3 times faster (on SBCL 1.0.57.0.debian, Linux amd64) than the unspecialized (try-take place) which calls (atomic (nonblocking (take place)))
tcell.lisp (file)
hand-made, nonblocking version of (take place) for TVARs. Less general but approx. 3 times faster (on SBCL 1.0.57.0.debian, Linux amd64) than the unspecialized (try-take place) which calls (atomic (nonblocking (take place)))
tvar.lisp (file)
this method shows a general technique to convert a blocking, atomic operation into a nonblocking, atomic one: simply wrap it in (atomic (nonblocking ...))
Next: Exported classes, Previous: Exported generic functions, Up: Exported definitions [Contents][Index]
atomic-counter.lisp (file)
structure-object (structure)
gv156 (structure)
stmx.lang:atomic-counter-slot-type
0
atomic-counter-version (function)
(setf atomic-counter-version) (function)
fast-vector.lisp (file)
structure-object (structure)
fixnum
0
fast-vector-len (function)
(setf fast-vector-len) (function)
simple-vector
stmx.lang::+empty-vector+
fast-vector-vec (function)
(setf fast-vector-vec) (function)
0
fast-vector-initial-element (function)
(setf fast-vector-initial-element) (function)
mutex.lisp (file)
structure-object (structure)
stmx.lang::atomic-t
mutex-owner (function)
(setf mutex-owner) (function)
Transactional cell holding two values. It is the STM equivalent of CONS cells.
To use TCONS cells, prepend T to the name of most list-manipulating functions. Examples:
(CONS a b) -> (TCONS a b)
(LIST ...) -> (TLIST ...)
(FIRST c) -> (TFIRST c)
(REST c) -> (TREST c) and so on
tcons.lisp (file)
structure-object (structure)
print-object (method)
(stmx:transactional t)
(stmx::tstruct-slot-initialize (quote stmx.util:tcons) (quote first) (quote nil))
%stmx-impl/tstruct/tcons-first (function)
(setf %stmx-impl/tstruct/tcons-first) (function)
(stmx:transactional t)
(stmx::tstruct-slot-initialize (quote stmx.util:tcons) (quote rest) (quote nil))
%stmx-impl/tstruct/tcons-rest (function)
(setf %stmx-impl/tstruct/tcons-rest) (function)
a transactional variable (tvar) is the smallest unit of transactional memory.
it contains a single value that can be read or written during a transaction
using ($-slot var) and (setf ($-slot var) value).
tvars are seldom used directly, since transactional objects (tobjs) wrap them
with a more convenient interface: you can read and write normally the slots
of a transactional object (with slot-value, accessors ...), and behind
the scenes the slots will be stored in transactional memory implemented by tvars.
tvar-fwd.lisp (file)
structure-object (structure)
stmx::version-type
stmx::+invalid-version+
tvar-version (function)
(setf tvar-version) (function)
stmx:+unbound-tvar+
tvar-value (function)
(setf tvar-value) (function)
fixnum
stmx::+invalid-version+
tvar-id (function)
(setf tvar-id) (function)
(or null hash-table)
tvar-waiting-for (function)
(setf tvar-waiting-for) (function)
(bordeaux-threads:make-lock "tvar-waiting")
tvar-waiting-lock (function)
(setf tvar-waiting-lock) (function)
Next: Exported types, Previous: Exported structures, Up: Exported definitions [Contents][Index]
Generic hash-table. Allows custom :test argument at creation - default is ’eql.
If :test is not one of ’eq ’eql or ’equal, also requires explicit :hash
argument at creation.
Not so useful by itself (standard CL:HASH-TABLE is usually faster),
it is the base for transactional hash-table implementation THASH-TABLE.
ghash-table.lisp (file)
standard-object (class)
thash-table (class)
(or stmx.util::ghash-vector stmx:tvar)
stmx.util::ghash-test-fun
stmx.util::ghash-hash-fun
stmx.util::ghash-aref-fun
(function svref)
stmx.util::ghash-set-aref-fun
(function stmx.util::set-svref)
(or null fixnum stmx:tvar)
0
symbol
:test
(quote eql)
symbol
:hash
Generic binary tree
gmap.lisp (file)
standard-object (class)
rbmap (class)
(or null stmx.util::gmap-node stmx:tvar)
function
pred-function-of (generic function)
(or null fixnum stmx:tvar)
0
count-of (generic function)
symbol
:pred
pred-of (generic function)
Red-black tree implementation of sorted binary map
rbmap.lisp (file)
gmap (class)
tmap (class)
tcell.lisp (file)
transactional-object (class)
:value
stmx.util::+empty-tcell+
Transactional multicast channel supporting unlimited reading ports.
Values written into the tchannel are available to all reading ports in the same order.
References to values written into the tchannel are kept only as long as
one or more ports still need to read them.
tchannel.lisp (file)
transactional-object (class)
(or stmx.util:tcons stmx:tvar)
(stmx.util:tcons nil nil)
back-of (generic function)
(setf back-of) (generic function)
tfifo.lisp (file)
transactional-object (class)
(or stmx.util:tcons stmx:tvar)
front-of (generic function)
(setf front-of) (generic function)
(or stmx.util:tcons stmx:tvar)
back-of (generic function)
(setf back-of) (generic function)
Transactional hash table.
thash-table.lisp (file)
Transactional sorted map, implemented with red-black tree
tmap.lisp (file)
(or (or null stmx.util::tnode) stmx:tvar)
Transactional reading port for a multicast tchannel.
Values written into the tchannel are available to all reading ports in the same order.
tchannel.lisp (file)
transactional-object (class)
(or cons stmx:tvar)
front-of (generic function)
(setf front-of) (generic function)
stmx.util:tchannel
:channel
(error "missing :channel argument instantiating ~a or a subclass" (quote stmx.util:tport))
channel-of (generic function)
The metaclass for transactional classes.
Classes defined with this metaclass have extra slot options, see the class TRANSACTIONAL-DIRECT-SLOT for details.
tclass.lisp (file)
standard-class (class)
Superclass of all transactional objects.
tclass.lisp (file)
standard-object (class)
update-instance-for-redefined-class (method)
tstack.lisp (file)
transactional-object (class)
(or list stmx:tvar)
stmx.util::top
top-of (generic function)
(setf top-of) (generic function)
Previous: Exported classes, Up: Exported definitions [Contents][Index]
atomic-counter.lisp (file)
atomic-counter.lisp (file)
ATOMIC-NUM must be a type suitable for ATOMIC-INCF and ATOMIC-DECF. STMX also assumes it is the same or wider than fixnum.
atomic-ops.lisp (file)
SIMPLE-TVECTOR is a transactional, one dimensional array. It is currently a deftype, not a class or struct: methods cannot be specialized on it.
simple-tvector.lisp (file)
tcons.lisp (file)
Transactional memory containing TYPE
tvar-fwd.lisp (file)
Previous: Exported definitions, Up: Definitions [Contents][Index]
• Internal constants | ||
• Internal special variables | ||
• Internal macros | ||
• Internal functions | ||
• Internal generic functions | ||
• Internal conditions | ||
• Internal structures | ||
• Internal classes | ||
• Internal types |
Next: Internal special variables, Previous: Internal definitions, Up: Internal definitions [Contents][Index]
rbmap.lisp (file)
compiler.lisp (file)
Empty TCELL objects actually contain this symbol in their VALUE slot. Use with care.
tcell.lisp (file)
Default initial capacity of a GHASH-TABLE.
ghash-table.lisp (file)
Maximum capacity of a GHASH-TABLE.
Equal to MOST-POSITIVE-FIXNUM rounded down to nearest power of 2.
ghash-table.lisp (file)
ghash-table.lisp (file)
+global-clock+ VERSION is incremented by 2 each time: the lowest bit is reserved as "locked" flag in TVARs versioning - used if TVAR-LOCK feature is equal to :BIT.
global-clock.lisp (file)
+global-clock+ NOHW-COUNTER incremented by 2 each time: the lowest bit is reserved as "prevent HW transactions"
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
hw-atomic.lisp (file)
tvar-fwd.lisp (file)
rbmap.lisp (file)
classes.lisp (file)
txhash.lisp (file)
Next: Internal macros, Previous: Internal constants, Up: Internal definitions [Contents][Index]
bheap.lisp (file)
features.lisp (file)
A boolean controlling the behaviour of the function (slot-value)
and of slot accessors for TOBJs slots:
- if false, (slot-value) and accessors will get or set the actual TVAR stored
inside the slot.
- if true, (slot-value) and accessors will get or set the value stored inside
the slot’s TVAR.
This flag is almost always true; it is temporarily set to false during some MOP calls (slot-value-using-class ...) that implement access to TOBJs slots.
classes.lisp (file)
classes.lisp (file)
global-clock.lisp (file)
optimize-for.lisp (file)
print.lisp (file)
A flag indicating if transactions are being recorded to TLOGs or not.
Recording is normally enabled during transactions,
while it is normally disabled in these cases:
- outside transactions
- when initializing TOBJs slots
- during some MOP calls (slot-value-using-class etc.) that implement
access to TOBJs slots.
classes.lisp (file)
tclass.lisp (file)
tclass.lisp (file)
The current transaction log.
classes.lisp (file)
tvar-fwd.lisp (file)
txhash.lisp (file)
fast-vector.lisp (file)
macro.lisp (file)
Next: Internal functions, Previous: Internal special variables, Up: Internal definitions [Contents][Index]
tcons-list.lisp (file)
tcons-list.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
Run BODY in a hardware memory transaction.
If the transaction aborts, retry it as long as it has chances to succeed.
If it has no chances to succeed, execute FALLBACK.
Warning: if a transaction is already running, execute BODY inside it
hw-atomic.lisp (file)
tcons-alist.lisp (file)
tcons-list.lisp (file)
tcons-list.lisp (file)
tcons-alist.lisp (file)
tcons-list.lisp (file)
tcons-list.lisp (file)
tcons-alist.lisp (file)
Like PUSH, but atomic. PLACE may be read multiple times before the operation completes – the write does not occur until such time that no other thread modified PLACE between the read and the write.
Works only on places supported by ATOMIC-COMPARE-AND-SWAP.
atomic-ops.lisp (file)
classes.lisp (file)
classes.lisp (file)
thread.lisp (file)
Return the current software transaction log
classes.lisp (file)
tclass.lisp (file)
tstruct.lisp (file)
compiler.lisp (file)
Execute BODY on every transactional direct slot (not inherited) of CLASS.
tclass.lisp (file)
Execute BODY on every transactional slot (direct or inherited) of CLASS.
tclass.lisp (file)
Execute BODY on each KEY/VALUE contained in FIFO. Return NIL.
txhash.lisp (file)
Execute BODY on each TXPAIR contained in FIFO. Return NIL.
txhash.lisp (file)
Execute BODY on each GHASH-PAIR pair contained in HASH. Return NIL.
ghash-table.lisp (file)
Execute BODY in order on each key/value pair contained in M:
first execute it on the smallest key, then the second smallest...
finally execute BODY on the largest key. Return nil.
If :FROM-END is true, BODY will be executed first on the largest key,
then on the second largest key... and finally on the smallest key.
Adding or removing keys from M during this call (even from other threads) has undefined consequences. Not even the current key can be removed.
Execute BODY inside a loop, iterating on tstruct-def STRUCT-DEF and all its superclasses
tstruct.lisp (file)
Analogous to DOLIST, iterates on transactional list TLIST.
On each iteration, sets VAR to the element and executes BODY inside a tagbody.
Returns RESULT. Note: when RESULT is executed, VAR is set to NIL.
An implicit block named NIL surrounds DO-TLIST, so RETURN can be used
to terminate immediately the iterations and return zero or more values.
tcons.lisp (file)
Execute BODY on tstruct-def STRUCT-DEF and all its superclasses
tstruct.lisp (file)
Execute BODY on each KEY/VALUE contained in FIFO. Return NIL.
txhash.lisp (file)
Execute BODY on each TXPAIR contained in FIFO. Return NIL.
txhash.lisp (file)
Execute BODY on each KEY/VALUE contained in HASH. Return NIL.
txhash.lisp (file)
Execute BODY on each TXPAIR pair contained in HASH. Return NIL.
txhash.lisp (file)
sw-atomic.lisp (file)
Decrement by one the number of software-only transaction commits currently running.
This function must be called at the end of each software-only transaction commit, (retry), or any other operation incompatible with hardware transactions, in order to let the latter run, since their current implementations are mutually incompatible.
global-clock.lisp (file)
Return the features of the GLOBAL-CLOCK algorithm, i.e. a list containing zero or more of :SUITABLE-FOR-HW-TRANSACTIONS and :SPURIOUS-FAILURES-IN-SINGLE-THREAD. The list of possible features will be expanded as more GLOBAL-CLOCK algorithms are implemented.
global-clock.lisp (file)
Return the number of operations currently running that are incompatible with
hardware transactions. Example of operations that AT THE MOMENT are incompatible with
hardware transactions include:
1) software-only transaction commits
2) (retry)
This function must be called at the beginning of each hardware transaction
in order to detect if an incompatible operation is started during the hardware
transaction, and abort the transaction in such case.
global-clock.lisp (file)
Return the value to use as new transaction "read version",
This function must be called after a hardware transaction failed/aborted and before rerunning it.
global-clock.lisp (file)
Return the value to use as hardware transaction "read version".
This function must be invoked once upon starting a hardware transaction for the first time. In case the transaction just aborted and is being re-executed, invoke instead (GLOBAL-CLOCK/HW/AFTER-ABORT).
global-clock.lisp (file)
Return the value to use as hardware transaction "write version",
given the transaction current READ-VERSION that was assigned at transaction start.
During hardware transactions - and also during hardware-based commits of software transactions - this function must be called once before writing the first TVAR.
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
Return the value to use as TVAR "write version", given the hardware
transaction current WRITE-VERSION that was assigned by GLOBAL-CLOCK/HW/START-WRITE
before the transaction started writing to TVARs.
This function must be called for **each** TVAR being written during
hardware-assisted commit phase of software transactions
and during pure hardware transactions.
global-clock.lisp (file)
Increment by one the number of operations currently running that are incompatible with
hardware transactions.
This function must be called at the beginning of each software-only transaction commit, (retry), or any other operation incompatible with hardware transactions, in order to abort the latter, since their current implementations are mutually incompatible.
global-clock.lisp (file)
Return the value to use as new transaction "read version",
This function must be called after a software transaction failed/aborted and before rerunning it.
global-clock.lisp (file)
Return the value to use as software transaction "read version".
This function must be invoked once upon starting a software transaction for the first time. In case the transaction just aborted and is being re-executed, invoke instead (GLOBAL-CLOCK/SW/AFTER-ABORT).
global-clock.lisp (file)
Return the value to use as softarw transaction "write version", given the software transaction current READ-VERSION that was assigned at transaction start.
During software-only commits, this function must be called once before committing the first TVAR write.
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
Return the value to use as TVAR "write version", given the software
transaction current WRITE-VERSION that was assigned by GLOBAL-CLOCK/SW/START-WRITE
before the transaction started writing to TVARs.
Fhis function must be called for **each** TVAR being written
during software-only commit phase of software transactions.
global-clock.lisp (file)
Return T if TVAR-VERSION is compatible with transaction "read version".
If this function returns NIL, the transaction must be aborted.
During software transactions, this function must be invoked after every TVAR read and before returning the TVAR value to the application code. During hardware transactions, this function is not used.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/AFTER-ABORT. Return the current +gv+ value.
global-clock.lisp (file)
This is GV1 implementation of GV1/DECF-NOHW-COUNTER. It does nothing and returns zero.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/FEATURES.
Return nil, i.e. not ’(:suitable-for-hw-transactions) because (GV1/START-WRITE ...) increments the global clock, which causes conflicts and aborts when multiple hardware transactions are running simultaneously.
global-clock.lisp (file)
This is GV1 implementation of GV1/GET-NOHW-COUNTER. It does nothing and returns zero.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/AFTER-ABORT. Calls GV1/AFTER-ABORT.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/START-READ. Calls GV1/START-READ.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/START-WRITE. Calls GV1/START-WRITE.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/STAT-ABORTED. Calls GV1/STAT-ABORTED.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/STAT-COMMITTED. Calls GV1/STAT-COMMITTED.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/HW/WRITE. Calls GV1/WRITE.
global-clock.lisp (file)
This is GV1 implementation of GV1/INCF-NOHW-COUNTER. It does nothing and returns zero.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/START-READ. Return the current +gv+ value.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/START-WRITE. Atomically increment +gv+ and return its new value.
global-clock.lisp (file)
This is GV1 implementation of GV1/STAT-ABORTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV1 implementation of GV1/STAT-COMMITTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/AFTER-ABORT. Calls GV1/AFTER-ABORT.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/START-READ. Calls GV1/START-READ.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/START-WRITE. Calls GV1/START-WRITE.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/STAT-ABORTED. Calls GV1/STAT-ABORTED.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/STAT-COMMITTED. Calls GV1/STAT-COMMITTED.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/SW/WRITE. Calls GV1/WRITE.
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/VALID-READ? Return (<= tvar-version read-version)
global-clock.lisp (file)
This is GV1 implementation of GLOBAL-CLOCK/WRITE. Return WRITE-VERSION.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/AFTER-ABORT. Increment +gv+ and return its new value.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/DECF-NOHW-COUNTER. Decrement by DELTA the slot NOHW-COUNTER of +gv+ and return its new value.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/FEATURES.
Return ’(:SUITABLE-FOR-HW-TRANSACTIONS :SPURIOUS-FAILURES-IN-SINGLE-THREAD)
because the global clock is incremented only by GV5/AFTER-ABORT, which avoids
incrementing it in GV5/START-WRITE (it would cause hardware transactions
to conflict with each other and abort) but also causes a 50% abort rate (!) even
in a single, isolated thread reading and writing its own transactional memory.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/GET-NOHW-COUNTER.
Return the number of software-only transaction commits currently running.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/AFTER-ABORT. Calls GV5/AFTER-ABORT.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/START-READ. Calls GV5/START-READ.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/START-WRITE. Calls GV5/START-WRITE.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/STAT-ABORTED. Calls GV5/STAT-ABORTED.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/STAT-COMMITTED. Calls GV5/STAT-COMMITTED.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/WRITE. Calls GV5/WRITE.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/INCF-NOHW-COUNTER. Increment by DELTA the slot NOHW-COUNTER of +gv+ and return its new value.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/START-READ. Return the current +gv+ value.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/START-WRITE. Return (1+ +gv+) without incrementing it.
global-clock.lisp (file)
This is GV5 implementation of GV5/STAT-ABORTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV5 implementation of GV5/STAT-COMMITTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/AFTER-ABORT. Calls GV5/AFTER-ABORT.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/START-READ. Calls GV5/START-READ.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/START-WRITE. Calls GV5/START-WRITE.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/STAT-ABORTED. Calls GV5/STAT-ABORTED.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/STAT-COMMITTED. Calls GV5/STAT-COMMITTED.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/WRITE. Calls GV5/WRITE.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/VALID-READ? Return (<= tvar-version read-version)
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/{HW,SW}/WRITE. Return WRITE-VERSION.
global-clock.lisp (file)
Return T if GV6 is currently in GV5 mode, i.e. it allows HW transactions. Return NIL if GV6 is currently in GV1 mode, i.e. it forbids HW transactions.
global-clock.lisp (file)
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/DECF-NOHW-COUNTER. Calls (GV5/DECF-NOHW-COUNTER).
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/FEATURES.
Return ’(:SUITABLE-FOR-HW-TRANSACTIONS :SPURIOUS-FAILURES-IN-SINGLE-THREAD)
just like GV5 because the global clock is based on GV5: it is usually not
incremented by GV6/START-WRITE, to prevent hardware transactions from
conflicting with each other.
This can cause very high abort rates of software transactions, so
GV6 adaptively switches to GV1 algorithm in the following cases:
a) software-only commits are in progress
b) abort rate is very high
in order to try to reduce the abort rates.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/GET-NOHW-COUNTER.
Return LOGIOR of two quantities:
1. (GV5/GET-NOHW-COUNTER)
2. the global-clock slot NOHW-FLAG
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/HW/AFTER-ABORT.
Calls (GV5/AFTER-ABORT), since GV1 mode forbids hardware transactions.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/HW/START-READ.
Calls (GV5/HW/START-READ), since GV1 mode forbids hardware transactions.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/HW/START-WRITE.
Calls (GV5/HW/START-WRITE), since GV1 mode forbids hardware transactions.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/HW/STAT-ABORTED.
It increases local-clock slot ABORTS and may decide to switch between GV1 and GV5 modes.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/HW/STAT-COMMITTED.
It increases local-clock slot COMMITS and may decide to switch between GV1 and GV5 modes.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/SW/WRITE.
Calls (GV5/HW/START-WRITE), since GV1 mode forbids hardware transactions.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/INCF-NOHW-COUNTER. Calls (GV5/INCF-NOHW-COUNTER).
global-clock.lisp (file)
This is GV6 implementation of GV6/STAT-ABORTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV6 implementation of GV6/STAT-COMMITTED. It does nothing and returns zero.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/SW/AFTER-ABORT.
Calls either (GV5/AFTER-ABORT) or (GV1/AFTER-ABORT), depending on the current mode.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/SW/START-READ.
Calls either (GV5/SW/START-READ) or (GV1/SW/START-READ), depending on the current mode.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/SW/START-WRITE.
Calls either (GV5/START-WRITE) or (GV1/START-WRITE), depending on the current mode.
global-clock.lisp (file)
This is GV5 implementation of GLOBAL-CLOCK/SW/STAT-ABORTED.
It increases local-clock slot ABORTS and may decide to switch between GV1 and GV5 modes.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/SW/STAT-COMMITTED.
It increases local-clock slot COMMITS and may decide to switch between GV1 and GV5 modes.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/HW/WRITE.
Calls either (GV5/SW/WRITE) or (GV1/WRITE), depending on the current mode.
global-clock.lisp (file)
This is GV6 implementation of GLOBAL-CLOCK/VALID-READ? Return (<= tvar-version read-version)
global-clock.lisp (file)
global-clock.lisp (file)
Return the WRITE-VERSION for the current hardware transaction
classes.lisp (file)
hash-table.lisp (file)
classes.lisp (file)
optimize-for.lisp (file)
Return the raw tvar stored in a transactional slot.
tslot.lisp (file)
Run BODY in a software memory transaction. All changes to transactional memory
will be visible to other threads only after BODY returns normally (commits).
If BODY signals an error, its effects on transactional memory are rolled back
and the error is propagated normally.
Also, no work-in-progress transactional memory will ever be visible to other
threads.
sw-atomic.lisp (file)
Immediately abort a hardware memory transaction with a user-specified
ERR-CODE, which must be a constant between 0 and 255 (default: 1).
Note: the value returned by (transaction-begin) will also contain "somewhere"
the bits of ERR-CODE, but will have a different value.
See Intel x86-64 CPU instruction reference manual, section TSX, for details.
If a transaction is in progress, TRANSACTION-ABORT-MACRO does not return normally:
execution is resumed at the instruction immediately after the outermost
TRANSACTION-BEGIN.
If called without a running transaction, TRANSACTION-ABORT-MACRO returns normally with an implementation-dependent value.
transaction.lisp (file)
tvar-fwd.lisp (file)
tclass.lisp (file)
tclass.lisp (file)
Return T if $-hwtx and (setf $-hwtx) should be used, otherwise return NIL.
Return T if $-swtx and (setf $-swtx) should be used, otherwise return NIL.
optimize-for.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
Enable recording of reads and writes to TLOGs while executing BODY.
classes.lisp (file)
Use LOG as the current transaction log and enable recording of transactions to TLOGs while executing BODY.
classes.lisp (file)
optimize-for.lisp (file)
Use LOG as the current software transaction log while executing BODY.
classes.lisp (file)
optimize-for.lisp (file)
Disable recording of transactions to TLOGs and disable hiding TVARs inside TOBJs slots while executing BODY.
classes.lisp (file)
Next: Internal generic functions, Previous: Internal macros, Up: Internal definitions [Contents][Index]
Get the value from the transactional variable VAR and return it.
Return +unbound-tvar+ if VAR is not bound to a value.
Works ONLY outside memory transactions.
tvar.lisp (file)
(setf $-notx) (setf expander)
tvar.lisp (file)
$-notx (function)
set-$-notx (function)
Get the value from the transactional variable VAR and return it.
Return +unbound-tvar+ if VAR is not bound to a value.
Works ONLY inside software memory transactions.
tvar.lisp (file)
(setf $-swtx) (setf expander)
tcons-alist.lisp (file)
features-reader.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
tstruct.lisp (file)
atomic-counter.lisp (file)
fast-vector.lisp (file)
mutex.lisp (file)
classes.lisp (file)
classes.lisp (file)
Rebalance red-black tree after adding a child to (first stack).
Return (values node stack) for some rebalanced node and its path from root.
If stack is nil, returned node is the new root to set.
rbmap.lisp (file)
Remove (first stack) from red-black tree M and return (values some-node that-node-stack) from rebalanced tree. Some-node will be nil only if the tree is empty after removal.
rbmap.lisp (file)
Remove from red-black tree M black leaf NODE, whose path is STACK. Return some node in rebalanced tree and its stack as multiple values
rbmap.lisp (file)
Function equivalent of the SW-ATOMIC macro.
Run the function TX inside a transaction.
If the transaction is invalid (conflicts) re-run TX immediately, ignoring
any error it may signal.
Otherwise, commit if TX returns normally, or rollback if it signals an error.
Finally, if TX called (retry), re-run it after at least some of the transactional memory it read has changed.
sw-atomic.lisp (file)
tvar-slot.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tvar-slot.lisp (file)
(setf %stmx-impl/notx/$-slot) (setf expander)
tvar-slot.lisp (file)
%stmx-impl/notx/$-slot (function)
tvar-slot.lisp (file)
tvar-slot.lisp (file)
simple-tvector.lisp (file)
tcons.lisp (file)
(setf %stmx-impl/notx/tcar) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/tcar (function)
tcons.lisp (file)
(setf %stmx-impl/notx/tcdr) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/tcdr (function)
tcons.lisp (file)
(setf %stmx-impl/notx/tcons-first) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/tcons-first (function)
tcons.lisp (file)
(setf %stmx-impl/notx/tcons-rest) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/tcons-rest (function)
tcons.lisp (file)
(setf %stmx-impl/notx/tfirst) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/tfirst (function)
tcons.lisp (file)
(setf %stmx-impl/notx/trest) (setf expander)
tcons.lisp (file)
%stmx-impl/notx/trest (function)
tcons.lisp (file)
tcons.lisp (file)
tvar-slot.lisp (file)
tvar-slot.lisp (file)
simple-tvector.lisp (file)
tvar-slot.lisp (file)
tvar-slot.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tvar-slot.lisp (file)
(setf %stmx-impl/swtx/$-slot) (setf expander)
tvar-slot.lisp (file)
%stmx-impl/swtx/$-slot (function)
tvar-slot.lisp (file)
tvar-slot.lisp (file)
simple-tvector.lisp (file)
tcons.lisp (file)
(setf %stmx-impl/swtx/tcar) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/tcar (function)
tcons.lisp (file)
(setf %stmx-impl/swtx/tcdr) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/tcdr (function)
tcons.lisp (file)
(setf %stmx-impl/swtx/tcons-first) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/tcons-first (function)
tcons.lisp (file)
(setf %stmx-impl/swtx/tcons-rest) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/tcons-rest (function)
tcons.lisp (file)
(setf %stmx-impl/swtx/tfirst) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/tfirst (function)
tcons.lisp (file)
(setf %stmx-impl/swtx/trest) (setf expander)
tcons.lisp (file)
%stmx-impl/swtx/trest (function)
tcons.lisp (file)
tcons.lisp (file)
tvar-slot.lisp (file)
tvar-slot.lisp (file)
simple-tvector.lisp (file)
tvar-slot.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
tvar-slot.lisp (file)
Set VALUE as the first element in a TCONS or non-null TLIST. This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
Set VALUE as the rest element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
tcons.lisp (file)
tcons.lisp (file)
Set VALUE as the first element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
Set VALUE as the rest element in a TCONS or non-null TLIST.
This function should always be executed inside an STMX atomic block.
tcons.lisp (file)
tcons-list.lisp (file)
tcons-list.lisp (file)
Internal function used only by TVAR-VALUE-AND-VERSION-OR-FAIL.
tvar-fwd.lisp (file)
Add VALUE to bheap Q. Return VALUE.
bheap.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
txhash.lisp (file)
Adjust a single slot definition for a transactional class.
Unless the slot is defined as :transactional NIL,
wrap its :initform with a TVAR and alter its :type to also accept TVARs
tclass.lisp (file)
Adjust each slot definition for a transactional class:
unless a slot is defined as :transactional NIL, wrap its :initform with a TVAR
and alter its :type to also accept TVARs
tclass.lisp (file)
atomic-counter.lisp (file)
atomic-counter.lisp (file)
Return a form suitable for MACROLET
optimize-for.lisp (file)
Return t if NODE is black. Nil nodes are assumed to be black
rbmap.lisp (file)
tclass.lisp (file)
tclass.lisp (file)
tclass.lisp (file)
Remove all values from bheap Q. Return Q.
bheap.lisp (file)
Remove all features from *FEATURE-LIST*.
features.lisp (file)
Remove all transactional reads and writes stored in LOG,
as well as functions registered with BEFORE-COMMIT and AFTER-COMMIT;
return LOG itself.
txhash.lisp (file)
Remove all keys and values from HASH. Return HASH.
txhash.lisp (file)
class-precedence-list.lisp (file)
class-precedence-list.lisp (file)
class-precedence-list.lisp (file)
Commit a TLOG to memory.
It returns a boolean specifying whether or not the transaction
log was committed. If the transaction log cannot be committed
it either means that:
a) the TLOG is invalid - then the whole transaction must be re-executed
b) another TLOG is writing the same TVARs being committed
so that TVARs locks could not be aquired - also in this case
the whole transaction will be re-executed, as there is little hope
that the TLOG will still be valid.
Note: internally invokes GLOBAL-CLOCK/{HW,SW}/STAT-{COMMITTED,ABORTED}
commit.lisp (file)
Commit LOG into its parent log; return LOG.
Unlike (commit log), this function is guaranteed to always succeed.
Implementation note: copy tlog-reads, tlog-writes, tlog-before-commit and tlog-after-commit into parent, or swap them with parent
commit.lisp (file)
Actually COMMIT, i.e. write new values into TVARs. Also unlock all TVARs.
commit.lisp (file)
Compare entries at positions N1 and N2 in bqueue Q.
bheap.lisp (file)
Compare KEY1 agains KEY2 using the comparison function PRED.
Return K< if KEY1 compares as lesser than KEY2,
return K> if KEY1 compares as greater than KEY2,
return K= if KEY1 and KEY2 compare as equal.
features-reader.lisp (file)
features-reader.lisp (file)
Return T if all the features in ARGS are present in *FEATURE-LIST*, otherwise return NIL.
features-reader.lisp (file)
Return T if feature has the specified value, otherwise return NIL.
features-reader.lisp (file)
features-reader.lisp (file)
features-reader.lisp (file)
Return NIL if the feature in ARGS is present in *FEATURE-LIST*, otherwise return T.
features-reader.lisp (file)
Return T if at least one feature in ARGS is present in *FEATURE-LIST*, otherwise return NIL.
features-reader.lisp (file)
compiler.lisp (file)
compiler.lisp (file)
Return T if symbol exists in specified package, otherwise return NIL. Arguments are: package-name symbol-name.
features-reader.lisp (file)
features-reader.lisp (file)
print.lisp (file)
atomic-counter.lisp (file)
fast-vector.lisp (file)
Return a copy of ghash-table HASH.
The copy will have the same class, test and hash functions, and elements.
ghash-table.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
mutex.lisp (file)
orelse.lisp (file)
tclass.lisp (file)
tcons.lisp (file)
Return a new tlist which has the same elements as TLIST. TLIST may be improper.
tcons-list.lisp (file)
classes.lisp (file)
tstruct.lisp (file)
tstruct.lisp (file)
Recursively copy trees of TCONSes.
tcons-tree.lisp (file)
tvar-fwd.lisp (file)
classes.lisp (file)
classes.lisp (file)
Clear DST, then copy SRC contents into it. Return NIL.
txhash.lisp (file)
classes.lisp (file)
test for multi-threading support: :STMX/DISABLE-THREADS most not be present CL:*FEATURES*, BORDEAUX-THREADS:*SUPPORTS-THREADS-P* must be non-NIL, and (BT:MAKE-THREAD) and (BT:JOIN-THREAD) must work.
thread.lisp (file)
Return t if bheap Q is empty.
bheap.lisp (file)
Create tlog-after-commit log if nil, and return it.
commit.lisp (file)
Create tlog-before-commit log if nil, and return it.
commit.lisp (file)
Add TRANSACTIONAL-OBJECT as the first superclass of a transactional class if not already present in the superclass list.
tclass.lisp (file)
tclass.lisp (file)
Double the length of vector V, i.e. create a new larger vector
and copy elements from V to the new vector.
Return the new, larger vector.
This method exists to simplify the implementation of transactional priority queue TQUEUE: as long as bheap is concerned, (vector-push-extend ...) would be fine.
bheap.lisp (file)
optimize-for.lisp (file)
optimize-for.lisp (file)
fast-vector.lisp (file)
fast-vector.lisp (file)
fast-vector.lisp (file)
fast-vector.lisp (file)
fast-vector.lisp (file)
tclass.lisp (file)
Return index of the first tx that wants to rerun or is invalid. Return nil if all tx are valid and want to retry.
orelse.lisp (file)
If KEY is present in HASH, return the GHASH-PAIR containing KEY. Otherwise return NIL.
ghash-table.lisp (file)
Return stack of visited nodes from root to insertion point for KEY, and comparison between the KEY to insert and last visited node’s key, as multiple values
tclass.lisp (file)
tclass.lisp (file)
If KEY is present in HASH, return the TXPAIR containing KEY. Otherwise return NIL.
txhash.lisp (file)
Flip NODE color. Return the new color.
rbmap.lisp (file)
Return a no-longer-needed TLOG to the pool.
Return to TLOG pool all logs contained in TXS
orelse.lisp (file)
Return the first value in bheap Q without removing it, and t as multiple values. Return (values DEFAULT nil) if Q contains no values.
bheap.lisp (file)
tvar-fwd.lisp (file)
If KEY is associated to VALUE in HASH, return (values VALUE t) Otherwise return (values DEFAULT nil).
txhash.lisp (file)
Return the bitmask to use for hash indexes.
ghash-table.lisp (file)
Return the array subscript in HASH corresponding to HASH-CODE.
ghash-table.lisp (file)
Return T if ghash-table HASH contains at most COUNT key/value entries.
ghash-table.lisp (file)
Return T if ghash-table HASH contains more than COUNT key/value entries.
ghash-table.lisp (file)
Publish (GLOBAL-CLOCK/FEATURES) to stmx.lang::*feature-list* so they can be tested with #?+ and #?- reader macros.
global-clock.lisp (file)
Return T if gmap M contains at most COUNT key/value entries.
Return T if ghash-table HASH contains more than COUNT key/value entries.
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)
global-clock.lisp (file)